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

commit/galaxy-central: jgoecks: Fix Trackster bug and remove debugging code. Pack scripts.
by Bitbucket 02 Jul '12
by Bitbucket 02 Jul '12
02 Jul '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/05f25cefa175/
changeset: 05f25cefa175
user: jgoecks
date: 2012-07-02 15:02:58
summary: Fix Trackster bug and remove debugging code. Pack scripts.
affected #: 4 files
diff -r 9b7cf76169b41729ee6253d9722145347e9f5213 -r 05f25cefa1751a165d76882919ba3f7ecafe0bb1 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 class_module=function(b,a){var c=function(){var g=arguments[0];for(var f=1;f<arguments.length;f++){var d=arguments[f];for(var e in d){g[e]=d[e]}}return g};a.extend=c};var requestAnimationFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b,a){window.setTimeout(b,1000/60)}})();var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=BEFORE}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var is_deferred=function(a){if(a==="pending"){console.log("pending")}return("isResolved" in a)};var get_random_color=function(a){if(!a){a="#ffffff"}if(typeof(a)==="string"){a=[a]}for(var j=0;j<a.length;j++){a[j]=parseInt(a[j].slice(1),16)}var n=function(t,s,i){return((t*299)+(s*587)+(i*114))/1000};var e=function(v,u,w,s,i,t){return(Math.max(v,s)-Math.min(v,s))+(Math.max(u,i)-Math.min(u,i))+(Math.max(w,t)-Math.min(w,t))};var g,o,f,k,q,h,r,c,d,b,p,m=false,l=0;do{g=Math.round(Math.random()*16777215);o=(g&16711680)>>16;f=(g&65280)>>8;k=g&255;d=n(o,f,k);m=true;for(j=0;j<a.length;j++){q=a[j];h=(q&16711680)>>16;r=(q&65280)>>8;c=q&255;b=n(h,r,c);p=e(o,f,k,h,r,c);if((Math.abs(d-b)<40)||(p<200)){m=false;break}}l++}while(!m&&l<=10);return"#"+(16777216+g).toString(16).substr(1,6)};var create_action_icon=function(c,b,a){return $("<a/>").attr("href","javascript:void(0);").attr("title",c).addClass("icon-button").addClass(b).tipsy({gravity:"s"}).click(a)};var trackster_module=function(d,R){var o=d("class").extend,r=d("slotting"),H=d("painters");var m={};var k=function(Y,Z){m[Y.attr("id")]=Z};var l=function(Y,aa,ac,ab){ac=".group";var Z={};m[Y.attr("id")]=ab;Y.bind("drag",{handle:"."+aa,relative:true},function(ak,al){var aj=$(this),ao=$(this).parent(),ag=ao.children(),ai=m[$(this).attr("id")],af,ae,am,ad,ah;ae=$(this).parents(ac);if(ae.length!==0){am=ae.position().top;ad=am+ae.outerHeight();if(al.offsetY<am){$(this).insertBefore(ae);var an=m[ae.attr("id")];an.remove_drawable(ai);an.container.add_drawable_before(ai,an);return}else{if(al.offsetY>ad){$(this).insertAfter(ae);var an=m[ae.attr("id")];an.remove_drawable(ai);an.container.add_drawable(ai);return}}}ae=null;for(ah=0;ah<ag.length;ah++){af=$(ag.get(ah));am=af.position().top;ad=am+af.outerHeight();if(af.is(ac)&&this!==af.get(0)&&al.offsetY>=am&&al.offsetY<=ad){if(al.offsetY-am<ad-al.offsetY){af.find(".content-div").prepend(this)}else{af.find(".content-div").append(this)}if(ai.container){ai.container.remove_drawable(ai)}m[af.attr("id")].add_drawable(ai);return}}for(ah=0;ah<ag.length;ah++){af=$(ag.get(ah));if(al.offsetY<af.position().top&&!(af.hasClass("reference-track")||af.hasClass("intro"))){break}}if(ah===ag.length){if(this!==ag.get(ah-1)){ao.append(this);m[ao.attr("id")].move_drawable(ai,ah)}}else{if(this!==ag.get(ah)){$(this).insertBefore(ag.get(ah));m[ao.attr("id")].move_drawable(ai,(al.deltaY>0?ah-1:ah))}}}).bind("dragstart",function(){Z["border-top"]=Y.css("border-top");Z["border-bottom"]=Y.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(Z)})};R.moveable=l;var X=16,C=9,z=20,w=100,E=12000,O=400,G=5000,t=100,n="There was an error in indexing this dataset. ",F="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",A="No data for this chrom/contig.",s="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",u="Tool cannot be rerun: ",a="Loading data...",S="Ready for display",M=10,D=20;function T(Z,Y){if(!Y){Y=0}var aa=Math.pow(10,Y);return Math.round(Z*aa)/aa}var p=function(Z,Y,ab){if(!p.id_counter){p.id_counter=0}this.id=p.id_counter++;this.name=ab.name;this.view=Z;this.container=Y;this.config=new B({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:ab.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=ab.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(ac){ac.stopPropagation()});var aa=this;this.container_div.hover(function(){aa.icons_div.show()},function(){aa.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};p.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(Y){if(Y.content_visible){Y.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");Y.hide_contents();Y.content_visible=false}else{Y.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");Y.content_visible=true;Y.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(Z){var ab=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},Y=function(){Z.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},aa=function(ac){if((ac.keyCode||ac.which)===27){ab()}else{if((ac.keyCode||ac.which)===13){Y()}}};$(window).bind("keypress.check_enter_esc",aa);show_modal("Configure",Z.config.build_form(),{Cancel:ab,OK:Y})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(Y){$(".tipsy").remove();Y.remove()}}];o(p.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(){},to_dict:function(){},set_name:function(Y){this.old_name=this.name;this.name=Y;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 Y=this.view;this.container_div.hide(0,function(){$(this).remove();Y.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(Z,ae,ad,ac,Y,ab){var aa=this;this.action_icons[Z]=$("<a/>").attr("href","javascript:void(0);").attr("title",ae).addClass("icon-button").addClass(ad).tipsy({gravity:"s"}).click(function(){ac(aa)}).appendTo(this.icons_div);if(ab){this.action_icons[Z].hide()}},build_action_icons:function(Y){var aa;for(var Z=0;Z<Y.length;Z++){aa=Y[Z];this.add_action_icon(aa.name,aa.title,aa.css_class,aa.on_click_fn,aa.prepend,aa.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){}});var v=function(Z,Y,aa){p.call(this,Z,Y,aa);this.obj_type=aa.obj_type;this.drawables=[]};o(v.prototype,p.prototype,{unpack_drawables:function(aa){this.drawables=[];var Z;for(var Y=0;Y<aa.length;Y++){Z=object_from_template(aa[Y],this);this.add_drawable(Z)}},init:function(){for(var Y=0;Y<this.drawables.length;Y++){this.drawables[Y].init()}},_draw:function(){for(var Y=0;Y<this.drawables.length;Y++){this.drawables[Y]._draw()}},to_dict:function(){var Z=[];for(var Y=0;Y<this.drawables.length;Y++){Z.push(this.drawables[Y].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:Z}},add_drawable:function(Y){this.drawables.push(Y);Y.container=this;this.changed()},add_drawable_before:function(aa,Y){this.changed();var Z=this.drawables.indexOf(Y);if(Z!==-1){this.drawables.splice(Z,0,aa);return true}return false},replace_drawable:function(aa,Y,Z){var ab=this.drawables.indexOf(aa);if(ab!==-1){this.drawables[ab]=Y;if(Z){aa.container_div.replaceWith(Y.container_div)}this.changed()}return ab},remove_drawable:function(Z){var Y=this.drawables.indexOf(Z);if(Y!==-1){this.drawables.splice(Y,1);Z.container=null;this.changed();return true}return false},move_drawable:function(Z,aa){var Y=this.drawables.indexOf(Z);if(Y!==-1){this.drawables.splice(Y,1);this.drawables.splice(aa,0,Z);this.changed();return true}return false}});var L=function(Z,Y,ab){o(ab,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});v.call(this,Z,Y,ab);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);k(this.container_div,this);k(this.content_div,this);l(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new U(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in ab){this.unpack_drawables(ab.drawables)}if("filters" in ab){var aa=this.filters_manager;this.filters_manager=new U(this,ab.filters);aa.parent_div.replaceWith(this.filters_manager.parent_div);if(ab.filters.visible){this.setup_multitrack_filtering()}}};o(L.prototype,p.prototype,v.prototype,{action_icons_def:[p.prototype.action_icons_def[0],p.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(Y){$(".tipsy").remove();Y.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(Y){if(Y.filters_manager.visible()){Y.filters_manager.clear_filters();Y._restore_filter_managers()}else{Y.setup_multitrack_filtering();Y.request_draw(true)}Y.filters_manager.toggle()}},p.prototype.action_icons_def[2]],build_container_div:function(){var Y=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(Y)}return Y},build_header_div:function(){var Y=$("<div/>").addClass("track-header");Y.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(Y);return Y},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var aa=this.drawables.length;if(aa===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(aa===1){if(this.drawables[0] instanceof g){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var ah,ag,ae,ak=true,ac=this.drawables[0].get_type(),Y=0;for(ah=0;ah<aa;ah++){ae=this.drawables[ah];if(ae.get_type()!==ac){can_composite=false;break}if(ae instanceof c){Y++}}if(ak||Y===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".tipsy").remove()}if(Y>1&&Y===this.drawables.length){var al={},Z;ae=this.drawables[0];for(ag=0;ag<ae.filters_manager.filters.length;ag++){Z=ae.filters_manager.filters[ag];al[Z.name]=[Z]}for(ah=1;ah<this.drawables.length;ah++){ae=this.drawables[ah];for(ag=0;ag<ae.filters_manager.filters.length;ag++){Z=ae.filters_manager.filters[ag];if(Z.name in al){al[Z.name].push(Z)}}}this.filters_manager.remove_all();var ab,ad,af,ai;for(var aj in al){ab=al[aj];if(ab.length===Y){ad=new P({name:ab[0].name,index:ab[0].index});this.filters_manager.add_filter(ad)}}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 Y=0;Y<this.drawables.length;Y++){this.drawables[Y].filters_manager=this.saved_filters_managers[Y]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var Y=0;Y<this.drawables.length;Y++){drawable=this.drawables[Y];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var ac=[];for(var Z=0;Z<this.drawables.length;Z++){ac.push(this.drawables[Z].name)}var aa="Composite Track of "+this.drawables.length+" tracks ("+ac.join(", ")+")";var ab=new g(this.view,this.view,{name:aa,drawables:this.drawables});var Y=this.container.replace_drawable(this,ab,true);ab.request_draw()},add_drawable:function(Y){v.prototype.add_drawable.call(this,Y);this.update_icons()},remove_drawable:function(Y){v.prototype.remove_drawable.call(this,Y);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var Y=o(v.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return Y},request_draw:function(Y,aa){for(var Z=0;Z<this.drawables.length;Z++){this.drawables[Z].request_draw(Y,aa)}}});var W=function(Y){o(Y,{obj_type:"View"});v.call(this,"View",Y.container,Y);this.chrom=null;this.vis_id=Y.vis_id;this.dbkey=Y.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.init();this.canvas_manager=new CanvasManager(this.container.get(0).ownerDocument);this.reset()};_.extend(W.prototype,Backbone.Events);o(W.prototype,v.prototype,{init:function(){this.requested_redraw=false;var aa=this.container,Y=this;this.top_container=$("<div/>").addClass("top-container").appendTo(aa);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(aa);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(aa);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.browser_content_div);this.content_div=this.viewport_container;k(this.viewport_container,Y);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var ab=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_datasets(add_datasets_url,add_track_async_url,function(ac){_.each(ac,function(ad){Y.add_drawable(object_from_template(ad,Y))})})});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").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var Z=function(ac){if(ac.type==="focusout"||(ac.keyCode||ac.which)===13||(ac.keyCode||ac.which)===27){if((ac.keyCode||ac.which)!==27){Y.go_to($(this).val())}$(this).hide();$(this).val("");Y.location_span.show();Y.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",Z).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").attr("original-title","Click to change location").tipsy({gravity:"n"}).appendTo(this.nav_controls);this.location_span.click(function(){Y.location_span.hide();Y.chrom_select.hide();Y.nav_input.val(Y.chrom+":"+Y.low+"-"+Y.high);Y.nav_input.css("display","inline-block");Y.nav_input.select();Y.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a/>").attr("id","zoom-out").attr("title","Zoom out").tipsy({gravity:"n"}).click(function(){Y.zoom_out();Y.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tipsy({gravity:"n"}).click(function(){Y.zoom_in();Y.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){Y.change_chrom(Y.chrom_select.val())});this.browser_content_div.click(function(ac){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ac){Y.zoom_in(ac.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ac,ad){this.current_x=ad.offsetX}).bind("drag",function(ac,ae){var af=ae.offsetX-this.current_x;this.current_x=ae.offsetX;var ad=Math.round(af/Y.viewport_container.width()*(Y.max_high-Y.max_low));Y.move_delta(-ad)});this.overview_close.click(function(){Y.reset_overview()});this.viewport_container.bind("draginit",function(ac,ad){if(ac.clientX>Y.viewport_container.width()-16){return false}}).bind("dragstart",function(ac,ad){ad.original_low=Y.low;ad.current_height=ac.clientY;ad.current_x=ad.offsetX}).bind("drag",function(ae,ag){var ac=$(this);var ah=ag.offsetX-ag.current_x;var ad=ac.scrollTop()-(ae.clientY-ag.current_height);ac.scrollTop(ad);ag.current_height=ae.clientY;ag.current_x=ag.offsetX;var af=Math.round(ah/Y.viewport_container.width()*(Y.high-Y.low));Y.move_delta(af)}).bind("mousewheel",function(ae,ag,ad,ac){if(ad){ad*=50;var af=Math.round(-ad/Y.viewport_container.width()*(Y.high-Y.low));Y.move_delta(af)}});this.top_labeltrack.bind("dragstart",function(ac,ad){return $("<div />").css({height:Y.browser_content_div.height()+Y.top_labeltrack.height()+Y.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ag,ah){$(ah.proxy).css({left:Math.min(ag.pageX,ah.startX)-Y.container.offset().left,width:Math.abs(ag.pageX-ah.startX)});var ad=Math.min(ag.pageX,ah.startX)-Y.container.offset().left,ac=Math.max(ag.pageX,ah.startX)-Y.container.offset().left,af=(Y.high-Y.low),ae=Y.viewport_container.width();Y.update_location(Math.round(ad/ae*af)+Y.low,Math.round(ac/ae*af)+Y.low)}).bind("dragend",function(ah,ai){var ad=Math.min(ah.pageX,ai.startX),ac=Math.max(ah.pageX,ai.startX),af=(Y.high-Y.low),ae=Y.viewport_container.width(),ag=Y.low;Y.low=Math.round(ad/ae*af)+ag;Y.high=Math.round(ac/ae*af)+ag;$(ai.proxy).remove();Y.request_redraw()});this.add_label_track(new V(this,{content_div:this.top_labeltrack}));this.add_label_track(new V(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){Y.resize_window()},500)});$(document).bind("redraw",function(){Y.redraw()});this.reset();$(window).trigger("resize")},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(Z,ab,Y,ac){if(this.timer){clearTimeout(this.timer)}if(ac){var aa=this;this.timer=setTimeout(function(){aa.trigger("navigate",Z+":"+ab+"-"+Y)},500)}else{view.trigger("navigate",Z+":"+ab+"-"+Y)}},update_location:function(Y,aa){this.location_span.text(commatize(Y)+" - "+commatize(aa));this.nav_input.val(this.chrom+":"+commatize(Y)+"-"+commatize(aa));var Z=view.chrom_select.val();if(Z!==""){this.trigger_navigate(Z,view.low,view.high,true)}},load_chroms:function(aa){aa.num=t;aa.dbkey=this.dbkey;var Y=this,Z=$.Deferred();$.ajax({url:chrom_url,data:aa,dataType:"json",success:function(ac){if(ac.chrom_info.length===0){alert("Invalid chromosome: "+aa.chrom);return}if(ac.reference){Y.add_label_track(new x(Y))}Y.chrom_data=ac.chrom_info;var af='<option value="">Select Chrom/Contig</option>';for(var ae=0,ab=Y.chrom_data.length;ae<ab;ae++){var ad=Y.chrom_data[ae].chrom;af+='<option value="'+ad+'">'+ad+"</option>"}if(ac.prev_chroms){af+='<option value="previous">Previous '+t+"</option>"}if(ac.next_chroms){af+='<option value="next">Next '+t+"</option>"}Y.chrom_select.html(af);Y.chrom_start_index=ac.start_index;Z.resolve(ac)},error:function(){alert("Could not load chroms for this dbkey:",Y.dbkey)}});return Z},change_chrom:function(ad,Z,af){var aa=this;if(!aa.chrom_data){aa.load_chroms_deferred.then(function(){aa.change_chrom(ad,Z,af)});return}if(!ad||ad==="None"){return}if(ad==="previous"){aa.load_chroms({low:this.chrom_start_index-t});return}if(ad==="next"){aa.load_chroms({low:this.chrom_start_index+t});return}var ae=$.grep(aa.chrom_data,function(ag,ah){return ag.chrom===ad})[0];if(ae===undefined){aa.load_chroms({chrom:ad},function(){aa.change_chrom(ad,Z,af)});return}else{if(ad!==aa.chrom){aa.chrom=ad;aa.chrom_select.val(aa.chrom);aa.max_high=ae.len-1;aa.reset();aa.request_redraw(true);for(var ac=0,Y=aa.drawables.length;ac<Y;ac++){var ab=aa.drawables[ac];if(ab.init){ab.init()}}if(aa.reference_track){aa.reference_track.init()}}if(Z!==undefined&&af!==undefined){aa.low=Math.max(Z,0);aa.high=Math.min(af,aa.max_high)}else{aa.low=0;aa.high=aa.max_high}aa.reset_overview();aa.request_redraw()}},go_to:function(ac){ac=ac.replace(/ |,/g,"");var ag=this,Y,ab,Z=ac.split(":"),ae=Z[0],af=Z[1];if(af!==undefined){try{var ad=af.split("-");Y=parseInt(ad[0],10);ab=parseInt(ad[1],10)}catch(aa){return false}}ag.change_chrom(ae,Y,ab)},move_fraction:function(aa){var Y=this;var Z=Y.high-Y.low;this.move_delta(aa*Z)},move_delta:function(ab){var Y=this;var aa=Y.high-Y.low;if(Y.low-ab<Y.max_low){Y.low=Y.max_low;Y.high=Y.max_low+aa}else{if(Y.high-ab>Y.max_high){Y.high=Y.max_high;Y.low=Y.max_high-aa}else{Y.high-=ab;Y.low-=ab}}Y.request_redraw();var Z=Y.chrom_select.val();this.trigger_navigate(Z,Y.low,Y.high,true)},add_drawable:function(Y){v.prototype.add_drawable.call(this,Y);Y.init();this.changed();this.update_intro_div()},add_label_track:function(Y){Y.view=this;Y.init();this.label_tracks.push(Y)},remove_drawable:function(aa,Z){v.prototype.remove_drawable.call(this,aa);if(Z){var Y=this;aa.container_div.hide(0,function(){$(this).remove();Y.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ag,Y,af,ah){var ae=this,ad=(ah?[ah]:ae.drawables),aa;var Z;for(var ac=0;ac<ad.length;ac++){Z=ad[ac];aa=-1;for(var ab=0;ab<ae.tracks_to_be_redrawn.length;ab++){if(ae.tracks_to_be_redrawn[ab][0]===Z){aa=ab;break}}if(aa<0){ae.tracks_to_be_redrawn.push([Z,Y,af])}else{ae.tracks_to_be_redrawn[ac][1]=Y;ae.tracks_to_be_redrawn[ac][2]=af}}if(!this.requested_redraw){requestAnimationFrame(function(){ae._redraw(ag)});this.requested_redraw=true}},_redraw:function(ai){this.requested_redraw=false;var af=this.low,ab=this.high;if(af<this.max_low){af=this.max_low}if(ab>this.max_high){ab=this.max_high}var ah=this.high-this.low;if(this.high!==0&&ah<this.min_separation){ab=af+this.min_separation}this.low=Math.floor(af);this.high=Math.ceil(ab);this.update_location(this.low,this.high);this.resolution_b_px=(this.high-this.low)/this.viewport_container.width();this.resolution_px_b=this.viewport_container.width()/(this.high-this.low);var Y=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ae=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var aj=13;this.overview_box.css({left:Y,width:Math.max(aj,ae)}).show();if(ae<aj){this.overview_box.css("left",Y-(aj-ae)/2)}if(this.overview_highlight){this.overview_highlight.css({left:Y,width:ae})}if(!ai){var aa,Z,ag;for(var ac=0,ad=this.tracks_to_be_redrawn.length;ac<ad;ac++){aa=this.tracks_to_be_redrawn[ac][0];Z=this.tracks_to_be_redrawn[ac][1];ag=this.tracks_to_be_redrawn[ac][2];if(aa){aa._draw(Z,ag)}}this.tracks_to_be_redrawn=[];for(ac=0,ad=this.label_tracks.length;ac<ad;ac++){this.label_tracks[ac]._draw()}}},zoom_in:function(Z,aa){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var ab=this.high-this.low,ac=ab/2+this.low,Y=(ab/this.zoom_factor)/2;if(Z){ac=Z/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ac-Y);this.high=Math.round(ac+Y);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var Z=this.high-this.low,aa=Z/2+this.low,Y=(Z*this.zoom_factor)/2;this.low=Math.round(aa-Y);this.high=Math.round(aa+Y);this.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(aa){if(this.overview_drawable){if(this.overview_drawable.dataset_id===aa.dataset_id){return}this.overview_viewport.find(".track").remove()}var Z=aa.copy({content_div:this.overview_viewport}),Y=this;Z.header_div.hide();Z.is_overview=true;Y.overview_drawable=Z;this.overview_drawable.postdraw_actions=function(){Y.overview_highlight.show().height(Y.overview_drawable.content_div.height());Y.overview_viewport.height(Y.overview_drawable.content_div.height()+Y.overview_box.outerHeight());Y.overview_close.show();Y.resize_window()};Y.overview_drawable.request_draw();this.changed()},reset_overview:function(){$(".tipsy").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 q=function(aa,af,ab){this.track=aa;this.name=af.name;this.params=[];var am=af.params;for(var ac=0;ac<am.length;ac++){var ah=am[ac],Z=ah.name,al=ah.label,ad=unescape(ah.html),an=ah.value,aj=ah.type;if(aj==="number"){this.params.push(new e(Z,al,ad,(Z in ab?ab[Z]:an),ah.min,ah.max))}else{if(aj==="select"){this.params.push(new J(Z,al,ad,(Z in ab?ab[Z]:an)))}else{console.log("WARNING: unrecognized tool parameter type:",Z,aj)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(ap){ap.stopPropagation()}).click(function(ap){ap.stopPropagation()}).bind("dblclick",function(ap){ap.stopPropagation()});var ak=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var ai=this.params;var ag=this;$.each(this.params,function(aq,au){var at=$("<div>").addClass("param-row").appendTo(ag.parent_div);var ap=$("<div>").addClass("param-label").text(au.label).appendTo(at);var ar=$("<div/>").addClass("param-input").html(au.html).appendTo(at);ar.find(":input").val(au.value);$("<div style='clear: both;'/>").appendTo(at)});this.parent_div.find("input").click(function(){$(this).select()});var ao=$("<div>").addClass("param-row").appendTo(this.parent_div);var ae=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(ao);var Y=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(ao);Y.click(function(){ag.run_on_region()});ae.click(function(){ag.run_on_dataset()});if("visible" in ab&&ab.visible){this.parent_div.show()}};o(q.prototype,{update_params:function(){for(var Y=0;Y<this.params.length;Y++){this.params[Y].update_value()}},state_dict:function(){var Z={};for(var Y=0;Y<this.params.length;Y++){Z[this.params[Y].name]=this.params[Y].value}Z.visible=this.parent_div.is(":visible");return Z},get_param_values_dict:function(){var Y={};this.parent_div.find(":input").each(function(){var Z=$(this).attr("name"),aa=$(this).val();Y[Z]=aa});return Y},get_param_values:function(){var Y=[];this.parent_div.find(":input").each(function(){var Z=$(this).attr("name"),aa=$(this).val();if(Z){Y[Y.length]=aa}});return Y},run_on_dataset:function(){var Y=this;Y.run({target_dataset_id:this.track.original_dataset_id,tool_id:Y.name},null,function(Z){show_modal(Y.name+" is Running",Y.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var Z={target_dataset_id:this.track.original_dataset_id,action:"rerun",tool_id:this.name,regions:[{chrom:this.track.view.chrom,start:this.track.view.low,end:this.track.view.high}]},ad=this.track,aa=Z.tool_id+ad.tool_region_and_parameters_str(Z.chrom,Z.low,Z.high),Y;if(ad.container===view){var ac=new L(view,view,{name:this.name});var ab=ad.container.replace_drawable(ad,ac,false);ac.container_div.insertBefore(ad.view.content_div.children()[ab]);ac.add_drawable(ad);ad.container_div.appendTo(ac.content_div);Y=ac}else{Y=ad.container}var ae=new ad.constructor(view,Y,{name:aa,hda_ldda:"hda"});ae.init_for_tool_data();ae.change_mode(ad.mode);ae.set_filters_manager(ad.filters_manager.copy(ae));ae.update_icons();Y.add_drawable(ae);ae.tiles_div.text("Starting job.");this.update_params();this.run(Z,ae,function(af){ae.set_dataset(new Dataset(af));ae.tiles_div.text("Running job.");ae.init()})},run:function(Y,aa,ab){Y.inputs=this.get_param_values_dict();var Z=new ServerStateDeferred({ajax_settings:{url:galaxy_paths.get("tool_url"),data:JSON.stringify(Y),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ac){return ac!=="pending"}});$.when(Z.go()).then(function(ac){if(ac==="no converter"){aa.container_div.addClass("error");aa.content_div.text(F)}else{if(ac.error){aa.container_div.addClass("error");aa.content_div.text(u+ac.message)}else{ab(ac)}}})}});var J=function(Z,Y,aa,ab){this.name=Z;this.label=Y;this.html=$(aa);this.value=ab};o(J.prototype,{update_value:function(){this.value=$(this.html).val()}});var e=function(aa,Z,ac,ad,ab,Y){J.call(this,aa,Z,ac,ad);this.min=ab;this.max=Y};o(e.prototype,J.prototype,{update_value:function(){J.prototype.update_value.call(this);this.value=parseFloat(this.value)}});var f=function(Y){this.manager=null;this.name=Y.name;this.index=Y.index;this.tool_id=Y.tool_id;this.tool_exp_name=Y.tool_exp_name};o(f.prototype,{to_dict:function(){return{name:this.name,index:this.index,tool_id:this.tool_id,tool_exp_name:this.tool_exp_name}}});var P=function(ah){f.call(this,ah);this.low=("low" in ah?ah.low:-Number.MAX_VALUE);this.high=("high" in ah?ah.high:Number.MAX_VALUE);this.min=("min" in ah?ah.min:Number.MAX_VALUE);this.max=("max" in ah?ah.max:-Number.MAX_VALUE);this.container=null;this.slider=null;this.slider_label=null;var ad=function(ai,aj,ak){ai.click(function(){var ap=aj.text(),an=parseFloat(ak.slider("option","max")),am=(an<=1?4:an<=1000000?an.toString().length:6),ao=false,al=$(this).parents(".slider-row");al.addClass("input");if(ak.slider("option","values")){am=2*am+1;ao=true}aj.text("");$("<input type='text'/>").attr("size",am).attr("maxlength",am).attr("value",ap).appendTo(aj).focus().select().click(function(aq){aq.stopPropagation()}).blur(function(){$(this).remove();aj.text(ap);al.removeClass("input")}).keyup(function(av){if(av.keyCode===27){$(this).trigger("blur")}else{if(av.keyCode===13){var at=ak.slider("option","min"),aq=ak.slider("option","max"),au=function(aw){return(isNaN(aw)||aw>aq||aw<at)},ar=$(this).val();if(!ao){ar=parseFloat(ar);if(au(ar)){alert("Parameter value must be in the range ["+at+"-"+aq+"]");return $(this)}}else{ar=ar.split("-");ar=[parseFloat(ar[0]),parseFloat(ar[1])];if(au(ar[0])||au(ar[1])){alert("Parameter value must be in the range ["+at+"-"+aq+"]");return $(this)}}ak.slider((ao?"values":"value"),ar);al.removeClass("input")}}})})};var Z=this;Z.parent_div=$("<div/>").addClass("filter-row slider-row");var Y=$("<div/>").addClass("elt-label").appendTo(Z.parent_div),af=$("<span/>").addClass("slider-name").text(Z.name+" ").appendTo(Y),aa=$("<span/>").text(this.low+"-"+this.high),ab=$("<span/>").addClass("slider-value").appendTo(Y).append("[").append(aa).append("]");Z.values_span=aa;var ae=$("<div/>").addClass("slider").appendTo(Z.parent_div);Z.control_element=$("<div/>").attr("id",Z.name+"-filter-control").appendTo(ae);var ac=[0,0];Z.control_element.slider({range:true,min:this.min,max:this.max,step:this.get_slider_step(this.min,this.max),values:[this.low,this.high],slide:function(ai,aj){Z.slide(ai,aj)},change:function(ai,aj){Z.control_element.slider("option","slide").call(Z.control_element,ai,aj)}});Z.slider=Z.control_element;Z.slider_label=aa;ad(ab,aa,Z.control_element);var ag=$("<div/>").addClass("display-controls").appendTo(Z.parent_div);this.transparency_icon=create_action_icon("Use filter for data transparency","layer-transparent",function(){if(Z.manager.alpha_filter!==Z){Z.manager.alpha_filter=Z;Z.manager.parent_div.find(".layer-transparent").removeClass("active").hide();Z.transparency_icon.addClass("active").show()}else{Z.manager.alpha_filter=null;Z.transparency_icon.removeClass("active")}Z.manager.track.request_draw(true,true)}).appendTo(ag).hide();this.height_icon=create_action_icon("Use filter for data height","arrow-resize-090",function(){if(Z.manager.height_filter!==Z){Z.manager.height_filter=Z;Z.manager.parent_div.find(".arrow-resize-090").removeClass("active").hide();Z.height_icon.addClass("active").show()}else{Z.manager.height_filter=null;Z.height_icon.removeClass("active")}Z.manager.track.request_draw(true,true)}).appendTo(ag).hide();Z.parent_div.hover(function(){Z.transparency_icon.show();Z.height_icon.show()},function(){if(Z.manager.alpha_filter!==Z){Z.transparency_icon.hide()}if(Z.manager.height_filter!==Z){Z.height_icon.hide()}});$("<div style='clear: both;'/>").appendTo(Z.parent_div)};o(P.prototype,{to_dict:function(){var Y=f.prototype.to_dict.call(this);return o(Y,{type:"number",min:this.min,max:this.max,low:this.low,high:this.high})},copy:function(){return new P({name:this.name,index:this.index,tool_id:this.tool_id,tool_exp_name:this.tool_exp_name})},get_slider_step:function(aa,Y){var Z=Y-aa;return(Z<=2?0.01:1)},slide:function(Z,aa){var Y=aa.values;this.values_span.text(Y[0]+"-"+Y[1]);this.low=Y[0];this.high=Y[1];this.manager.track.request_draw(true,true)},applies_to:function(Y){if(Y.length>this.index){return true}return false},_keep_val:function(Y){return(isNaN(Y)||(Y>=this.low&&Y<=this.high))},keep:function(Z){if(!this.applies_to(Z)){return true}var ab=this;var ac=Z[this.index];if(ac instanceof Array){var aa=true;for(var Y=0;Y<ac.length;Y++){if(!this._keep_val(ac[Y])){aa=false;break}}return aa}else{return this._keep_val(Z[this.index])}},update_attrs:function(ab){var Y=false;if(!this.applies_to(ab)){return Y}var Z=ab[this.index];if(!(Z instanceof Array)){Z=[Z]}for(var aa=0;aa<Z.length;aa++){var ac=Z[aa];if(ac<this.min){this.min=Math.floor(ac);Y=true}if(ac>this.max){this.max=Math.ceil(ac);Y=true}}return Y},update_ui_elt:function(){if(this.min<this.max){this.parent_div.show()}else{this.parent_div.hide()}var Z=this.slider.slider("option","min"),Y=this.slider.slider("option","max");if(this.min<Z||this.max>Y){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",this.get_slider_step(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var U=function(aa,ag){this.track=aa;this.alpha_filter=null;this.height_filter=null;this.filters=[];this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(ai){ai.stopPropagation()}).click(function(ai){ai.stopPropagation()}).bind("dblclick",function(ai){ai.stopPropagation()}).bind("keydown",function(ai){ai.stopPropagation()});if(ag&&"filters" in ag){var Y=("alpha_filter" in ag?ag.alpha_filter:null),ab=("height_filter" in ag?ag.height_filter:null),ad=ag.filters,Z;for(var ae=0;ae<ad.length;ae++){if(ad[ae].type==="number"){Z=new P(ad[ae]);this.add_filter(Z);if(Z.name===Y){this.alpha_filter=Z;Z.transparency_icon.addClass("active").show()}if(Z.name===ab){this.height_filter=Z;Z.height_icon.addClass("active").show()}}else{console.log("ERROR: unsupported filter: ",name,type)}}if("visible" in ag&&ag.visible){this.parent_div.show()}}if(this.filters.length!==0){var ah=$("<div/>").addClass("param-row").appendTo(this.parent_div);var af=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(ah);var ac=this;af.click(function(){ac.run_on_dataset()})}};o(U.prototype,{show:function(){this.parent_div.show()},hide:function(){this.parent_div.hide()},toggle:function(){this.parent_div.toggle()},visible:function(){return this.parent_div.is(":visible")},to_dict:function(){var ab={},aa=[],Z;for(var Y=0;Y<this.filters.length;Y++){Z=this.filters[Y];aa.push(Z.to_dict())}ab.filters=aa;ab.alpha_filter=(this.alpha_filter?this.alpha_filter.name:null);ab.height_filter=(this.height_filter?this.height_filter.name:null);ab.visible=this.parent_div.is(":visible");return ab},copy:function(Z){var aa=new U(Z);for(var Y=0;Y<this.filters.length;Y++){aa.add_filter(this.filters[Y].copy())}return aa},add_filter:function(Y){Y.manager=this;this.parent_div.append(Y.parent_div);this.filters.push(Y)},remove_all:function(){this.filters=[];this.parent_div.children().remove()},init_filters:function(){for(var Y=0;Y<this.filters.length;Y++){var Z=this.filters[Y];Z.update_ui_elt()}},clear_filters:function(){for(var Y=0;Y<this.filters.length;Y++){var Z=this.filters[Y];Z.slider.slider("option","values",[Z.min,Z.max])}this.alpha_filter=null;this.height_filter=null;this.parent_div.find(".icon-button").hide()},run_on_dataset:function(){var ae=function(ai,ag,ah){if(!(ag in ai)){ai[ag]=ah}return ai[ag]};var ad={},af,Y;for(var ac=0;ac<this.filters.length;ac++){af=this.filters[ac];if(af.tool_id){if(af.min!==af.low){Y=ae(ad,af.tool_id,[]);Y[Y.length]=af.tool_exp_name+" >= "+af.low}if(af.max!==af.high){Y=ae(ad,af.tool_id,[]);Y[Y.length]=af.tool_exp_name+" <= "+af.high}}}var Z=[];for(var ab in ad){Z[Z.length]=[ab,ad[ab]]}(function aa(am,aj){var ah=aj[0],ai=ah[0],al=ah[1],ak="("+al.join(") and (")+")",ag={cond:ak,input:am,target_dataset_id:am,tool_id:ai},aj=aj.slice(1);$.getJSON(run_tool_url,ag,function(an){if(an.error){show_modal("Filter Dataset","Error running tool "+ai,{Close:hide_modal})}else{if(aj.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{aa(an.dataset_id,aj)}}})})(this.track.dataset_id,Z)}});var y=function(Y,Z){H.Scaler.call(this,Z);this.filter=Y};y.prototype.gen_val=function(Y){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(Y[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var B=function(Y){this.track=Y.track;this.params=Y.params;this.values={};this.restore_values((Y.saved_values?Y.saved_values:{}));this.onchange=Y.onchange};o(B.prototype,{restore_values:function(Y){var Z=this;$.each(this.params,function(aa,ab){if(Y[ab.key]!==undefined){Z.values[ab.key]=Y[ab.key]}else{Z.values[ab.key]=ab.default_value}})},build_form:function(){var ab=this;var Y=$("<div />");var aa;function Z(af,ac){for(var aj=0;aj<af.length;aj++){aa=af[aj];if(aa.hidden){continue}var ad="param_"+aj;var an=ab.values[aa.key];var aq=$("<div class='form-row' />").appendTo(ac);aq.append($("<label />").attr("for",ad).text(aa.label+":"));if(aa.type==="bool"){aq.append($('<input type="checkbox" />').attr("id",ad).attr("name",ad).attr("checked",an))}else{if(aa.type==="text"){aq.append($('<input type="text"/>').attr("id",ad).val(an).click(function(){$(this).select()}))}else{if(aa.type==="select"){var al=$("<select />").attr("id",ad);for(var ah=0;ah<aa.options.length;ah++){$("<option/>").text(aa.options[ah].label).attr("value",aa.options[ah].value).appendTo(al)}al.val(an);aq.append(al)}else{if(aa.type==="color"){var ap=$("<div/>").appendTo(aq),ak=$("<input />").attr("id",ad).attr("name",ad).val(an).css("float","left").appendTo(ap).click(function(at){$(".tipsy").hide();var ar=$(this).siblings(".tipsy");ar.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(ar).height()/2)+($(this).height()/2)}).show();ar.click(function(au){au.stopPropagation()});$(document).bind("click.color-picker",function(){ar.hide();$(document).unbind("click.color-picker")});at.stopPropagation()}),ai=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(ap).attr("title","Set new random color").tipsy({gravity:"s"}),am=$("<div class='tipsy tipsy-west' style='position: absolute;' />").appendTo(ap).hide(),ae=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(am),ao=$("<div/>").appendTo(ae),ag=$.farbtastic(ao,{width:100,height:100,callback:ak,color:an});ap.append($("<div/>").css("clear","both"));(function(ar){ai.click(function(){ar.setColor(get_random_color())})})(ag)}else{aq.append($("<input />").attr("id",ad).attr("name",ad).val(an))}}}}if(aa.help){aq.append($("<div class='help'/>").text(aa.help))}}}Z(this.params,Y);return Y},update_from_form:function(Y){var aa=this;var Z=false;$.each(this.params,function(ab,ad){if(!ad.hidden){var ae="param_"+ab;var ac=Y.find("#"+ae).val();if(ad.type==="float"){ac=parseFloat(ac)}else{if(ad.type==="int"){ac=parseInt(ac)}else{if(ad.type==="bool"){ac=Y.find("#"+ae).is(":checked")}}}if(ac!==aa.values[ad.key]){aa.values[ad.key]=ac;Z=true}}});if(Z){this.onchange();this.track.changed()}}});var b=function(Y,ac,aa,Z,ab){this.track=Y;this.region=ac;this.low=ac.get("start");this.high=ac.get("end");this.resolution=aa;this.html_elt=$("<div class='track-tile'/>").append(Z).height($(Z).attr("height"));this.data=ab;this.stale=false};b.prototype.predisplay_actions=function(){};var j=function(Y,ad,aa,Z,ab,ac){b.call(this,Y,ad,aa,Z,ab);this.max_val=ac};o(j.prototype,b.prototype);var K=function(ab,aj,ac,aa,ae,al,af,am,Z,ai){b.call(this,ab,aj,ac,aa,ae);this.mode=af;this.all_slotted=Z;this.feature_mapper=ai;this.has_icons=false;if(am){this.has_icons=true;var ag=this;aa=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:z-1,width:aa.width}).prependTo(this.html_elt);var ah=new GenomeRegion({chrom:ab.view.chrom,start:this.low,end:this.high}),ak=ae.length,ad=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ak+" features in this region were obtained from server. Click to get more data including depth").tipsy({gravity:"s"}).appendTo(message_div),Y=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ak+" features in this region were obtained from server. Click to get more data excluding depth").tipsy({gravity:"s"}).appendTo(message_div);ad.click(function(){ag.stale=true;ab.data_manager.get_more_data(ah,ab.mode,ag.resolution,{},ab.data_manager.DEEP_DATA_REQ);$(".tipsy").hide();ab.request_draw(true)}).dblclick(function(an){an.stopPropagation()});Y.click(function(){ag.stale=true;ab.data_manager.get_more_data(ah,ab.mode,ag.resolution,{},ab.data_manager.BROAD_DATA_REQ);$(".tipsy").hide();ab.request_draw(true)}).dblclick(function(an){an.stopPropagation()})}};o(K.prototype,b.prototype);K.prototype.predisplay_actions=function(){var Z=this,Y={};if(Z.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(ak){if(!this.hovered){return}var af=$(this).offset(),aj=ak.pageX-af.left,ai=ak.pageY-af.top,ao=Z.feature_mapper.get_feature_data(aj,ai),ag=(ao?ao[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!ag||$(this).attr("id")!==ag.toString()){$(this).remove()}});if(ao){var ab=Y[ag];if(!ab){var ag=ao[0],al={name:ao[3],start:ao[1],end:ao[2],strand:ao[4]},ae=Z.track.filters_manager.filters,ad;for(var ah=0;ah<ae.length;ah++){ad=ae[ah];al[ad.name]=ao[ad.index]}var ab=$("<div/>").attr("id",ag).addClass("feature-popup"),ap=$("<table/>"),an,am,aq;for(an in al){am=al[an];aq=$("<tr/>").appendTo(ap);$("<th/>").appendTo(aq).text(an);$("<td/>").attr("align","left").appendTo(aq).text(typeof(am)==="number"?T(am,2):am)}ab.append($("<div class='feature-popup-inner'>").append(ap));Y[ag]=ab}ab.appendTo($(this).parents(".track-content").children(".overlay"));var ac=aj+parseInt(Z.html_elt.css("left"))-ab.width()/2,aa=ai+parseInt(Z.html_elt.css("top"))+7;ab.css("left",ac+"px").css("top",aa+"px")}else{if(!ak.isPropagationStopped()){ak.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ak)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var h=function(aa,Z,ac){o(ac,{drag_handle_class:"draghandle"});p.call(this,aa,Z,ac);this.data_url=("data_url" in ac?ac.data_url:default_data_url);this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in ac?ac.data_query_wait:G);this.dataset_check_url=("converted_datasets_state_url" in ac?ac.converted_datasets_state_url:converted_datasets_state_url);var Y=this,ab=new Dataset({id:ac.dataset_id,hda_ldda:ac.hda_ldda});this.data_manager=("data_manager" in ac?ac.data_manager:new GenomeDataManager({dataset:ab,data_url:Y.data_url,dataset_state_url:Y.dataset_check_url,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 ac)||ac.resize){this.add_resize_handle()}}};o(h.prototype,p.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},p.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(Y){Y.view.set_overview(Y)}},p.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(Y){if(Y.filters_manager.visible()){Y.filters_manager.clear_filters()}else{Y.filters_manager.init_filters()}Y.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(Y){Y.dynamic_tool_div.toggle();if(Y.dynamic_tool_div.is(":visible")){Y.set_name(Y.name+Y.tool_region_and_parameters_str())}else{Y.revert_name()}$(".tipsy").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(Y){var ab='<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>',aa=_.template(ab,{track:Y});var ad=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},Z=function(){var af=$('select[name="regions"] option:selected').val(),ah,ae=new GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),ag=_.map($(".bookmark"),function(ai){return new GenomeRegion({from_str:$(ai).children(".position").text()})});if(af==="cur"){ah=[ae]}else{if(af==="bookmarks"){ah=ag}else{ah=[ae].concat(ag)}}hide_modal();window.location.href=galaxy_paths.get("paramamonster_url")+"?"+$.param({dataset_id:Y.dataset_id,hda_ldda:Y.hda_ldda,regions:JSON.stringify(new Backbone.Collection(ah).toJSON())})},ac=function(ae){if((ae.keyCode||ae.which)===27){ad()}else{if((ae.keyCode||ae.which)===13){Z()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",aa,{No:ad,Yes:Z})}},p.prototype.action_icons_def[2]],can_draw:function(){if(this.dataset_id&&p.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 Y=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(Y)}this.name_div=$("<div/>").addClass("track-name").appendTo(Y).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return Y},on_resize:function(){},add_resize_handle:function(){var Y=this;var ab=false;var aa=false;var Z=$("<div class='track-resize'>");$(Y.container_div).hover(function(){if(Y.content_visible){ab=true;Z.show()}},function(){ab=false;if(!aa){Z.hide()}});Z.hide().bind("dragstart",function(ac,ad){aa=true;ad.original_height=$(Y.content_div).height()}).bind("drag",function(ad,ae){var ac=Math.min(Math.max(ae.original_height+ae.deltaY,Y.min_height_px),Y.max_height_px);$(Y.tiles_div).css("height",ac);Y.visible_height_px=(Y.max_height_px===ac?0:ac);Y.on_resize()}).bind("dragend",function(ac,ad){Y.tile_cache.clear();aa=false;if(!ab){Z.hide()}Y.config.values.height=Y.visible_height_px;Y.changed()}).appendTo(Y.container_div)},set_display_modes:function(ab,ae){this.display_modes=ab;this.mode=(ae?ae:(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 Z=this,ac={};for(var aa=0,Y=Z.display_modes.length;aa<Y;aa++){var ad=Z.display_modes[aa];ac[ad]=function(af){return function(){Z.change_mode(af);Z.icons_div.show();Z.container_div.mouseleave(function(){Z.icons_div.hide()})}}(ad)}make_popupmenu(this.action_icons.mode_icon,ac)},build_action_icons:function(){p.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 V){return"LabelTrack"}else{if(this instanceof x){return"ReferenceTrack"}else{if(this instanceof i){return"LineTrack"}else{if(this instanceof Q){return"ReadTrack"}else{if(this instanceof N){return"VcfTrack"}else{if(this instanceof g){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(){var Z=this;Z.enabled=false;Z.tile_cache.clear();Z.data_manager.clear();Z.content_div.css("height","auto");Z.tiles_div.children().remove();Z.container_div.removeClass("nodata error pending");if(!Z.dataset_id){return}var Y=$.Deferred();$.getJSON(this.dataset_check_url,{hda_ldda:Z.hda_ldda,dataset_id:Z.dataset_id,chrom:Z.view.chrom},function(aa){if(!aa||aa==="error"||aa.kind==="error"){Z.container_div.addClass("error");Z.tiles_div.text(n);if(aa.message){var ab=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+aa.message+"</pre>",{Close:hide_modal})});Z.tiles_div.append(ab)}}else{if(aa==="no converter"){Z.container_div.addClass("error");Z.tiles_div.text(F)}else{if(aa==="no data"||(aa.data!==undefined&&(aa.data===null||aa.data.length===0))){Z.container_div.addClass("nodata");Z.tiles_div.text(A)}else{if(aa==="pending"){Z.container_div.addClass("pending");Z.tiles_div.html(s);setTimeout(function(){Z.init()},Z.data_query_wait)}else{if(aa==="data"||aa.status==="data"){if(aa.valid_chroms){Z.valid_chroms=aa.valid_chroms;Z.update_icons()}Z.tiles_div.text(S);if(Z.view.chrom){Z.tiles_div.text("");Z.tiles_div.css("height",Z.visible_height_px+"px");Z.enabled=true;$.when(Z.predraw_init()).done(function(){Y.resolve();Z.container_div.removeClass("nodata error pending");Z.request_draw()})}else{Y.resolve()}}}}}}});this.update_icons();return Y},predraw_init:function(){}});var I=function(aa,Z,ab){h.call(this,aa,Z,ab);var Y=this,aa=Y.view;l(Y.container_div,Y.drag_handle_class,".group",Y);this.filters_manager=new U(this,("filters" in ab?ab.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=("tool" in ab&&ab.tool?new q(this,ab.tool,ab.tool_state):null);this.tile_cache=new Cache(M);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(ab.mode){this.change_mode(ab.mode)}};o(I.prototype,p.prototype,h.prototype,{action_icons_def:h.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(Y){$(".tipsy").remove();Y.slotters[Y.view.resolution_px_b].max_rows*=2;Y.request_draw(true)},hide:true}]),copy:function(Y){var Z=this.to_dict();o(Z,{data_manager:this.data_manager});var aa=new this.constructor(this.view,Y,Z);aa.change_mode(this.mode);aa.enabled=this.enabled;return aa},set_filters_manager:function(Y){this.filters_manager=Y;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},change_mode:function(Z){var Y=this;Y.mode=Z;Y.config.values.mode=Z;Y.tile_cache.clear();Y.request_draw();this.action_icons.mode_icon.attr("title","Set display mode (now: "+Y.mode+")");return Y},update_icons:function(){var Y=this;if(Y.filters_available){Y.action_icons.filters_icon.show()}else{Y.action_icons.filters_icon.hide()}if(Y.tool){Y.action_icons.tools_icon.show();Y.action_icons.param_space_viz_icon.show()}else{Y.action_icons.tools_icon.hide();Y.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(Z,aa,Y){return Z+"_"+aa+"_"+Y},request_draw:function(Z,Y){this.view.request_redraw(false,Z,Y,this)},before_draw:function(){},_draw:function(Z,aj){if(!this.can_draw()){return}var ah=this.view.low,ad=this.view.high,af=ad-ah,aa=this.view.container.width(),al=this.view.resolution_px_b,ac=this.view.resolution_b_px;if(this.is_overview){ah=this.view.max_low;ad=this.view.max_high;ac=Math.pow(RESOLUTION,Math.ceil(Math.log((view.max_high-view.max_low)/O)/Math.log(RESOLUTION)));al=aa/(view.max_high-view.max_low)}this.before_draw();this.tiles_div.children().addClass("remove");var Y=Math.floor(ah/(ac*O)),ag=true,ak=[],ae=function(am){return(am&&"track" in am)};while((Y*O*ac)<ad){var ai=this.draw_helper(Z,aa,Y,ac,this.tiles_div,al);if(ae(ai)){ak.push(ai)}else{ag=false}Y+=1}if(!aj){this.tiles_div.children(".remove").removeClass("remove").remove()}var ab=this;if(ag){this.tiles_div.children(".remove").remove();ab.postdraw_actions(ak,aa,al,aj)}},postdraw_actions:function(ab,ac,ae,Y){var aa=this;var ad=false;for(var Z=0;Z<ab.length;Z++){if(ab[Z].has_icons){ad=true;break}}if(ad){for(var Z=0;Z<ab.length;Z++){tile=ab[Z];if(!tile.has_icons){tile.html_elt.css("padding-top",z)}}}},draw_helper:function(Y,ak,ap,an,ad,ae,al){var aj=this,at=this._gen_tile_cache_key(ak,ae,ap),ab=this._get_tile_bounds(ap,an);if(!al){al={}}var ar=(Y?undefined:aj.tile_cache.get_elt(at));if(ar){aj.show_tile(ar,ad,ae);return ar}var ah=true;var ao=aj.data_manager.get_data(ab,aj.mode,an,aj.data_url_extra_params);if(is_deferred(ao)){ah=false}var af;if(view.reference_track&&ae>view.canvas_manager.char_width_px){af=view.reference_track.data_manager.get_data(ab,aj.mode,an,view.reference_track.data_url_extra_params);if(is_deferred(af)){ah=false}}if(ah){o(ao,al.more_tile_data);var ag=aj.mode;if(ag==="Auto"){ag=aj.get_mode(ao);aj.update_auto_mode(ag)}var aa=aj.view.canvas_manager.new_canvas(),aq=ab.get("start"),Z=ab.get("end"),ak=Math.ceil((Z-aq)*ae)+aj.left_offset,ai=aj.get_canvas_height(ao,ag,ae,ak);aa.width=ak;aa.height=ai;var am=aa.getContext("2d");am.translate(this.left_offset,0);var ar=aj.draw_tile(ao,am,ag,an,ab,ae,af);if(ar!==undefined){aj.tile_cache.set_elt(at,ar);aj.show_tile(ar,ad,ae)}return ar}var ac=$.Deferred();$.when(ao,af).then(function(){view.request_redraw(false,false,false,aj);ac.resolve()});return ac},get_canvas_height:function(Y,aa,ab,Z){return this.visible_height_px},draw_tile:function(Y,Z,ad,ab,ac,ae,aa){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(aa,ac,ad){var Z=this,Y=aa.html_elt;aa.predisplay_actions();var ab=(aa.low-(this.is_overview?this.view.max_low:this.view.low))*ad;if(this.left_offset){ab-=this.left_offset}Y.css({position:"absolute",top:0,left:ab});if(Y.hasClass("remove")){Y.removeClass("remove")}else{ac.append(Y)}Z.after_show_tile(aa)},after_show_tile:function(Y){},_get_tile_bounds:function(Y,Z){var ab=Math.floor(Y*O*Z),ac=Math.ceil(O*Z),aa=(ab+ac<=this.view.max_high?ab+ac:this.view.max_high);return new GenomeRegion({chrom:this.view.chrom,start:ab,end:aa})},tool_region_and_parameters_str:function(aa,Y,ab){var Z=this,ac=(aa!==undefined&&Y!==undefined&&ab!==undefined?aa+":"+Y+"-"+ab:"all");return" - region=["+ac+"], parameters=["+Z.tool.get_param_values().join(", ")+"]"},data_and_mode_compatible:function(Y,Z){return true},can_subset:function(Y){return false},init_for_tool_data:function(){this.data_manager.set("data_url",raw_data_url);this.data_query_wait=1000;this.dataset_check_url=dataset_state_url;this.normal_postdraw_actions=this.postdraw_actions;this.postdraw_actions=function(aa,ab,ad,Y){var Z=this;Z.normal_postdraw_actions(aa,ab,ad,Y);Z.dataset_state_url=converted_datasets_state_url;Z.data_query_wait=G;var ac=new ServerStateDeferred({url:Z.dataset_state_url,url_params:{dataset_id:Z.dataset_id,hda_ldda:Z.hda_ldda},interval:Z.data_query_wait,success_fn:function(ae){return ae!=="pending"}});$.when(ac.go()).then(function(){Z.data_manager.set("data_url",default_data_url)});Z.postdraw_actions=Z.normal_postdraw_actions}}});var V=function(Z,Y){var aa={resize:false};h.call(this,Z,Y,aa);this.container_div.addClass("label-track")};o(V.prototype,h.prototype,{build_header_div:function(){},init:function(){this.enabled=true},_draw:function(){var aa=this.view,ab=aa.high-aa.low,ae=Math.floor(Math.pow(10,Math.floor(Math.log(ab)/Math.log(10)))),Y=Math.floor(aa.low/ae)*ae,ac=this.view.container.width(),Z=$("<div style='position: relative; height: 1.3em;'></div>");while(Y<aa.high){var ad=(Y-aa.low)/ab*ac;Z.append($("<div class='label'>"+commatize(Y)+"</div>").css({position:"absolute",left:ad-1}));Y+=ae}this.content_div.children(":first").remove();this.content_div.append(Z)}});var g=function(Z,Y,ac){I.call(this,Z,Y,ac);this.drawables=[];this.left_offset=0;if("drawables" in ac){var ab;for(var aa=0;aa<ac.drawables.length;aa++){ab=ac.drawables[aa];this.drawables[aa]=object_from_template(ab);if(ab.left_offset>this.left_offset){this.left_offset=ab.left_offset}}this.enabled=true}if(this.drawables.length!==0){this.set_display_modes(this.drawables[0].display_modes,this.drawables[0].mode)}this.update_icons();this.obj_type="CompositeTrack"};o(g.prototype,I.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(Y){$(".tipsy").remove();Y.show_group()}}].concat(I.prototype.action_icons_def),to_dict:v.prototype.to_dict,add_drawable:v.prototype.add_drawable,unpack_drawables:v.prototype.unpack_drawables,change_mode:function(Y){I.prototype.change_mode.call(this,Y);for(var Z=0;Z<this.drawables.length;Z++){this.drawables[Z].change_mode(Y)}},init:function(){var aa=[];for(var Z=0;Z<this.drawables.length;Z++){aa.push(this.drawables[Z].init())}var Y=this;$.when.apply($,aa).then(function(){Y.enabled=true;Y.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:p.prototype.can_draw,draw_helper:function(Z,an,au,aq,af,ah,ao){var am=this,ay=this._gen_tile_cache_key(an,ah,au),ad=this._get_tile_bounds(au,aq),av=ad.get("start"),aa=ad.get("end");if(!ao){ao={}}var ax=(Z?undefined:am.tile_cache.get_elt(ay));if(ax){am.show_tile(ax,af,ah);return ax}var ag=[],am,ak=true,ar,ai;for(var at=0;at<this.drawables.length;at++){am=this.drawables[at];ar=am.data_manager.get_data(av,aa,am.mode,aq,am.data_url_extra_params);if(is_deferred(ar)){ak=false}ag.push(ar);ai=null;if(view.reference_track&&ah>view.canvas_manager.char_width_px){ai=view.reference_track.data_manager.get_data(av,aa,am.mode,aq,view.reference_track.data_url_extra_params);if(is_deferred(ai)){ak=false}}ag.push(ai)}if(ak){o(ar,ao.more_tile_data);this.tile_predraw_init();var ac=am.view.canvas_manager.new_canvas(),ad=am._get_tile_bounds(au,aq),av=ad.get("start"),aa=ad.get("end"),aw=0,an=Math.ceil((aa-av)*ah)+this.left_offset,al=0,ab=[];var Y=0;for(var at=0;at<this.drawables.length;at++,aw+=2){am=this.drawables[at];ar=ag[aw];var aj=am.mode;if(aj==="Auto"){aj=am.get_mode(ar);am.update_auto_mode(aj)}ab.push(aj);Y=am.get_canvas_height(ar,aj,ah,an);if(Y>al){al=Y}}ac.width=an;ac.height=(ao.height?ao.height:al);aw=0;var ap=ac.getContext("2d");ap.translate(this.left_offset,0);ap.globalAlpha=0.5;ap.globalCompositeOperation="source-over";for(var at=0;at<this.drawables.length;at++,aw+=2){am=this.drawables[at];ar=ag[aw];ai=ag[aw+1];ax=am.draw_tile(ar,ap,ab[at],aq,ad,ah,ai)}this.tile_cache.set_elt(ay,ax);this.show_tile(ax,af,ah);return ax}var ae=$.Deferred(),am=this;$.when.apply($,ag).then(function(){view.request_redraw(false,false,false,am);ae.resolve()});return ae},show_group:function(){var ab=new L(this.view,this.container,{name:this.name}),Y;for(var aa=0;aa<this.drawables.length;aa++){Y=this.drawables[aa];ab.add_drawable(Y);Y.container=ab;ab.content_div.append(Y.container_div)}var Z=this.container.replace_drawable(this,ab,true);ab.request_draw()},tile_predraw_init:function(){var ab=Number.MAX_VALUE,Y=-ab,Z;for(var aa=0;aa<this.drawables.length;aa++){Z=this.drawables[aa];if(Z instanceof i){if(Z.prefs.min_value<ab){ab=Z.prefs.min_value}if(Z.prefs.max_value>Y){Y=Z.prefs.max_value}}}for(var aa=0;aa<this.drawables.length;aa++){Z=this.drawables[aa];Z.prefs.min_value=ab;Z.prefs.max_value=Y}},postdraw_actions:function(aa,ad,af,Z){I.prototype.postdraw_actions.call(this,aa,ad,af,Z);var ac=-1;for(var ab=0;ab<aa.length;ab++){var Y=aa[ab].html_elt.find("canvas").height();if(Y>ac){ac=Y}}for(var ab=0;ab<aa.length;ab++){var ae=aa[ab];if(ae.html_elt.find("canvas").height()!==ac){this.draw_helper(true,ad,ae.index,ae.resolution,ae.html_elt.parent(),af,{height:ac});ae.html_elt.remove()}}}});var x=function(Y){I.call(this,Y,{content_div:Y.top_labeltrack},{resize:false});Y.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=reference_url;this.data_url_extra_params={dbkey:Y.dbkey};this.data_manager=new ReferenceTrackDataManager({data_url:reference_url});this.hide_contents()};o(x.prototype,p.prototype,I.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},can_draw:p.prototype.can_draw,draw_tile:function(ag,ah,ac,ab,ae,ai){var aa=this;if(ai>this.view.canvas_manager.char_width_px){if(ag.data===null){this.hide_contents();return}var Z=ah.canvas;ah.font=ah.canvas.manager.default_font;ah.textAlign="center";ag=ag.data;for(var ad=0,af=ag.length;ad<af;ad++){var Y=Math.floor(ad*ai);ah.fillText(ag[ad],Y,10)}this.show_contents();return new b(aa,ae,ab,Z,ag)}this.hide_contents()}});var i=function(aa,Z,ab){var Y=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";I.call(this,aa,Z,ab);this.hda_ldda=ab.hda_ldda;this.dataset_id=ab.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;this.config=new B({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value: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:ab.prefs,onchange:function(){Y.set_name(Y.prefs.name);Y.vertical_range=Y.prefs.max_value-Y.prefs.min_value;Y.set_min_value(Y.prefs.min_value);Y.set_max_value(Y.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};o(i.prototype,p.prototype,I.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(Y){this.prefs.min_value=Y;$("#linetrack_"+this.dataset_id+"_minval").text(this.prefs.min_value);this.tile_cache.clear();this.request_draw()},set_max_value:function(Y){this.prefs.max_value=Y;$("#linetrack_"+this.dataset_id+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.request_draw()},predraw_init:function(){var Y=this;Y.vertical_range=undefined;return $.getJSON(Y.data_url,{stats:true,chrom:Y.view.chrom,low:null,high:null,hda_ldda:Y.hda_ldda,dataset_id:Y.dataset_id},function(Z){Y.container_div.addClass("line-track");var ac=Z.data;if(isNaN(parseFloat(Y.prefs.min_value))||isNaN(parseFloat(Y.prefs.max_value))){var aa=ac.min,ae=ac.max;aa=Math.floor(Math.min(0,Math.max(aa,ac.mean-2*ac.sd)));ae=Math.ceil(Math.max(0,Math.min(ae,ac.mean+2*ac.sd)));Y.prefs.min_value=aa;Y.prefs.max_value=ae;$("#track_"+Y.dataset_id+"_minval").val(Y.prefs.min_value);$("#track_"+Y.dataset_id+"_maxval").val(Y.prefs.max_value)}Y.vertical_range=Y.prefs.max_value-Y.prefs.min_value;Y.total_frequency=ac.total_frequency;Y.container_div.find(".yaxislabel").remove();var ad=$("<div/>").text(T(Y.prefs.min_value,3)).make_text_editable({num_cols:6,on_finish:function(af){$(".tipsy").remove();var af=parseFloat(af);if(!isNaN(af)){Y.set_min_value(af)}},help_text:"Set min value"}).addClass("yaxislabel bottom").attr("id","linetrack_"+Y.dataset_id+"_minval").prependTo(Y.container_div),ab=$("<div/>").text(T(Y.prefs.max_value,3)).make_text_editable({num_cols:6,on_finish:function(af){$(".tipsy").remove();var af=parseFloat(af);if(!isNaN(af)){Y.set_max_value(af)}},help_text:"Set max value"}).addClass("yaxislabel top").attr("id","linetrack_"+Y.dataset_id+"_maxval").prependTo(Y.container_div)})},draw_tile:function(ah,af,aa,Z,ac,ag){var Y=af.canvas,ab=ac.get("start"),ae=ac.get("end"),ad=new H.LinePainter(ah.data,ab,ae,this.prefs,aa);ad.draw(af,Y.width,Y.height,ag);return new b(this,ac,Z,Y,ah.data)},can_subset:function(Y){return false}});var c=function(ab,aa,ad){var Z=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];I.call(this,ab,aa,ad);var ac=get_random_color(),Y=get_random_color([ac,"#ffffff"]);this.config=new B({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:ac},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:Y},{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:"histogram_max",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:ad.prefs,onchange:function(){Z.set_name(Z.prefs.name);Z.tile_cache.clear();Z.set_painter_from_config();Z.request_draw()}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.hda_ldda=ad.hda_ldda;this.dataset_id=ad.dataset_id;this.original_dataset_id=ad.dataset_id;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()};o(c.prototype,p.prototype,I.prototype,{set_dataset:function(Y){this.dataset_id=Y.get("id");this.hda_ldda=Y.get("hda_ldda");this.data_manager.set("dataset",Y)},set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=H.ArcLinkedFeaturePainter}else{this.painter=H.LinkedFeaturePainter}},before_draw:function(){this.max_height_px=0},after_show_tile:function(Y){this.max_height_px=Math.max(this.max_height_px,Y.html_elt.height());Y.html_elt.parent().children().css("height",this.max_height_px+"px");var Z=this.max_height_px;if(this.visible_height_px!==0){Z=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",Z+"px")},postdraw_actions:function(an,ai,ad,ac){I.prototype.postdraw_actions.call(this,an,ac);var ah=this;if(ah.mode==="Histogram"){var ak,Z=-1;for(ak=0;ak<an.length;ak++){var aj=an[ak].max_val;if(aj>Z){Z=aj}}for(ak=0;ak<an.length;ak++){var ap=an[ak];if(ap.max_val!==Z){ap.html_elt.remove();ah.draw_helper(true,ai,ap.index,ap.resolution,ap.html_elt.parent(),ad,{more_tile_data:{max:Z}})}}}if(ah.filters_manager){var ae=ah.filters_manager.filters;for(var am=0;am<ae.length;am++){ae[am].update_ui_elt()}var ao=false,Y,af;for(var ak=0;ak<an.length;ak++){if(an[ak].data.length){Y=an[ak].data[0];for(var am=0;am<ae.length;am++){af=ae[am];if(af.applies_to(Y)&&af.min!==af.max){ao=true;break}}}}if(ah.filters_available!==ao){ah.filters_available=ao;if(!ah.filters_available){ah.filters_manager.hide()}ah.update_icons()}}this.container_div.find(".yaxislabel").remove();var ab=an[0];if(ab instanceof j){var ag=(this.prefs.histogram_max?this.prefs.histogram_max:ab.max_val),aa=$("<div/>").text(ag).make_text_editable({num_cols:12,on_finish:function(aq){$(".tipsy").remove();var aq=parseFloat(aq);ah.prefs.histogram_max=(!isNaN(aq)?aq:null);ah.tile_cache.clear();ah.request_draw()},help_text:"Set max value; leave blank to use default"}).addClass("yaxislabel top").css("color",this.prefs.label_color);this.container_div.prepend(aa)}if(ab instanceof K){var al=true;for(var ak=0;ak<an.length;ak++){if(!an[ak].all_slotted){al=false;break}}if(!al){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(Y){var Y;if(this.mode==="Auto"){if(Y==="no_detail"){Y="feature spans"}else{if(Y==="summary_tree"){Y="coverage histogram"}}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+Y+")")}},incremental_slots:function(ac,Y,ab){var Z=this.view.canvas_manager.dummy_context,aa=this.slotters[ac];if(!aa||(aa.mode!==ab)){aa=new (r.FeatureSlotter)(ac,ab,w,function(ad){return Z.measureText(ad)});this.slotters[ac]=aa}return aa.slot_features(Y)},get_summary_tree_data:function(ac,af,aa,an){if(an>aa-af){an=aa-af}var aj=Math.floor((aa-af)/an),am=[],ab=0;var ad=0,ae=0,ai,al=0,ag=[],ak,ah;var Z=function(aq,ap,ar,ao){aq[0]=ap+ar*ao;aq[1]=ap+(ar+1)*ao};while(al<an&&ad!==ac.length){var Y=false;for(;al<an&&!Y;al++){Z(ag,af,al,aj);for(ae=ad;ae<ac.length;ae++){ai=ac[ae].slice(1,3);if(is_overlap(ai,ag)){Y=true;break}}if(Y){break}}data_start_index=ae;am[am.length]=ak=[ag[0],0];for(;ae<ac.length;ae++){ai=ac[ae].slice(1,3);if(is_overlap(ai,ag)){ak[1]++}else{break}}if(ak[1]>ab){ab=ak[1]}al++}return{max:ab,delta:aj,data:am}},get_mode:function(Y){if(Y.dataset_type==="summary_tree"){mode="summary_tree"}else{if(Y.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>E){mode="Squish"}else{mode="Pack"}}}return mode},get_canvas_height:function(Y,ac,ad,Z){if(ac==="summary_tree"||ac==="Histogram"){return this.summary_draw_height}else{var ab=this.incremental_slots(ad,Y.data,ac);var aa=new (this.painter)(null,null,null,this.prefs,ac);return Math.max(X,aa.get_required_height(ab,Z))}},draw_tile:function(aj,an,al,ao,ab,af,aa){var am=this,Z=an.canvas,av=ab.get("start"),Y=ab.get("end"),aA=25,ac=this.left_offset;if(al==="summary_tree"||al==="Histogram"){if(aj.dataset_type!=="summary_tree"){var ag=this.get_summary_tree_data(aj.data,av,Y,200);if(aj.max){ag.max=aj.max}aj=ag}var ax=new H.SummaryTreePainter(aj,av,Y,this.prefs);ax.draw(an,Z.width,Z.height,af);return new j(am,ab,ao,Z,aj.data,aj.max)}var ae=[],ak=this.slotters[af].slots;all_slotted=true;if(aj.data){var ah=this.filters_manager.filters;for(var ap=0,ar=aj.data.length;ap<ar;ap++){var ad=aj.data[ap];var aq=false;var ai;for(var au=0,az=ah.length;au<az;au++){ai=ah[au];ai.update_attrs(ad);if(!ai.keep(ad)){aq=true;break}}if(!aq){ae.push(ad);if(!(ad[0] in ak)){all_slotted=false}}}}var ay=(this.filters_manager.alpha_filter?new y(this.filters_manager.alpha_filter):null);var aw=(this.filters_manager.height_filter?new y(this.filters_manager.height_filter):null);var ax=new (this.painter)(ae,av,Y,this.prefs,al,ay,aw,aa);var at=null;an.fillStyle=this.prefs.block_color;an.font=an.canvas.manager.default_font;an.textAlign="right";if(aj.data){at=ax.draw(an,Z.width,Z.height,af,ak);at.translation=-ac}return new K(am,ab,ao,Z,aj.data,af,al,aj.message,all_slotted,at)},data_and_mode_compatible:function(Y,Z){if(Z==="Auto"){return true}else{if(Y.extra_info==="no_detail"||Y.dataset_type==="summary_tree"){return false}else{return true}}},can_subset:function(Y){if(Y.dataset_type==="summary_tree"||Y.message||Y.extra_info==="no_detail"){return false}return true}});var N=function(Z,Y,aa){c.call(this,Z,Y,aa);this.config=new B({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:get_random_color()},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:aa.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=H.ReadPainter};o(N.prototype,p.prototype,I.prototype,c.prototype);var Q=function(aa,Z,ac){c.call(this,aa,Z,ac);var ab=get_random_color(),Y=get_random_color([ab,"#ffffff"]);this.config=new B({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:ab},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:Y},{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:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"Clear value to set automatically"},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ac.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=H.ReadPainter;this.update_icons()};o(Q.prototype,p.prototype,I.prototype,c.prototype);R.View=W;R.DrawableGroup=L;R.LineTrack=i;R.FeatureTrack=c;R.ReadTrack=Q;R.VcfTrack=N;R.CompositeTrack=g};var slotting_module=function(c,b){var e=c("class").extend;var d=2,a=5;b.FeatureSlotter=function(i,h,f,g){this.slots={};this.start_end_dct={};this.w_scale=i;this.mode=h;this.include_label=(h==="Pack");this.max_rows=f;this.measureText=g};e(b.FeatureSlotter.prototype,{slot_features:function(m){var p=this.w_scale,h=this.start_end_dct,x=[],z=[],n=0,y=this.max_rows;for(var v=0,w=m.length;v<w;v++){var k=m[v],o=k[0];if(this.slots[o]!==undefined){n=Math.max(n,this.slots[o]);z.push(this.slots[o])}else{x.push(v)}}var q=function(E,F){for(var D=0;D<=y;D++){var B=false,G=h[D];if(G!==undefined){for(var A=0,C=G.length;A<C;A++){var i=G[A];if(F>i[0]&&E<i[1]){B=true;break}}}if(!B){return D}}return -1};for(var v=0,w=x.length;v<w;v++){var k=m[x[v]],o=k[0],t=k[1],f=k[2],r=k[3],g=Math.floor(t*p),l=Math.ceil(f*p),u=this.measureText(r).width,j;if(r!==undefined&&this.include_label){u+=(d+a);if(g-u>=0){g-=u;j="left"}else{l+=u;j="right"}}var s=q(g,l);if(s>=0){if(h[s]===undefined){h[s]=[]}h[s].push([g,l]);this.slots[o]=s;n=Math.max(n,s)}}return n+1}})};var painters_module=function(i,x){var u=i("class").extend;var p=function(I,A,G,z,F,D){if(D===undefined){D=4}var C=z-A;var B=F-G;var E=Math.floor(Math.sqrt(C*C+B*B)/D);var J=C/E;var H=B/E;var y;for(y=0;y<E;y++,A+=J,G+=H){if(y%2!==0){continue}I.fillRect(A,G,D,1)}};var q=function(B,A,z,E){var D=A-E/2,C=A+E/2,F=z-Math.sqrt(E*3/2);B.beginPath();B.moveTo(D,F);B.lineTo(C,F);B.lineTo(A,z);B.lineTo(D,F);B.strokeStyle=this.fillStyle;B.fill();B.stroke();B.closePath()};var d=function(y){this.default_val=(y?y:1)};d.prototype.gen_val=function(y){return this.default_val};var l=function(A,C,y,z,B){this.data=A;this.view_start=C;this.view_end=y;this.prefs=u({},this.default_prefs,z);this.mode=B};l.prototype.default_prefs={};l.prototype.draw=function(z,A,y,B){};var v=function(A,C,y,z,B){l.call(this,A,C,y,z,B)};v.prototype.default_prefs={show_counts:false};v.prototype.draw=function(L,z,K,M){var E=this.view_start,N=this.view_end-this.view_start,I=this.data.data,G=(this.prefs.histogram_max?this.prefs.histogram_max:this.data.max),B=K;delta_x_px=Math.ceil(this.data.delta*M);L.save();for(var C=0,D=I.length;C<D;C++){var H=Math.floor((I[C][0]-E)*M);var F=I[C][1];if(!F){continue}var J=F/G*K;if(F!==0&&J<1){J=1}L.fillStyle=this.prefs.block_color;L.fillRect(H,B-J,delta_x_px,J);var A=4;if(this.prefs.show_counts&&(L.measureText(F).width+A)<delta_x_px){L.fillStyle=this.prefs.label_color;L.textAlign="center";L.fillText(F,H+(delta_x_px/2),10)}}L.restore()};var b=function(y,C,E,F,A){l.call(this,y,C,E,F,A);if(this.prefs.min_value===undefined){var G=Infinity;for(var z=0,B=this.data.length;z<B;z++){G=Math.min(G,this.data[z][1])}this.prefs.min_value=G}if(this.prefs.max_value===undefined){var D=-Infinity;for(var z=0,B=this.data.length;z<B;z++){D=Math.max(D,this.data[z][1])}this.prefs.max_value=D}};b.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};b.prototype.draw=function(S,Q,N,D){var I=false,K=this.prefs.min_value,F=this.prefs.max_value,M=F-K,B=N,C=this.view_start,P=this.view_end-this.view_start,L=this.mode,aa=this.data;S.save();var ac=Math.round(N+K/M*N);if(L!=="Intensity"){S.fillStyle="#aaa";S.fillRect(0,ac,Q,1)}S.beginPath();var Y,G,E;if(aa.length>1){E=Math.ceil((aa[1][0]-aa[0][0])*D)}else{E=10}var A=parseInt(this.prefs.color.slice(1),16),H=(A&16711680)>>16,R=(A&65280)>>8,V=A&255;for(var T=0,U=aa.length;T<U;T++){S.fillStyle=S.strokeStyle=this.prefs.color;Y=Math.round((aa[T][0]-C)*D);G=aa[T][1];var W=false,J=false;if(G===null){if(I&&L==="Filled"){S.lineTo(Y,B)}I=false;continue}if(G<K){J=true;G=K}else{if(G>F){W=true;G=F}}if(L==="Histogram"){G=Math.round(G/M*B);S.fillRect(Y,ac,E,-G)}else{if(L==="Intensity"){var z=(G-K)/M,O=Math.round(H+(255-H)*(1-z)),X=Math.round(R+(255-R)*(1-z)),ab=Math.round(V+(255-V)*(1-z));S.fillStyle="rgb("+O+","+X+","+ab+")";S.fillRect(Y,0,E,B)}else{G=Math.round(B-(G-K)/M*B);if(I){S.lineTo(Y,G)}else{I=true;if(L==="Filled"){S.moveTo(Y,B);S.lineTo(Y,G)}else{S.moveTo(Y,G)}}}}S.fillStyle=this.prefs.overflow_color;if(W||J){var Z;if(L==="Histogram"||L==="Intensity"){Z=E}else{Y-=2;Z=4}if(W){S.fillRect(Y,0,Z,3)}if(J){S.fillRect(Y,B-3,Z,3)}}S.fillStyle=this.prefs.color}if(L==="Filled"){if(I){S.lineTo(Y,ac);S.lineTo(0,ac)}S.fill()}else{S.stroke()}S.restore()};var m=function(y){this.feature_positions={};this.slot_height=y;this.translation=0;this.y_translation=0};m.prototype.map_feature_data=function(z,B,y,A){if(!this.feature_positions[B]){this.feature_positions[B]=[]}this.feature_positions[B].push({data:z,x_start:y,x_end:A})};m.prototype.get_feature_data=function(z,D){var C=Math.floor((D-this.y_translation)/this.slot_height),B;if(!this.feature_positions[C]){return null}z+=this.translation;for(var A=0;A<this.feature_positions[C].length;A++){B=this.feature_positions[C][A];if(z>=B.x_start&&z<=B.x_end){return B.data}}};var o=function(A,D,y,z,C,E,B){l.call(this,A,D,y,z,C);this.alpha_scaler=(E?E:new d());this.height_scaler=(B?B:new d())};o.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};u(o.prototype,{get_required_height:function(A,z){var y=y_scale=this.get_row_height(),B=this.mode;if(B==="no_detail"||B==="Squish"||B==="Pack"){y=A*y_scale}return y+this.get_top_padding(z)+this.get_bottom_padding(z)},get_top_padding:function(y){return 0},get_bottom_padding:function(y){return Math.max(Math.round(this.get_row_height()/2),5)},draw:function(K,I,G,E,F){var Q=this.data,D=this.view_start,M=this.view_end;K.save();K.fillStyle=this.prefs.block_color;K.textAlign="right";var H=this.view_end-this.view_start,L=this.get_row_height(),P=new m(L),B;for(var N=0,O=Q.length;N<O;N++){var A=Q[N],C=A[0],J=A[1],y=A[2],z=(F&&F[C]!==undefined?F[C]:null);if((J<M&&y>D)&&(this.mode==="Dense"||z!==null)){B=this.draw_element(K,this.mode,A,z,D,M,E,L,I);P.map_feature_data(A,z,B[0],B[1])}}K.restore();P.y_translation=this.get_top_padding(I);return P},draw_element:function(E,A,G,C,B,D,F,z,y){console.log("WARNING: Unimplemented function.");return[0,0]}});var c=10,h=3,k=5,w=10,f=1,s=9,e=3,a=9,j=2,g="#ccc";var r=function(A,D,y,z,C,E,B){o.call(this,A,D,y,z,C,E,B);this.draw_background_connector=true;this.draw_individual_connectors=false};u(r.prototype,o.prototype,{get_row_height:function(){var z=this.mode,y;if(z==="Dense"){y=c}else{if(z==="no_detail"){y=h}else{if(z==="Squish"){y=k}else{y=w}}}return y},draw_element:function(M,D,X,H,O,ai,am,ao,y){var T=X[0],ak=X[1],ad=X[2]-1,Q=X[3],K=X[4],ae=Math.floor(Math.max(0,(ak-O)*am)),N=Math.ceil(Math.min(y,Math.max(0,(ad-O)*am))),ac=ae,an=N,aa=(D==="Dense"?0:(0+H))*ao+this.get_top_padding(y),L,ag,R=null,aq=null,B=B=(!K||K==="+"||K==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;M.globalAlpha=this.alpha_scaler.gen_val(X);if(D==="Dense"){H=1}if(D==="no_detail"){M.fillStyle=B;M.fillRect(ae,aa+5,N-ae,f)}else{var Z=X[5],af=X[6],C=X[7],V=true;if(Z&&af){R=Math.floor(Math.max(0,(Z-O)*am));aq=Math.ceil(Math.min(y,Math.max(0,(af-O)*am)))}var al,U;if(D==="Squish"){al=1;U=e;V=false}else{if(D==="Dense"){al=5;U=s}else{al=5;U=a}}if(!C){M.fillStyle=B;M.fillRect(ae,aa+1,N-ae,U);if(K&&V){if(K==="+"){M.fillStyle=M.canvas.manager.get_pattern("right_strand_inv")}else{if(K==="-"){M.fillStyle=M.canvas.manager.get_pattern("left_strand_inv")}}M.fillRect(ae,aa+1,N-ae,U)}}else{var J,W;if(D==="Squish"||D==="Dense"){J=aa+Math.floor(e/2)+1;W=1}else{if(K){J=aa;W=U}else{J+=(e/2)+1;W=1}}if(this.draw_background_connector){if(D==="Squish"||D==="Dense"){M.fillStyle=g}else{if(K){if(K==="+"){M.fillStyle=M.canvas.manager.get_pattern("right_strand")}else{if(K==="-"){M.fillStyle=M.canvas.manager.get_pattern("left_strand")}}}else{M.fillStyle=g}}M.fillRect(ae,J,N-ae,W)}var E;for(var aj=0,A=C.length;aj<A;aj++){var F=C[aj],z=Math.floor(Math.max(0,(F[0]-O)*am)),Y=Math.ceil(Math.min(y,Math.max((F[1]-1-O)*am))),S,ab;if(z>Y){continue}M.fillStyle=B;M.fillRect(z,aa+(U-al)/2+1,Y-z,al);if(R!==undefined&&af>Z&&!(z>aq||Y<R)){var ah=Math.max(z,R),I=Math.min(Y,aq);M.fillRect(ah,aa+1,I-ah,U)}if(this.draw_individual_connectors&&S){this.draw_connector(M,S,ab,z,Y,aa)}S=z;ab=Y}if(D==="Pack"){M.globalAlpha=1;M.fillStyle="white";var G=this.height_scaler.gen_val(X),P=Math.ceil(U*G),ap=Math.round((U-P)/2);if(G!==1){M.fillRect(ae,J+1,N-ae,ap);M.fillRect(ae,J+U-ap+1,N-ae,ap)}}}M.globalAlpha=1;if(D==="Pack"&&ak>O){M.fillStyle=label_color;if(O===0&&ae-M.measureText(Q).width<0){M.textAlign="left";M.fillText(Q,N+j,aa+8);an+=M.measureText(Q).width+j}else{M.textAlign="right";M.fillText(Q,ae-j,aa+8);ac-=M.measureText(Q).width+j}}}M.globalAlpha=1;return[ac,an]}});var t=function(B,E,y,A,D,F,C,z){o.call(this,B,E,y,A,D,F,C);this.ref_seq=(z?z.data:null)};u(t.prototype,o.prototype,{get_row_height:function(){var y,z=this.mode;if(z==="Dense"){y=c}else{if(z==="Squish"){y=k}else{y=w;if(this.prefs.show_insertions){y*=2}}}return y},draw_read:function(K,A,ag,V,L,aa,ad,C,B,M){K.textAlign="center";var J=this,R=[L,aa],Z=0,W=0,D=0,F=K.canvas.manager.char_width_px,y=(B==="+"?this.prefs.block_color:this.prefs.reverse_strand_color);var O=[];if((A==="Pack"||this.mode==="Auto")&&M!==undefined&&ag>F){D=Math.round(ag/2)}if(!C){C=[[0,M.length]]}for(var G=0,I=C.length;G<I;G++){var z=C[G],E="MIDNSHP=X"[z[0]],S=z[1];if(E==="H"||E==="S"){Z-=S}var U=ad+Z,Y=Math.floor(Math.max(0,(U-L)*ag)),ab=Math.floor(Math.max(0,(U+S-L)*ag));if(Y===ab){ab+=1}switch(E){case"H":break;case"S":case"M":case"=":if(is_overlap([U,U+S],R)){var N=M.slice(W,W+S);if(D>0){K.fillStyle=y;K.fillRect(Y-D,V+1,ab-Y,9);K.fillStyle=g;for(var af=0,H=N.length;af<H;af++){if(this.prefs.show_differences){if(this.ref_seq){var P=this.ref_seq[U-L+af];if(!P||P.toLowerCase()===N[af].toLowerCase()){continue}}else{continue}}if(U+af>=L&&U+af<=aa){var X=Math.floor(Math.max(0,(U+af-L)*ag));K.fillText(N[af],X,V+9)}}}else{K.fillStyle=y;K.fillRect(Y,V+4,ab-Y,e)}}W+=S;Z+=S;break;case"N":K.fillStyle=g;K.fillRect(Y-D,V+5,ab-Y,1);Z+=S;break;case"D":K.fillStyle="red";K.fillRect(Y-D,V+4,ab-Y,3);Z+=S;break;case"P":break;case"I":var ah=Y-D;if(is_overlap([U,U+S],R)){var N=M.slice(W,W+S);if(this.prefs.show_insertions){var T=Y-(ab-Y)/2;if((A==="Pack"||this.mode==="Auto")&&M!==undefined&&ag>F){K.fillStyle="yellow";K.fillRect(T-D,V-9,ab-Y,9);O[O.length]={type:"triangle",data:[ah,V+4,5]};K.fillStyle=g;switch(compute_overlap([U,U+S],R)){case (OVERLAP_START):N=N.slice(L-U);break;case (OVERLAP_END):N=N.slice(0,U-aa);break;case (CONTAINED_BY):break;case (CONTAINS):N=N.slice(L-U,U-aa);break}for(var af=0,H=N.length;af<H;af++){var X=Math.floor(Math.max(0,(U+af-L)*ag));K.fillText(N[af],X-(ab-Y)/2,V)}}else{K.fillStyle="yellow";K.fillRect(T,V+(this.mode!=="Dense"?2:5),ab-Y,(A!=="Dense"?e:s))}}else{if((A==="Pack"||this.mode==="Auto")&&M!==undefined&&ag>F){O.push({type:"text",data:[N.length,ah,V+9]})}else{}}}W+=S;break;case"X":W+=S;break}}K.fillStyle="yellow";var Q,ai,ae;for(var ac=0;ac<O.length;ac++){Q=O[ac];ai=Q.type;ae=Q.data;if(ai==="text"){K.save();K.font="bold "+K.font;K.fillText(ae[0],ae[1],ae[2]);K.restore()}else{if(ai==="triangle"){q(K,ae[0],ae[1],ae[2])}}}},draw_element:function(R,M,E,B,U,z,I,S,P){var H=E[0],Q=E[1],A=E[2],J=E[3],D=Math.floor(Math.max(0,(Q-U)*I)),F=Math.ceil(Math.min(P,Math.max(0,(A-U)*I))),C=(M==="Dense"?0:(0+B))*S,G=this.prefs.label_color,O=0;if((M==="Pack"||this.mode==="Auto")&&I>R.canvas.manager.char_width_px){var O=Math.round(I/2)}if(E[5] instanceof Array){var N=Math.floor(Math.max(0,(E[4][0]-U)*I)),L=Math.ceil(Math.min(P,Math.max(0,(E[4][1]-U)*I))),K=Math.floor(Math.max(0,(E[5][0]-U)*I)),y=Math.ceil(Math.min(P,Math.max(0,(E[5][1]-U)*I)));if(E[4][1]>=U&&E[4][0]<=z&&E[4][2]){this.draw_read(R,M,I,C,U,z,E[4][0],E[4][2],E[4][3],E[4][4])}if(E[5][1]>=U&&E[5][0]<=z&&E[5][2]){this.draw_read(R,M,I,C,U,z,E[5][0],E[5][2],E[5][3],E[5][4])}if(K>L){R.fillStyle=g;p(R,L-O,C+5,K-O,C+5)}}else{this.draw_read(R,M,I,C,U,z,Q,E[4],E[5],E[6])}if(M==="Pack"&&Q>U&&J!=="."){R.fillStyle=this.prefs.label_color;var T=1;if(T===0&&D-R.measureText(J).width<0){R.textAlign="left";R.fillText(J,F+j-O,C+8)}else{R.textAlign="right";R.fillText(J,D-j-O,C+8)}}return[0,0]}});var n=function(A,D,y,z,C,E,B){r.call(this,A,D,y,z,C,E,B);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};u(n.prototype,o.prototype,r.prototype,{calculate_longest_feature_length:function(){var z=0;for(var C=0,y=this.data.length;C<y;C++){var B=this.data[C],A=B[1],D=B[2];z=Math.max(z,D-A)}return z},get_top_padding:function(z){var y=this.view_end-this.view_start,A=z/y;return Math.min(128,Math.ceil((this.longest_feature_length/2)*A))},draw_connector:function(G,B,F,H,E,D){var y=(F+H)/2,C=H-y;var A=Math.PI,z=0;if(C>0){G.beginPath();G.arc(y,D,H-y,Math.PI,0);G.stroke()}}});x.Scaler=d;x.SummaryTreePainter=v;x.LinePainter=b;x.LinkedFeaturePainter=r;x.ReadPainter=t;x.ArcLinkedFeaturePainter=n};(function(d){var c={};var b=function(e){return c[e]};var a=function(f,g){var e={};g(b,e);c[f]=e};a("class",class_module);a("slotting",slotting_module);a("painters",painters_module);a("trackster",trackster_module);for(key in c.trackster){d[key]=c.trackster[key]}})(window);
\ No newline at end of file
+var class_module=function(b,a){var c=function(){var g=arguments[0];for(var f=1;f<arguments.length;f++){var d=arguments[f];for(var e in d){g[e]=d[e]}}return g};a.extend=c};var requestAnimationFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b,a){window.setTimeout(b,1000/60)}})();var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=BEFORE}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var is_deferred=function(a){return("isResolved" in a)};var get_random_color=function(a){if(!a){a="#ffffff"}if(typeof(a)==="string"){a=[a]}for(var j=0;j<a.length;j++){a[j]=parseInt(a[j].slice(1),16)}var n=function(t,s,i){return((t*299)+(s*587)+(i*114))/1000};var e=function(v,u,w,s,i,t){return(Math.max(v,s)-Math.min(v,s))+(Math.max(u,i)-Math.min(u,i))+(Math.max(w,t)-Math.min(w,t))};var g,o,f,k,q,h,r,c,d,b,p,m=false,l=0;do{g=Math.round(Math.random()*16777215);o=(g&16711680)>>16;f=(g&65280)>>8;k=g&255;d=n(o,f,k);m=true;for(j=0;j<a.length;j++){q=a[j];h=(q&16711680)>>16;r=(q&65280)>>8;c=q&255;b=n(h,r,c);p=e(o,f,k,h,r,c);if((Math.abs(d-b)<40)||(p<200)){m=false;break}}l++}while(!m&&l<=10);return"#"+(16777216+g).toString(16).substr(1,6)};var create_action_icon=function(c,b,a){return $("<a/>").attr("href","javascript:void(0);").attr("title",c).addClass("icon-button").addClass(b).tipsy({gravity:"s"}).click(a)};var trackster_module=function(d,R){var o=d("class").extend,r=d("slotting"),H=d("painters");var m={};var k=function(Y,Z){m[Y.attr("id")]=Z};var l=function(Y,aa,ac,ab){ac=".group";var Z={};m[Y.attr("id")]=ab;Y.bind("drag",{handle:"."+aa,relative:true},function(ak,al){var aj=$(this),ao=$(this).parent(),ag=ao.children(),ai=m[$(this).attr("id")],af,ae,am,ad,ah;ae=$(this).parents(ac);if(ae.length!==0){am=ae.position().top;ad=am+ae.outerHeight();if(al.offsetY<am){$(this).insertBefore(ae);var an=m[ae.attr("id")];an.remove_drawable(ai);an.container.add_drawable_before(ai,an);return}else{if(al.offsetY>ad){$(this).insertAfter(ae);var an=m[ae.attr("id")];an.remove_drawable(ai);an.container.add_drawable(ai);return}}}ae=null;for(ah=0;ah<ag.length;ah++){af=$(ag.get(ah));am=af.position().top;ad=am+af.outerHeight();if(af.is(ac)&&this!==af.get(0)&&al.offsetY>=am&&al.offsetY<=ad){if(al.offsetY-am<ad-al.offsetY){af.find(".content-div").prepend(this)}else{af.find(".content-div").append(this)}if(ai.container){ai.container.remove_drawable(ai)}m[af.attr("id")].add_drawable(ai);return}}for(ah=0;ah<ag.length;ah++){af=$(ag.get(ah));if(al.offsetY<af.position().top&&!(af.hasClass("reference-track")||af.hasClass("intro"))){break}}if(ah===ag.length){if(this!==ag.get(ah-1)){ao.append(this);m[ao.attr("id")].move_drawable(ai,ah)}}else{if(this!==ag.get(ah)){$(this).insertBefore(ag.get(ah));m[ao.attr("id")].move_drawable(ai,(al.deltaY>0?ah-1:ah))}}}).bind("dragstart",function(){Z["border-top"]=Y.css("border-top");Z["border-bottom"]=Y.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(Z)})};R.moveable=l;var X=16,C=9,z=20,w=100,E=12000,O=400,G=5000,t=100,n="There was an error in indexing this dataset. ",F="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",A="No data for this chrom/contig.",s="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",u="Tool cannot be rerun: ",a="Loading data...",S="Ready for display",M=10,D=20;function T(Z,Y){if(!Y){Y=0}var aa=Math.pow(10,Y);return Math.round(Z*aa)/aa}var p=function(Z,Y,ab){if(!p.id_counter){p.id_counter=0}this.id=p.id_counter++;this.name=ab.name;this.view=Z;this.container=Y;this.config=new B({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:ab.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=ab.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(ac){ac.stopPropagation()});var aa=this;this.container_div.hover(function(){aa.icons_div.show()},function(){aa.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};p.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(Y){if(Y.content_visible){Y.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");Y.hide_contents();Y.content_visible=false}else{Y.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");Y.content_visible=true;Y.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(Z){var ab=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},Y=function(){Z.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},aa=function(ac){if((ac.keyCode||ac.which)===27){ab()}else{if((ac.keyCode||ac.which)===13){Y()}}};$(window).bind("keypress.check_enter_esc",aa);show_modal("Configure",Z.config.build_form(),{Cancel:ab,OK:Y})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(Y){$(".tipsy").remove();Y.remove()}}];o(p.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(){},to_dict:function(){},set_name:function(Y){this.old_name=this.name;this.name=Y;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 Y=this.view;this.container_div.hide(0,function(){$(this).remove();Y.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(Z,ae,ad,ac,Y,ab){var aa=this;this.action_icons[Z]=$("<a/>").attr("href","javascript:void(0);").attr("title",ae).addClass("icon-button").addClass(ad).tipsy({gravity:"s"}).click(function(){ac(aa)}).appendTo(this.icons_div);if(ab){this.action_icons[Z].hide()}},build_action_icons:function(Y){var aa;for(var Z=0;Z<Y.length;Z++){aa=Y[Z];this.add_action_icon(aa.name,aa.title,aa.css_class,aa.on_click_fn,aa.prepend,aa.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){}});var v=function(Z,Y,aa){p.call(this,Z,Y,aa);this.obj_type=aa.obj_type;this.drawables=[]};o(v.prototype,p.prototype,{unpack_drawables:function(aa){this.drawables=[];var Z;for(var Y=0;Y<aa.length;Y++){Z=object_from_template(aa[Y],this);this.add_drawable(Z)}},init:function(){for(var Y=0;Y<this.drawables.length;Y++){this.drawables[Y].init()}},_draw:function(){for(var Y=0;Y<this.drawables.length;Y++){this.drawables[Y]._draw()}},to_dict:function(){var Z=[];for(var Y=0;Y<this.drawables.length;Y++){Z.push(this.drawables[Y].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:Z}},add_drawable:function(Y){this.drawables.push(Y);Y.container=this;this.changed()},add_drawable_before:function(aa,Y){this.changed();var Z=this.drawables.indexOf(Y);if(Z!==-1){this.drawables.splice(Z,0,aa);return true}return false},replace_drawable:function(aa,Y,Z){var ab=this.drawables.indexOf(aa);if(ab!==-1){this.drawables[ab]=Y;if(Z){aa.container_div.replaceWith(Y.container_div)}this.changed()}return ab},remove_drawable:function(Z){var Y=this.drawables.indexOf(Z);if(Y!==-1){this.drawables.splice(Y,1);Z.container=null;this.changed();return true}return false},move_drawable:function(Z,aa){var Y=this.drawables.indexOf(Z);if(Y!==-1){this.drawables.splice(Y,1);this.drawables.splice(aa,0,Z);this.changed();return true}return false}});var L=function(Z,Y,ab){o(ab,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});v.call(this,Z,Y,ab);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);k(this.container_div,this);k(this.content_div,this);l(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new U(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in ab){this.unpack_drawables(ab.drawables)}if("filters" in ab){var aa=this.filters_manager;this.filters_manager=new U(this,ab.filters);aa.parent_div.replaceWith(this.filters_manager.parent_div);if(ab.filters.visible){this.setup_multitrack_filtering()}}};o(L.prototype,p.prototype,v.prototype,{action_icons_def:[p.prototype.action_icons_def[0],p.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(Y){$(".tipsy").remove();Y.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(Y){if(Y.filters_manager.visible()){Y.filters_manager.clear_filters();Y._restore_filter_managers()}else{Y.setup_multitrack_filtering();Y.request_draw(true)}Y.filters_manager.toggle()}},p.prototype.action_icons_def[2]],build_container_div:function(){var Y=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(Y)}return Y},build_header_div:function(){var Y=$("<div/>").addClass("track-header");Y.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(Y);return Y},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var aa=this.drawables.length;if(aa===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(aa===1){if(this.drawables[0] instanceof g){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var ah,ag,ae,ak=true,ac=this.drawables[0].get_type(),Y=0;for(ah=0;ah<aa;ah++){ae=this.drawables[ah];if(ae.get_type()!==ac){can_composite=false;break}if(ae instanceof c){Y++}}if(ak||Y===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".tipsy").remove()}if(Y>1&&Y===this.drawables.length){var al={},Z;ae=this.drawables[0];for(ag=0;ag<ae.filters_manager.filters.length;ag++){Z=ae.filters_manager.filters[ag];al[Z.name]=[Z]}for(ah=1;ah<this.drawables.length;ah++){ae=this.drawables[ah];for(ag=0;ag<ae.filters_manager.filters.length;ag++){Z=ae.filters_manager.filters[ag];if(Z.name in al){al[Z.name].push(Z)}}}this.filters_manager.remove_all();var ab,ad,af,ai;for(var aj in al){ab=al[aj];if(ab.length===Y){ad=new P({name:ab[0].name,index:ab[0].index});this.filters_manager.add_filter(ad)}}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 Y=0;Y<this.drawables.length;Y++){this.drawables[Y].filters_manager=this.saved_filters_managers[Y]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var Y=0;Y<this.drawables.length;Y++){drawable=this.drawables[Y];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var ac=[];for(var Z=0;Z<this.drawables.length;Z++){ac.push(this.drawables[Z].name)}var aa="Composite Track of "+this.drawables.length+" tracks ("+ac.join(", ")+")";var ab=new g(this.view,this.view,{name:aa,drawables:this.drawables});var Y=this.container.replace_drawable(this,ab,true);ab.request_draw()},add_drawable:function(Y){v.prototype.add_drawable.call(this,Y);this.update_icons()},remove_drawable:function(Y){v.prototype.remove_drawable.call(this,Y);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var Y=o(v.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return Y},request_draw:function(Y,aa){for(var Z=0;Z<this.drawables.length;Z++){this.drawables[Z].request_draw(Y,aa)}}});var W=function(Y){o(Y,{obj_type:"View"});v.call(this,"View",Y.container,Y);this.chrom=null;this.vis_id=Y.vis_id;this.dbkey=Y.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.init();this.canvas_manager=new CanvasManager(this.container.get(0).ownerDocument);this.reset()};_.extend(W.prototype,Backbone.Events);o(W.prototype,v.prototype,{init:function(){this.requested_redraw=false;var aa=this.container,Y=this;this.top_container=$("<div/>").addClass("top-container").appendTo(aa);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(aa);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(aa);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.browser_content_div);this.content_div=this.viewport_container;k(this.viewport_container,Y);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var ab=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_datasets(add_datasets_url,add_track_async_url,function(ac){_.each(ac,function(ad){Y.add_drawable(object_from_template(ad,Y))})})});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").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var Z=function(ac){if(ac.type==="focusout"||(ac.keyCode||ac.which)===13||(ac.keyCode||ac.which)===27){if((ac.keyCode||ac.which)!==27){Y.go_to($(this).val())}$(this).hide();$(this).val("");Y.location_span.show();Y.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",Z).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").attr("original-title","Click to change location").tipsy({gravity:"n"}).appendTo(this.nav_controls);this.location_span.click(function(){Y.location_span.hide();Y.chrom_select.hide();Y.nav_input.val(Y.chrom+":"+Y.low+"-"+Y.high);Y.nav_input.css("display","inline-block");Y.nav_input.select();Y.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a/>").attr("id","zoom-out").attr("title","Zoom out").tipsy({gravity:"n"}).click(function(){Y.zoom_out();Y.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tipsy({gravity:"n"}).click(function(){Y.zoom_in();Y.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){Y.change_chrom(Y.chrom_select.val())});this.browser_content_div.click(function(ac){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ac){Y.zoom_in(ac.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ac,ad){this.current_x=ad.offsetX}).bind("drag",function(ac,ae){var af=ae.offsetX-this.current_x;this.current_x=ae.offsetX;var ad=Math.round(af/Y.viewport_container.width()*(Y.max_high-Y.max_low));Y.move_delta(-ad)});this.overview_close.click(function(){Y.reset_overview()});this.viewport_container.bind("draginit",function(ac,ad){if(ac.clientX>Y.viewport_container.width()-16){return false}}).bind("dragstart",function(ac,ad){ad.original_low=Y.low;ad.current_height=ac.clientY;ad.current_x=ad.offsetX}).bind("drag",function(ae,ag){var ac=$(this);var ah=ag.offsetX-ag.current_x;var ad=ac.scrollTop()-(ae.clientY-ag.current_height);ac.scrollTop(ad);ag.current_height=ae.clientY;ag.current_x=ag.offsetX;var af=Math.round(ah/Y.viewport_container.width()*(Y.high-Y.low));Y.move_delta(af)}).bind("mousewheel",function(ae,ag,ad,ac){if(ad){ad*=50;var af=Math.round(-ad/Y.viewport_container.width()*(Y.high-Y.low));Y.move_delta(af)}});this.top_labeltrack.bind("dragstart",function(ac,ad){return $("<div />").css({height:Y.browser_content_div.height()+Y.top_labeltrack.height()+Y.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ag,ah){$(ah.proxy).css({left:Math.min(ag.pageX,ah.startX)-Y.container.offset().left,width:Math.abs(ag.pageX-ah.startX)});var ad=Math.min(ag.pageX,ah.startX)-Y.container.offset().left,ac=Math.max(ag.pageX,ah.startX)-Y.container.offset().left,af=(Y.high-Y.low),ae=Y.viewport_container.width();Y.update_location(Math.round(ad/ae*af)+Y.low,Math.round(ac/ae*af)+Y.low)}).bind("dragend",function(ah,ai){var ad=Math.min(ah.pageX,ai.startX),ac=Math.max(ah.pageX,ai.startX),af=(Y.high-Y.low),ae=Y.viewport_container.width(),ag=Y.low;Y.low=Math.round(ad/ae*af)+ag;Y.high=Math.round(ac/ae*af)+ag;$(ai.proxy).remove();Y.request_redraw()});this.add_label_track(new V(this,{content_div:this.top_labeltrack}));this.add_label_track(new V(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){Y.resize_window()},500)});$(document).bind("redraw",function(){Y.redraw()});this.reset();$(window).trigger("resize")},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(Z,ab,Y,ac){if(this.timer){clearTimeout(this.timer)}if(ac){var aa=this;this.timer=setTimeout(function(){aa.trigger("navigate",Z+":"+ab+"-"+Y)},500)}else{view.trigger("navigate",Z+":"+ab+"-"+Y)}},update_location:function(Y,aa){this.location_span.text(commatize(Y)+" - "+commatize(aa));this.nav_input.val(this.chrom+":"+commatize(Y)+"-"+commatize(aa));var Z=view.chrom_select.val();if(Z!==""){this.trigger_navigate(Z,view.low,view.high,true)}},load_chroms:function(aa){aa.num=t;aa.dbkey=this.dbkey;var Y=this,Z=$.Deferred();$.ajax({url:chrom_url,data:aa,dataType:"json",success:function(ac){if(ac.chrom_info.length===0){alert("Invalid chromosome: "+aa.chrom);return}if(ac.reference){Y.add_label_track(new x(Y))}Y.chrom_data=ac.chrom_info;var af='<option value="">Select Chrom/Contig</option>';for(var ae=0,ab=Y.chrom_data.length;ae<ab;ae++){var ad=Y.chrom_data[ae].chrom;af+='<option value="'+ad+'">'+ad+"</option>"}if(ac.prev_chroms){af+='<option value="previous">Previous '+t+"</option>"}if(ac.next_chroms){af+='<option value="next">Next '+t+"</option>"}Y.chrom_select.html(af);Y.chrom_start_index=ac.start_index;Z.resolve(ac)},error:function(){alert("Could not load chroms for this dbkey:",Y.dbkey)}});return Z},change_chrom:function(ad,Z,af){var aa=this;if(!aa.chrom_data){aa.load_chroms_deferred.then(function(){aa.change_chrom(ad,Z,af)});return}if(!ad||ad==="None"){return}if(ad==="previous"){aa.load_chroms({low:this.chrom_start_index-t});return}if(ad==="next"){aa.load_chroms({low:this.chrom_start_index+t});return}var ae=$.grep(aa.chrom_data,function(ag,ah){return ag.chrom===ad})[0];if(ae===undefined){aa.load_chroms({chrom:ad},function(){aa.change_chrom(ad,Z,af)});return}else{if(ad!==aa.chrom){aa.chrom=ad;aa.chrom_select.val(aa.chrom);aa.max_high=ae.len-1;aa.reset();aa.request_redraw(true);for(var ac=0,Y=aa.drawables.length;ac<Y;ac++){var ab=aa.drawables[ac];if(ab.init){ab.init()}}if(aa.reference_track){aa.reference_track.init()}}if(Z!==undefined&&af!==undefined){aa.low=Math.max(Z,0);aa.high=Math.min(af,aa.max_high)}else{aa.low=0;aa.high=aa.max_high}aa.reset_overview();aa.request_redraw()}},go_to:function(ac){ac=ac.replace(/ |,/g,"");var ag=this,Y,ab,Z=ac.split(":"),ae=Z[0],af=Z[1];if(af!==undefined){try{var ad=af.split("-");Y=parseInt(ad[0],10);ab=parseInt(ad[1],10)}catch(aa){return false}}ag.change_chrom(ae,Y,ab)},move_fraction:function(aa){var Y=this;var Z=Y.high-Y.low;this.move_delta(aa*Z)},move_delta:function(ab){var Y=this;var aa=Y.high-Y.low;if(Y.low-ab<Y.max_low){Y.low=Y.max_low;Y.high=Y.max_low+aa}else{if(Y.high-ab>Y.max_high){Y.high=Y.max_high;Y.low=Y.max_high-aa}else{Y.high-=ab;Y.low-=ab}}Y.request_redraw();var Z=Y.chrom_select.val();this.trigger_navigate(Z,Y.low,Y.high,true)},add_drawable:function(Y){v.prototype.add_drawable.call(this,Y);Y.init();this.changed();this.update_intro_div()},add_label_track:function(Y){Y.view=this;Y.init();this.label_tracks.push(Y)},remove_drawable:function(aa,Z){v.prototype.remove_drawable.call(this,aa);if(Z){var Y=this;aa.container_div.hide(0,function(){$(this).remove();Y.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ag,Y,af,ah){var ae=this,ad=(ah?[ah]:ae.drawables),aa;var Z;for(var ac=0;ac<ad.length;ac++){Z=ad[ac];aa=-1;for(var ab=0;ab<ae.tracks_to_be_redrawn.length;ab++){if(ae.tracks_to_be_redrawn[ab][0]===Z){aa=ab;break}}if(aa<0){ae.tracks_to_be_redrawn.push([Z,Y,af])}else{ae.tracks_to_be_redrawn[ac][1]=Y;ae.tracks_to_be_redrawn[ac][2]=af}}if(!this.requested_redraw){requestAnimationFrame(function(){ae._redraw(ag)});this.requested_redraw=true}},_redraw:function(ai){this.requested_redraw=false;var af=this.low,ab=this.high;if(af<this.max_low){af=this.max_low}if(ab>this.max_high){ab=this.max_high}var ah=this.high-this.low;if(this.high!==0&&ah<this.min_separation){ab=af+this.min_separation}this.low=Math.floor(af);this.high=Math.ceil(ab);this.update_location(this.low,this.high);this.resolution_b_px=(this.high-this.low)/this.viewport_container.width();this.resolution_px_b=this.viewport_container.width()/(this.high-this.low);var Y=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ae=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var aj=13;this.overview_box.css({left:Y,width:Math.max(aj,ae)}).show();if(ae<aj){this.overview_box.css("left",Y-(aj-ae)/2)}if(this.overview_highlight){this.overview_highlight.css({left:Y,width:ae})}if(!ai){var aa,Z,ag;for(var ac=0,ad=this.tracks_to_be_redrawn.length;ac<ad;ac++){aa=this.tracks_to_be_redrawn[ac][0];Z=this.tracks_to_be_redrawn[ac][1];ag=this.tracks_to_be_redrawn[ac][2];if(aa){aa._draw(Z,ag)}}this.tracks_to_be_redrawn=[];for(ac=0,ad=this.label_tracks.length;ac<ad;ac++){this.label_tracks[ac]._draw()}}},zoom_in:function(Z,aa){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var ab=this.high-this.low,ac=ab/2+this.low,Y=(ab/this.zoom_factor)/2;if(Z){ac=Z/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ac-Y);this.high=Math.round(ac+Y);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var Z=this.high-this.low,aa=Z/2+this.low,Y=(Z*this.zoom_factor)/2;this.low=Math.round(aa-Y);this.high=Math.round(aa+Y);this.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(aa){if(this.overview_drawable){if(this.overview_drawable.dataset_id===aa.dataset_id){return}this.overview_viewport.find(".track").remove()}var Z=aa.copy({content_div:this.overview_viewport}),Y=this;Z.header_div.hide();Z.is_overview=true;Y.overview_drawable=Z;this.overview_drawable.postdraw_actions=function(){Y.overview_highlight.show().height(Y.overview_drawable.content_div.height());Y.overview_viewport.height(Y.overview_drawable.content_div.height()+Y.overview_box.outerHeight());Y.overview_close.show();Y.resize_window()};Y.overview_drawable.request_draw();this.changed()},reset_overview:function(){$(".tipsy").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 q=function(aa,af,ab){this.track=aa;this.name=af.name;this.params=[];var am=af.params;for(var ac=0;ac<am.length;ac++){var ah=am[ac],Z=ah.name,al=ah.label,ad=unescape(ah.html),an=ah.value,aj=ah.type;if(aj==="number"){this.params.push(new e(Z,al,ad,(Z in ab?ab[Z]:an),ah.min,ah.max))}else{if(aj==="select"){this.params.push(new J(Z,al,ad,(Z in ab?ab[Z]:an)))}else{console.log("WARNING: unrecognized tool parameter type:",Z,aj)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(ap){ap.stopPropagation()}).click(function(ap){ap.stopPropagation()}).bind("dblclick",function(ap){ap.stopPropagation()});var ak=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var ai=this.params;var ag=this;$.each(this.params,function(aq,au){var at=$("<div>").addClass("param-row").appendTo(ag.parent_div);var ap=$("<div>").addClass("param-label").text(au.label).appendTo(at);var ar=$("<div/>").addClass("param-input").html(au.html).appendTo(at);ar.find(":input").val(au.value);$("<div style='clear: both;'/>").appendTo(at)});this.parent_div.find("input").click(function(){$(this).select()});var ao=$("<div>").addClass("param-row").appendTo(this.parent_div);var ae=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(ao);var Y=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(ao);Y.click(function(){ag.run_on_region()});ae.click(function(){ag.run_on_dataset()});if("visible" in ab&&ab.visible){this.parent_div.show()}};o(q.prototype,{update_params:function(){for(var Y=0;Y<this.params.length;Y++){this.params[Y].update_value()}},state_dict:function(){var Z={};for(var Y=0;Y<this.params.length;Y++){Z[this.params[Y].name]=this.params[Y].value}Z.visible=this.parent_div.is(":visible");return Z},get_param_values_dict:function(){var Y={};this.parent_div.find(":input").each(function(){var Z=$(this).attr("name"),aa=$(this).val();Y[Z]=aa});return Y},get_param_values:function(){var Y=[];this.parent_div.find(":input").each(function(){var Z=$(this).attr("name"),aa=$(this).val();if(Z){Y[Y.length]=aa}});return Y},run_on_dataset:function(){var Y=this;Y.run({target_dataset_id:this.track.original_dataset_id,tool_id:Y.name},null,function(Z){show_modal(Y.name+" is Running",Y.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var Z={target_dataset_id:this.track.original_dataset_id,action:"rerun",tool_id:this.name,regions:[{chrom:this.track.view.chrom,start:this.track.view.low,end:this.track.view.high}]},ad=this.track,aa=Z.tool_id+ad.tool_region_and_parameters_str(Z.chrom,Z.low,Z.high),Y;if(ad.container===view){var ac=new L(view,view,{name:this.name});var ab=ad.container.replace_drawable(ad,ac,false);ac.container_div.insertBefore(ad.view.content_div.children()[ab]);ac.add_drawable(ad);ad.container_div.appendTo(ac.content_div);Y=ac}else{Y=ad.container}var ae=new ad.constructor(view,Y,{name:aa,hda_ldda:"hda"});ae.init_for_tool_data();ae.change_mode(ad.mode);ae.set_filters_manager(ad.filters_manager.copy(ae));ae.update_icons();Y.add_drawable(ae);ae.tiles_div.text("Starting job.");this.update_params();this.run(Z,ae,function(af){ae.set_dataset(new Dataset(af));ae.tiles_div.text("Running job.");ae.init()})},run:function(Y,aa,ab){Y.inputs=this.get_param_values_dict();var Z=new ServerStateDeferred({ajax_settings:{url:galaxy_paths.get("tool_url"),data:JSON.stringify(Y),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ac){return ac!=="pending"}});$.when(Z.go()).then(function(ac){if(ac==="no converter"){aa.container_div.addClass("error");aa.content_div.text(F)}else{if(ac.error){aa.container_div.addClass("error");aa.content_div.text(u+ac.message)}else{ab(ac)}}})}});var J=function(Z,Y,aa,ab){this.name=Z;this.label=Y;this.html=$(aa);this.value=ab};o(J.prototype,{update_value:function(){this.value=$(this.html).val()}});var e=function(aa,Z,ac,ad,ab,Y){J.call(this,aa,Z,ac,ad);this.min=ab;this.max=Y};o(e.prototype,J.prototype,{update_value:function(){J.prototype.update_value.call(this);this.value=parseFloat(this.value)}});var f=function(Y){this.manager=null;this.name=Y.name;this.index=Y.index;this.tool_id=Y.tool_id;this.tool_exp_name=Y.tool_exp_name};o(f.prototype,{to_dict:function(){return{name:this.name,index:this.index,tool_id:this.tool_id,tool_exp_name:this.tool_exp_name}}});var P=function(ah){f.call(this,ah);this.low=("low" in ah?ah.low:-Number.MAX_VALUE);this.high=("high" in ah?ah.high:Number.MAX_VALUE);this.min=("min" in ah?ah.min:Number.MAX_VALUE);this.max=("max" in ah?ah.max:-Number.MAX_VALUE);this.container=null;this.slider=null;this.slider_label=null;var ad=function(ai,aj,ak){ai.click(function(){var ap=aj.text(),an=parseFloat(ak.slider("option","max")),am=(an<=1?4:an<=1000000?an.toString().length:6),ao=false,al=$(this).parents(".slider-row");al.addClass("input");if(ak.slider("option","values")){am=2*am+1;ao=true}aj.text("");$("<input type='text'/>").attr("size",am).attr("maxlength",am).attr("value",ap).appendTo(aj).focus().select().click(function(aq){aq.stopPropagation()}).blur(function(){$(this).remove();aj.text(ap);al.removeClass("input")}).keyup(function(av){if(av.keyCode===27){$(this).trigger("blur")}else{if(av.keyCode===13){var at=ak.slider("option","min"),aq=ak.slider("option","max"),au=function(aw){return(isNaN(aw)||aw>aq||aw<at)},ar=$(this).val();if(!ao){ar=parseFloat(ar);if(au(ar)){alert("Parameter value must be in the range ["+at+"-"+aq+"]");return $(this)}}else{ar=ar.split("-");ar=[parseFloat(ar[0]),parseFloat(ar[1])];if(au(ar[0])||au(ar[1])){alert("Parameter value must be in the range ["+at+"-"+aq+"]");return $(this)}}ak.slider((ao?"values":"value"),ar);al.removeClass("input")}}})})};var Z=this;Z.parent_div=$("<div/>").addClass("filter-row slider-row");var Y=$("<div/>").addClass("elt-label").appendTo(Z.parent_div),af=$("<span/>").addClass("slider-name").text(Z.name+" ").appendTo(Y),aa=$("<span/>").text(this.low+"-"+this.high),ab=$("<span/>").addClass("slider-value").appendTo(Y).append("[").append(aa).append("]");Z.values_span=aa;var ae=$("<div/>").addClass("slider").appendTo(Z.parent_div);Z.control_element=$("<div/>").attr("id",Z.name+"-filter-control").appendTo(ae);var ac=[0,0];Z.control_element.slider({range:true,min:this.min,max:this.max,step:this.get_slider_step(this.min,this.max),values:[this.low,this.high],slide:function(ai,aj){Z.slide(ai,aj)},change:function(ai,aj){Z.control_element.slider("option","slide").call(Z.control_element,ai,aj)}});Z.slider=Z.control_element;Z.slider_label=aa;ad(ab,aa,Z.control_element);var ag=$("<div/>").addClass("display-controls").appendTo(Z.parent_div);this.transparency_icon=create_action_icon("Use filter for data transparency","layer-transparent",function(){if(Z.manager.alpha_filter!==Z){Z.manager.alpha_filter=Z;Z.manager.parent_div.find(".layer-transparent").removeClass("active").hide();Z.transparency_icon.addClass("active").show()}else{Z.manager.alpha_filter=null;Z.transparency_icon.removeClass("active")}Z.manager.track.request_draw(true,true)}).appendTo(ag).hide();this.height_icon=create_action_icon("Use filter for data height","arrow-resize-090",function(){if(Z.manager.height_filter!==Z){Z.manager.height_filter=Z;Z.manager.parent_div.find(".arrow-resize-090").removeClass("active").hide();Z.height_icon.addClass("active").show()}else{Z.manager.height_filter=null;Z.height_icon.removeClass("active")}Z.manager.track.request_draw(true,true)}).appendTo(ag).hide();Z.parent_div.hover(function(){Z.transparency_icon.show();Z.height_icon.show()},function(){if(Z.manager.alpha_filter!==Z){Z.transparency_icon.hide()}if(Z.manager.height_filter!==Z){Z.height_icon.hide()}});$("<div style='clear: both;'/>").appendTo(Z.parent_div)};o(P.prototype,{to_dict:function(){var Y=f.prototype.to_dict.call(this);return o(Y,{type:"number",min:this.min,max:this.max,low:this.low,high:this.high})},copy:function(){return new P({name:this.name,index:this.index,tool_id:this.tool_id,tool_exp_name:this.tool_exp_name})},get_slider_step:function(aa,Y){var Z=Y-aa;return(Z<=2?0.01:1)},slide:function(Z,aa){var Y=aa.values;this.values_span.text(Y[0]+"-"+Y[1]);this.low=Y[0];this.high=Y[1];this.manager.track.request_draw(true,true)},applies_to:function(Y){if(Y.length>this.index){return true}return false},_keep_val:function(Y){return(isNaN(Y)||(Y>=this.low&&Y<=this.high))},keep:function(Z){if(!this.applies_to(Z)){return true}var ab=this;var ac=Z[this.index];if(ac instanceof Array){var aa=true;for(var Y=0;Y<ac.length;Y++){if(!this._keep_val(ac[Y])){aa=false;break}}return aa}else{return this._keep_val(Z[this.index])}},update_attrs:function(ab){var Y=false;if(!this.applies_to(ab)){return Y}var Z=ab[this.index];if(!(Z instanceof Array)){Z=[Z]}for(var aa=0;aa<Z.length;aa++){var ac=Z[aa];if(ac<this.min){this.min=Math.floor(ac);Y=true}if(ac>this.max){this.max=Math.ceil(ac);Y=true}}return Y},update_ui_elt:function(){if(this.min<this.max){this.parent_div.show()}else{this.parent_div.hide()}var Z=this.slider.slider("option","min"),Y=this.slider.slider("option","max");if(this.min<Z||this.max>Y){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",this.get_slider_step(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var U=function(aa,ag){this.track=aa;this.alpha_filter=null;this.height_filter=null;this.filters=[];this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(ai){ai.stopPropagation()}).click(function(ai){ai.stopPropagation()}).bind("dblclick",function(ai){ai.stopPropagation()}).bind("keydown",function(ai){ai.stopPropagation()});if(ag&&"filters" in ag){var Y=("alpha_filter" in ag?ag.alpha_filter:null),ab=("height_filter" in ag?ag.height_filter:null),ad=ag.filters,Z;for(var ae=0;ae<ad.length;ae++){if(ad[ae].type==="number"){Z=new P(ad[ae]);this.add_filter(Z);if(Z.name===Y){this.alpha_filter=Z;Z.transparency_icon.addClass("active").show()}if(Z.name===ab){this.height_filter=Z;Z.height_icon.addClass("active").show()}}else{console.log("ERROR: unsupported filter: ",name,type)}}if("visible" in ag&&ag.visible){this.parent_div.show()}}if(this.filters.length!==0){var ah=$("<div/>").addClass("param-row").appendTo(this.parent_div);var af=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(ah);var ac=this;af.click(function(){ac.run_on_dataset()})}};o(U.prototype,{show:function(){this.parent_div.show()},hide:function(){this.parent_div.hide()},toggle:function(){this.parent_div.toggle()},visible:function(){return this.parent_div.is(":visible")},to_dict:function(){var ab={},aa=[],Z;for(var Y=0;Y<this.filters.length;Y++){Z=this.filters[Y];aa.push(Z.to_dict())}ab.filters=aa;ab.alpha_filter=(this.alpha_filter?this.alpha_filter.name:null);ab.height_filter=(this.height_filter?this.height_filter.name:null);ab.visible=this.parent_div.is(":visible");return ab},copy:function(Z){var aa=new U(Z);for(var Y=0;Y<this.filters.length;Y++){aa.add_filter(this.filters[Y].copy())}return aa},add_filter:function(Y){Y.manager=this;this.parent_div.append(Y.parent_div);this.filters.push(Y)},remove_all:function(){this.filters=[];this.parent_div.children().remove()},init_filters:function(){for(var Y=0;Y<this.filters.length;Y++){var Z=this.filters[Y];Z.update_ui_elt()}},clear_filters:function(){for(var Y=0;Y<this.filters.length;Y++){var Z=this.filters[Y];Z.slider.slider("option","values",[Z.min,Z.max])}this.alpha_filter=null;this.height_filter=null;this.parent_div.find(".icon-button").hide()},run_on_dataset:function(){var ae=function(ai,ag,ah){if(!(ag in ai)){ai[ag]=ah}return ai[ag]};var ad={},af,Y;for(var ac=0;ac<this.filters.length;ac++){af=this.filters[ac];if(af.tool_id){if(af.min!==af.low){Y=ae(ad,af.tool_id,[]);Y[Y.length]=af.tool_exp_name+" >= "+af.low}if(af.max!==af.high){Y=ae(ad,af.tool_id,[]);Y[Y.length]=af.tool_exp_name+" <= "+af.high}}}var Z=[];for(var ab in ad){Z[Z.length]=[ab,ad[ab]]}(function aa(am,aj){var ah=aj[0],ai=ah[0],al=ah[1],ak="("+al.join(") and (")+")",ag={cond:ak,input:am,target_dataset_id:am,tool_id:ai},aj=aj.slice(1);$.getJSON(run_tool_url,ag,function(an){if(an.error){show_modal("Filter Dataset","Error running tool "+ai,{Close:hide_modal})}else{if(aj.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{aa(an.dataset_id,aj)}}})})(this.track.dataset_id,Z)}});var y=function(Y,Z){H.Scaler.call(this,Z);this.filter=Y};y.prototype.gen_val=function(Y){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(Y[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var B=function(Y){this.track=Y.track;this.params=Y.params;this.values={};this.restore_values((Y.saved_values?Y.saved_values:{}));this.onchange=Y.onchange};o(B.prototype,{restore_values:function(Y){var Z=this;$.each(this.params,function(aa,ab){if(Y[ab.key]!==undefined){Z.values[ab.key]=Y[ab.key]}else{Z.values[ab.key]=ab.default_value}})},build_form:function(){var ab=this;var Y=$("<div />");var aa;function Z(af,ac){for(var aj=0;aj<af.length;aj++){aa=af[aj];if(aa.hidden){continue}var ad="param_"+aj;var an=ab.values[aa.key];var aq=$("<div class='form-row' />").appendTo(ac);aq.append($("<label />").attr("for",ad).text(aa.label+":"));if(aa.type==="bool"){aq.append($('<input type="checkbox" />').attr("id",ad).attr("name",ad).attr("checked",an))}else{if(aa.type==="text"){aq.append($('<input type="text"/>').attr("id",ad).val(an).click(function(){$(this).select()}))}else{if(aa.type==="select"){var al=$("<select />").attr("id",ad);for(var ah=0;ah<aa.options.length;ah++){$("<option/>").text(aa.options[ah].label).attr("value",aa.options[ah].value).appendTo(al)}al.val(an);aq.append(al)}else{if(aa.type==="color"){var ap=$("<div/>").appendTo(aq),ak=$("<input />").attr("id",ad).attr("name",ad).val(an).css("float","left").appendTo(ap).click(function(at){$(".tipsy").hide();var ar=$(this).siblings(".tipsy");ar.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(ar).height()/2)+($(this).height()/2)}).show();ar.click(function(au){au.stopPropagation()});$(document).bind("click.color-picker",function(){ar.hide();$(document).unbind("click.color-picker")});at.stopPropagation()}),ai=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(ap).attr("title","Set new random color").tipsy({gravity:"s"}),am=$("<div class='tipsy tipsy-west' style='position: absolute;' />").appendTo(ap).hide(),ae=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(am),ao=$("<div/>").appendTo(ae),ag=$.farbtastic(ao,{width:100,height:100,callback:ak,color:an});ap.append($("<div/>").css("clear","both"));(function(ar){ai.click(function(){ar.setColor(get_random_color())})})(ag)}else{aq.append($("<input />").attr("id",ad).attr("name",ad).val(an))}}}}if(aa.help){aq.append($("<div class='help'/>").text(aa.help))}}}Z(this.params,Y);return Y},update_from_form:function(Y){var aa=this;var Z=false;$.each(this.params,function(ab,ad){if(!ad.hidden){var ae="param_"+ab;var ac=Y.find("#"+ae).val();if(ad.type==="float"){ac=parseFloat(ac)}else{if(ad.type==="int"){ac=parseInt(ac)}else{if(ad.type==="bool"){ac=Y.find("#"+ae).is(":checked")}}}if(ac!==aa.values[ad.key]){aa.values[ad.key]=ac;Z=true}}});if(Z){this.onchange();this.track.changed()}}});var b=function(Y,ac,aa,Z,ab){this.track=Y;this.region=ac;this.low=ac.get("start");this.high=ac.get("end");this.resolution=aa;this.html_elt=$("<div class='track-tile'/>").append(Z).height($(Z).attr("height"));this.data=ab;this.stale=false};b.prototype.predisplay_actions=function(){};var j=function(Y,ad,aa,Z,ab,ac){b.call(this,Y,ad,aa,Z,ab);this.max_val=ac};o(j.prototype,b.prototype);var K=function(ab,aj,ac,aa,ae,al,af,am,Z,ai){b.call(this,ab,aj,ac,aa,ae);this.mode=af;this.all_slotted=Z;this.feature_mapper=ai;this.has_icons=false;if(am){this.has_icons=true;var ag=this;aa=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:z-1,width:aa.width}).prependTo(this.html_elt);var ah=new GenomeRegion({chrom:ab.view.chrom,start:this.low,end:this.high}),ak=ae.length,ad=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ak+" features in this region were obtained from server. Click to get more data including depth").tipsy({gravity:"s"}).appendTo(message_div),Y=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ak+" features in this region were obtained from server. Click to get more data excluding depth").tipsy({gravity:"s"}).appendTo(message_div);ad.click(function(){ag.stale=true;ab.data_manager.get_more_data(ah,ab.mode,ag.resolution,{},ab.data_manager.DEEP_DATA_REQ);$(".tipsy").hide();ab.request_draw(true)}).dblclick(function(an){an.stopPropagation()});Y.click(function(){ag.stale=true;ab.data_manager.get_more_data(ah,ab.mode,ag.resolution,{},ab.data_manager.BROAD_DATA_REQ);$(".tipsy").hide();ab.request_draw(true)}).dblclick(function(an){an.stopPropagation()})}};o(K.prototype,b.prototype);K.prototype.predisplay_actions=function(){var Z=this,Y={};if(Z.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(ak){if(!this.hovered){return}var af=$(this).offset(),aj=ak.pageX-af.left,ai=ak.pageY-af.top,ao=Z.feature_mapper.get_feature_data(aj,ai),ag=(ao?ao[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!ag||$(this).attr("id")!==ag.toString()){$(this).remove()}});if(ao){var ab=Y[ag];if(!ab){var ag=ao[0],al={name:ao[3],start:ao[1],end:ao[2],strand:ao[4]},ae=Z.track.filters_manager.filters,ad;for(var ah=0;ah<ae.length;ah++){ad=ae[ah];al[ad.name]=ao[ad.index]}var ab=$("<div/>").attr("id",ag).addClass("feature-popup"),ap=$("<table/>"),an,am,aq;for(an in al){am=al[an];aq=$("<tr/>").appendTo(ap);$("<th/>").appendTo(aq).text(an);$("<td/>").attr("align","left").appendTo(aq).text(typeof(am)==="number"?T(am,2):am)}ab.append($("<div class='feature-popup-inner'>").append(ap));Y[ag]=ab}ab.appendTo($(this).parents(".track-content").children(".overlay"));var ac=aj+parseInt(Z.html_elt.css("left"))-ab.width()/2,aa=ai+parseInt(Z.html_elt.css("top"))+7;ab.css("left",ac+"px").css("top",aa+"px")}else{if(!ak.isPropagationStopped()){ak.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ak)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var h=function(aa,Z,ac){o(ac,{drag_handle_class:"draghandle"});p.call(this,aa,Z,ac);this.data_url=("data_url" in ac?ac.data_url:default_data_url);this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in ac?ac.data_query_wait:G);this.dataset_check_url=("converted_datasets_state_url" in ac?ac.converted_datasets_state_url:converted_datasets_state_url);var Y=this,ab=new Dataset({id:ac.dataset_id,hda_ldda:ac.hda_ldda});this.data_manager=("data_manager" in ac?ac.data_manager:new GenomeDataManager({dataset:ab,data_url:Y.data_url,dataset_state_url:Y.dataset_check_url,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 ac)||ac.resize){this.add_resize_handle()}}};o(h.prototype,p.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},p.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(Y){Y.view.set_overview(Y)}},p.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(Y){if(Y.filters_manager.visible()){Y.filters_manager.clear_filters()}else{Y.filters_manager.init_filters()}Y.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(Y){Y.dynamic_tool_div.toggle();if(Y.dynamic_tool_div.is(":visible")){Y.set_name(Y.name+Y.tool_region_and_parameters_str())}else{Y.revert_name()}$(".tipsy").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(Y){var ab='<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>',aa=_.template(ab,{track:Y});var ad=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},Z=function(){var af=$('select[name="regions"] option:selected').val(),ah,ae=new GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),ag=_.map($(".bookmark"),function(ai){return new GenomeRegion({from_str:$(ai).children(".position").text()})});if(af==="cur"){ah=[ae]}else{if(af==="bookmarks"){ah=ag}else{ah=[ae].concat(ag)}}hide_modal();window.location.href=galaxy_paths.get("paramamonster_url")+"?"+$.param({dataset_id:Y.dataset_id,hda_ldda:Y.hda_ldda,regions:JSON.stringify(new Backbone.Collection(ah).toJSON())})},ac=function(ae){if((ae.keyCode||ae.which)===27){ad()}else{if((ae.keyCode||ae.which)===13){Z()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",aa,{No:ad,Yes:Z})}},p.prototype.action_icons_def[2]],can_draw:function(){if(this.dataset_id&&p.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 Y=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(Y)}this.name_div=$("<div/>").addClass("track-name").appendTo(Y).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return Y},on_resize:function(){},add_resize_handle:function(){var Y=this;var ab=false;var aa=false;var Z=$("<div class='track-resize'>");$(Y.container_div).hover(function(){if(Y.content_visible){ab=true;Z.show()}},function(){ab=false;if(!aa){Z.hide()}});Z.hide().bind("dragstart",function(ac,ad){aa=true;ad.original_height=$(Y.content_div).height()}).bind("drag",function(ad,ae){var ac=Math.min(Math.max(ae.original_height+ae.deltaY,Y.min_height_px),Y.max_height_px);$(Y.tiles_div).css("height",ac);Y.visible_height_px=(Y.max_height_px===ac?0:ac);Y.on_resize()}).bind("dragend",function(ac,ad){Y.tile_cache.clear();aa=false;if(!ab){Z.hide()}Y.config.values.height=Y.visible_height_px;Y.changed()}).appendTo(Y.container_div)},set_display_modes:function(ab,ae){this.display_modes=ab;this.mode=(ae?ae:(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 Z=this,ac={};for(var aa=0,Y=Z.display_modes.length;aa<Y;aa++){var ad=Z.display_modes[aa];ac[ad]=function(af){return function(){Z.change_mode(af);Z.icons_div.show();Z.container_div.mouseleave(function(){Z.icons_div.hide()})}}(ad)}make_popupmenu(this.action_icons.mode_icon,ac)},build_action_icons:function(){p.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 V){return"LabelTrack"}else{if(this instanceof x){return"ReferenceTrack"}else{if(this instanceof i){return"LineTrack"}else{if(this instanceof Q){return"ReadTrack"}else{if(this instanceof N){return"VcfTrack"}else{if(this instanceof g){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(){var Z=this;Z.enabled=false;Z.tile_cache.clear();Z.data_manager.clear();Z.content_div.css("height","auto");Z.tiles_div.children().remove();Z.container_div.removeClass("nodata error pending");if(!Z.dataset_id){return}var Y=$.Deferred();$.getJSON(this.dataset_check_url,{hda_ldda:Z.hda_ldda,dataset_id:Z.dataset_id,chrom:Z.view.chrom},function(aa){if(!aa||aa==="error"||aa.kind==="error"){Z.container_div.addClass("error");Z.tiles_div.text(n);if(aa.message){var ab=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+aa.message+"</pre>",{Close:hide_modal})});Z.tiles_div.append(ab)}}else{if(aa==="no converter"){Z.container_div.addClass("error");Z.tiles_div.text(F)}else{if(aa==="no data"||(aa.data!==undefined&&(aa.data===null||aa.data.length===0))){Z.container_div.addClass("nodata");Z.tiles_div.text(A)}else{if(aa==="pending"){Z.container_div.addClass("pending");Z.tiles_div.html(s);setTimeout(function(){Z.init()},Z.data_query_wait)}else{if(aa==="data"||aa.status==="data"){if(aa.valid_chroms){Z.valid_chroms=aa.valid_chroms;Z.update_icons()}Z.tiles_div.text(S);if(Z.view.chrom){Z.tiles_div.text("");Z.tiles_div.css("height",Z.visible_height_px+"px");Z.enabled=true;$.when(Z.predraw_init()).done(function(){Y.resolve();Z.container_div.removeClass("nodata error pending");Z.request_draw()})}else{Y.resolve()}}}}}}});this.update_icons();return Y},predraw_init:function(){}});var I=function(aa,Z,ab){h.call(this,aa,Z,ab);var Y=this,aa=Y.view;l(Y.container_div,Y.drag_handle_class,".group",Y);this.filters_manager=new U(this,("filters" in ab?ab.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=("tool" in ab&&ab.tool?new q(this,ab.tool,ab.tool_state):null);this.tile_cache=new Cache(M);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(ab.mode){this.change_mode(ab.mode)}};o(I.prototype,p.prototype,h.prototype,{action_icons_def:h.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(Y){$(".tipsy").remove();Y.slotters[Y.view.resolution_px_b].max_rows*=2;Y.request_draw(true)},hide:true}]),copy:function(Y){var Z=this.to_dict();o(Z,{data_manager:this.data_manager});var aa=new this.constructor(this.view,Y,Z);aa.change_mode(this.mode);aa.enabled=this.enabled;return aa},set_filters_manager:function(Y){this.filters_manager=Y;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},change_mode:function(Z){var Y=this;Y.mode=Z;Y.config.values.mode=Z;Y.tile_cache.clear();Y.request_draw();this.action_icons.mode_icon.attr("title","Set display mode (now: "+Y.mode+")");return Y},update_icons:function(){var Y=this;if(Y.filters_available){Y.action_icons.filters_icon.show()}else{Y.action_icons.filters_icon.hide()}if(Y.tool){Y.action_icons.tools_icon.show();Y.action_icons.param_space_viz_icon.show()}else{Y.action_icons.tools_icon.hide();Y.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(Z,aa,Y){return Z+"_"+aa+"_"+Y},request_draw:function(Z,Y){this.view.request_redraw(false,Z,Y,this)},before_draw:function(){},_draw:function(Z,aj){if(!this.can_draw()){return}var ah=this.view.low,ad=this.view.high,af=ad-ah,aa=this.view.container.width(),al=this.view.resolution_px_b,ac=this.view.resolution_b_px;if(this.is_overview){ah=this.view.max_low;ad=this.view.max_high;ac=Math.pow(RESOLUTION,Math.ceil(Math.log((view.max_high-view.max_low)/O)/Math.log(RESOLUTION)));al=aa/(view.max_high-view.max_low)}this.before_draw();this.tiles_div.children().addClass("remove");var Y=Math.floor(ah/(ac*O)),ag=true,ak=[],ae=function(am){return(am&&"track" in am)};while((Y*O*ac)<ad){var ai=this.draw_helper(Z,aa,Y,ac,this.tiles_div,al);if(ae(ai)){ak.push(ai)}else{ag=false}Y+=1}if(!aj){this.tiles_div.children(".remove").removeClass("remove").remove()}var ab=this;if(ag){this.tiles_div.children(".remove").remove();ab.postdraw_actions(ak,aa,al,aj)}},postdraw_actions:function(ab,ac,ae,Y){var aa=this;var ad=false;for(var Z=0;Z<ab.length;Z++){if(ab[Z].has_icons){ad=true;break}}if(ad){for(var Z=0;Z<ab.length;Z++){tile=ab[Z];if(!tile.has_icons){tile.html_elt.css("padding-top",z)}}}},draw_helper:function(Y,ak,ap,an,ad,ae,al){var aj=this,at=this._gen_tile_cache_key(ak,ae,ap),ab=this._get_tile_bounds(ap,an);if(!al){al={}}var ar=(Y?undefined:aj.tile_cache.get_elt(at));if(ar){aj.show_tile(ar,ad,ae);return ar}var ah=true;var ao=aj.data_manager.get_data(ab,aj.mode,an,aj.data_url_extra_params);if(is_deferred(ao)){ah=false}var af;if(view.reference_track&&ae>view.canvas_manager.char_width_px){af=view.reference_track.data_manager.get_data(ab,aj.mode,an,view.reference_track.data_url_extra_params);if(is_deferred(af)){ah=false}}if(ah){o(ao,al.more_tile_data);var ag=aj.mode;if(ag==="Auto"){ag=aj.get_mode(ao);aj.update_auto_mode(ag)}var aa=aj.view.canvas_manager.new_canvas(),aq=ab.get("start"),Z=ab.get("end"),ak=Math.ceil((Z-aq)*ae)+aj.left_offset,ai=aj.get_canvas_height(ao,ag,ae,ak);aa.width=ak;aa.height=ai;var am=aa.getContext("2d");am.translate(this.left_offset,0);var ar=aj.draw_tile(ao,am,ag,an,ab,ae,af);if(ar!==undefined){aj.tile_cache.set_elt(at,ar);aj.show_tile(ar,ad,ae)}return ar}var ac=$.Deferred();$.when(ao,af).then(function(){view.request_redraw(false,false,false,aj);ac.resolve()});return ac},get_canvas_height:function(Y,aa,ab,Z){return this.visible_height_px},draw_tile:function(Y,Z,ad,ab,ac,ae,aa){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(aa,ac,ad){var Z=this,Y=aa.html_elt;aa.predisplay_actions();var ab=(aa.low-(this.is_overview?this.view.max_low:this.view.low))*ad;if(this.left_offset){ab-=this.left_offset}Y.css({position:"absolute",top:0,left:ab});if(Y.hasClass("remove")){Y.removeClass("remove")}else{ac.append(Y)}Z.after_show_tile(aa)},after_show_tile:function(Y){},_get_tile_bounds:function(Y,Z){var ab=Math.floor(Y*O*Z),ac=Math.ceil(O*Z),aa=(ab+ac<=this.view.max_high?ab+ac:this.view.max_high);return new GenomeRegion({chrom:this.view.chrom,start:ab,end:aa})},tool_region_and_parameters_str:function(aa,Y,ab){var Z=this,ac=(aa!==undefined&&Y!==undefined&&ab!==undefined?aa+":"+Y+"-"+ab:"all");return" - region=["+ac+"], parameters=["+Z.tool.get_param_values().join(", ")+"]"},data_and_mode_compatible:function(Y,Z){return true},can_subset:function(Y){return false},init_for_tool_data:function(){this.data_manager.set("data_url",raw_data_url);this.data_query_wait=1000;this.dataset_check_url=dataset_state_url;this.normal_postdraw_actions=this.postdraw_actions;this.postdraw_actions=function(aa,ab,ad,Y){var Z=this;Z.normal_postdraw_actions(aa,ab,ad,Y);Z.dataset_state_url=converted_datasets_state_url;Z.data_query_wait=G;var ac=new ServerStateDeferred({url:Z.dataset_state_url,url_params:{dataset_id:Z.dataset_id,hda_ldda:Z.hda_ldda},interval:Z.data_query_wait,success_fn:function(ae){return ae!=="pending"}});$.when(ac.go()).then(function(){Z.data_manager.set("data_url",default_data_url)});Z.postdraw_actions=Z.normal_postdraw_actions}}});var V=function(Z,Y){var aa={resize:false};h.call(this,Z,Y,aa);this.container_div.addClass("label-track")};o(V.prototype,h.prototype,{build_header_div:function(){},init:function(){this.enabled=true},_draw:function(){var aa=this.view,ab=aa.high-aa.low,ae=Math.floor(Math.pow(10,Math.floor(Math.log(ab)/Math.log(10)))),Y=Math.floor(aa.low/ae)*ae,ac=this.view.container.width(),Z=$("<div style='position: relative; height: 1.3em;'></div>");while(Y<aa.high){var ad=(Y-aa.low)/ab*ac;Z.append($("<div class='label'>"+commatize(Y)+"</div>").css({position:"absolute",left:ad-1}));Y+=ae}this.content_div.children(":first").remove();this.content_div.append(Z)}});var g=function(Z,Y,ac){I.call(this,Z,Y,ac);this.drawables=[];this.left_offset=0;if("drawables" in ac){var ab;for(var aa=0;aa<ac.drawables.length;aa++){ab=ac.drawables[aa];this.drawables[aa]=object_from_template(ab);if(ab.left_offset>this.left_offset){this.left_offset=ab.left_offset}}this.enabled=true}if(this.drawables.length!==0){this.set_display_modes(this.drawables[0].display_modes,this.drawables[0].mode)}this.update_icons();this.obj_type="CompositeTrack"};o(g.prototype,I.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(Y){$(".tipsy").remove();Y.show_group()}}].concat(I.prototype.action_icons_def),to_dict:v.prototype.to_dict,add_drawable:v.prototype.add_drawable,unpack_drawables:v.prototype.unpack_drawables,change_mode:function(Y){I.prototype.change_mode.call(this,Y);for(var Z=0;Z<this.drawables.length;Z++){this.drawables[Z].change_mode(Y)}},init:function(){var aa=[];for(var Z=0;Z<this.drawables.length;Z++){aa.push(this.drawables[Z].init())}var Y=this;$.when.apply($,aa).then(function(){Y.enabled=true;Y.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:p.prototype.can_draw,draw_helper:function(Z,an,au,aq,af,ah,ao){var am=this,ay=this._gen_tile_cache_key(an,ah,au),ad=this._get_tile_bounds(au,aq),av=ad.get("start"),aa=ad.get("end");if(!ao){ao={}}var ax=(Z?undefined:am.tile_cache.get_elt(ay));if(ax){am.show_tile(ax,af,ah);return ax}var ag=[],am,ak=true,ar,ai;for(var at=0;at<this.drawables.length;at++){am=this.drawables[at];ar=am.data_manager.get_data(av,aa,am.mode,aq,am.data_url_extra_params);if(is_deferred(ar)){ak=false}ag.push(ar);ai=null;if(view.reference_track&&ah>view.canvas_manager.char_width_px){ai=view.reference_track.data_manager.get_data(av,aa,am.mode,aq,view.reference_track.data_url_extra_params);if(is_deferred(ai)){ak=false}}ag.push(ai)}if(ak){o(ar,ao.more_tile_data);this.tile_predraw_init();var ac=am.view.canvas_manager.new_canvas(),ad=am._get_tile_bounds(au,aq),av=ad.get("start"),aa=ad.get("end"),aw=0,an=Math.ceil((aa-av)*ah)+this.left_offset,al=0,ab=[];var Y=0;for(var at=0;at<this.drawables.length;at++,aw+=2){am=this.drawables[at];ar=ag[aw];var aj=am.mode;if(aj==="Auto"){aj=am.get_mode(ar);am.update_auto_mode(aj)}ab.push(aj);Y=am.get_canvas_height(ar,aj,ah,an);if(Y>al){al=Y}}ac.width=an;ac.height=(ao.height?ao.height:al);aw=0;var ap=ac.getContext("2d");ap.translate(this.left_offset,0);ap.globalAlpha=0.5;ap.globalCompositeOperation="source-over";for(var at=0;at<this.drawables.length;at++,aw+=2){am=this.drawables[at];ar=ag[aw];ai=ag[aw+1];ax=am.draw_tile(ar,ap,ab[at],aq,ad,ah,ai)}this.tile_cache.set_elt(ay,ax);this.show_tile(ax,af,ah);return ax}var ae=$.Deferred(),am=this;$.when.apply($,ag).then(function(){view.request_redraw(false,false,false,am);ae.resolve()});return ae},show_group:function(){var ab=new L(this.view,this.container,{name:this.name}),Y;for(var aa=0;aa<this.drawables.length;aa++){Y=this.drawables[aa];ab.add_drawable(Y);Y.container=ab;ab.content_div.append(Y.container_div)}var Z=this.container.replace_drawable(this,ab,true);ab.request_draw()},tile_predraw_init:function(){var ab=Number.MAX_VALUE,Y=-ab,Z;for(var aa=0;aa<this.drawables.length;aa++){Z=this.drawables[aa];if(Z instanceof i){if(Z.prefs.min_value<ab){ab=Z.prefs.min_value}if(Z.prefs.max_value>Y){Y=Z.prefs.max_value}}}for(var aa=0;aa<this.drawables.length;aa++){Z=this.drawables[aa];Z.prefs.min_value=ab;Z.prefs.max_value=Y}},postdraw_actions:function(aa,ad,af,Z){I.prototype.postdraw_actions.call(this,aa,ad,af,Z);var ac=-1;for(var ab=0;ab<aa.length;ab++){var Y=aa[ab].html_elt.find("canvas").height();if(Y>ac){ac=Y}}for(var ab=0;ab<aa.length;ab++){var ae=aa[ab];if(ae.html_elt.find("canvas").height()!==ac){this.draw_helper(true,ad,ae.index,ae.resolution,ae.html_elt.parent(),af,{height:ac});ae.html_elt.remove()}}}});var x=function(Y){I.call(this,Y,{content_div:Y.top_labeltrack},{resize:false});Y.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=reference_url;this.data_url_extra_params={dbkey:Y.dbkey};this.data_manager=new ReferenceTrackDataManager({data_url:reference_url});this.hide_contents()};o(x.prototype,p.prototype,I.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},can_draw:p.prototype.can_draw,draw_tile:function(ag,ah,ac,ab,ae,ai){var aa=this;if(ai>this.view.canvas_manager.char_width_px){if(ag.data===null){this.hide_contents();return}var Z=ah.canvas;ah.font=ah.canvas.manager.default_font;ah.textAlign="center";ag=ag.data;for(var ad=0,af=ag.length;ad<af;ad++){var Y=Math.floor(ad*ai);ah.fillText(ag[ad],Y,10)}this.show_contents();return new b(aa,ae,ab,Z,ag)}this.hide_contents()}});var i=function(aa,Z,ab){var Y=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";I.call(this,aa,Z,ab);this.hda_ldda=ab.hda_ldda;this.dataset_id=ab.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;this.config=new B({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value: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:ab.prefs,onchange:function(){Y.set_name(Y.prefs.name);Y.vertical_range=Y.prefs.max_value-Y.prefs.min_value;Y.set_min_value(Y.prefs.min_value);Y.set_max_value(Y.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};o(i.prototype,p.prototype,I.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(Y){this.prefs.min_value=Y;$("#linetrack_"+this.dataset_id+"_minval").text(this.prefs.min_value);this.tile_cache.clear();this.request_draw()},set_max_value:function(Y){this.prefs.max_value=Y;$("#linetrack_"+this.dataset_id+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.request_draw()},predraw_init:function(){var Y=this;Y.vertical_range=undefined;return $.getJSON(Y.data_url,{stats:true,chrom:Y.view.chrom,low:null,high:null,hda_ldda:Y.hda_ldda,dataset_id:Y.dataset_id},function(Z){Y.container_div.addClass("line-track");var ac=Z.data;if(isNaN(parseFloat(Y.prefs.min_value))||isNaN(parseFloat(Y.prefs.max_value))){var aa=ac.min,ae=ac.max;aa=Math.floor(Math.min(0,Math.max(aa,ac.mean-2*ac.sd)));ae=Math.ceil(Math.max(0,Math.min(ae,ac.mean+2*ac.sd)));Y.prefs.min_value=aa;Y.prefs.max_value=ae;$("#track_"+Y.dataset_id+"_minval").val(Y.prefs.min_value);$("#track_"+Y.dataset_id+"_maxval").val(Y.prefs.max_value)}Y.vertical_range=Y.prefs.max_value-Y.prefs.min_value;Y.total_frequency=ac.total_frequency;Y.container_div.find(".yaxislabel").remove();var ad=$("<div/>").text(T(Y.prefs.min_value,3)).make_text_editable({num_cols:6,on_finish:function(af){$(".tipsy").remove();var af=parseFloat(af);if(!isNaN(af)){Y.set_min_value(af)}},help_text:"Set min value"}).addClass("yaxislabel bottom").attr("id","linetrack_"+Y.dataset_id+"_minval").prependTo(Y.container_div),ab=$("<div/>").text(T(Y.prefs.max_value,3)).make_text_editable({num_cols:6,on_finish:function(af){$(".tipsy").remove();var af=parseFloat(af);if(!isNaN(af)){Y.set_max_value(af)}},help_text:"Set max value"}).addClass("yaxislabel top").attr("id","linetrack_"+Y.dataset_id+"_maxval").prependTo(Y.container_div)})},draw_tile:function(ah,af,aa,Z,ac,ag){var Y=af.canvas,ab=ac.get("start"),ae=ac.get("end"),ad=new H.LinePainter(ah.data,ab,ae,this.prefs,aa);ad.draw(af,Y.width,Y.height,ag);return new b(this,ac,Z,Y,ah.data)},can_subset:function(Y){return false}});var c=function(ab,aa,ad){var Z=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];I.call(this,ab,aa,ad);var ac=get_random_color(),Y=get_random_color([ac,"#ffffff"]);this.config=new B({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:ac},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:Y},{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:"histogram_max",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:ad.prefs,onchange:function(){Z.set_name(Z.prefs.name);Z.tile_cache.clear();Z.set_painter_from_config();Z.request_draw()}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.hda_ldda=ad.hda_ldda;this.dataset_id=ad.dataset_id;this.original_dataset_id=ad.dataset_id;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()};o(c.prototype,p.prototype,I.prototype,{set_dataset:function(Y){this.dataset_id=Y.get("id");this.hda_ldda=Y.get("hda_ldda");this.data_manager.set("dataset",Y)},set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=H.ArcLinkedFeaturePainter}else{this.painter=H.LinkedFeaturePainter}},before_draw:function(){this.max_height_px=0},after_show_tile:function(Y){this.max_height_px=Math.max(this.max_height_px,Y.html_elt.height());Y.html_elt.parent().children().css("height",this.max_height_px+"px");var Z=this.max_height_px;if(this.visible_height_px!==0){Z=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",Z+"px")},postdraw_actions:function(an,ai,ad,ac){I.prototype.postdraw_actions.call(this,an,ac);var ah=this;if(ah.mode==="Histogram"){var ak,Z=-1;for(ak=0;ak<an.length;ak++){var aj=an[ak].max_val;if(aj>Z){Z=aj}}for(ak=0;ak<an.length;ak++){var ap=an[ak];if(ap.max_val!==Z){ap.html_elt.remove();ah.draw_helper(true,ai,ap.index,ap.resolution,ap.html_elt.parent(),ad,{more_tile_data:{max:Z}})}}}if(ah.filters_manager){var ae=ah.filters_manager.filters;for(var am=0;am<ae.length;am++){ae[am].update_ui_elt()}var ao=false,Y,af;for(var ak=0;ak<an.length;ak++){if(an[ak].data.length){Y=an[ak].data[0];for(var am=0;am<ae.length;am++){af=ae[am];if(af.applies_to(Y)&&af.min!==af.max){ao=true;break}}}}if(ah.filters_available!==ao){ah.filters_available=ao;if(!ah.filters_available){ah.filters_manager.hide()}ah.update_icons()}}this.container_div.find(".yaxislabel").remove();var ab=an[0];if(ab instanceof j){var ag=(this.prefs.histogram_max?this.prefs.histogram_max:ab.max_val),aa=$("<div/>").text(ag).make_text_editable({num_cols:12,on_finish:function(aq){$(".tipsy").remove();var aq=parseFloat(aq);ah.prefs.histogram_max=(!isNaN(aq)?aq:null);ah.tile_cache.clear();ah.request_draw()},help_text:"Set max value; leave blank to use default"}).addClass("yaxislabel top").css("color",this.prefs.label_color);this.container_div.prepend(aa)}if(ab instanceof K){var al=true;for(var ak=0;ak<an.length;ak++){if(!an[ak].all_slotted){al=false;break}}if(!al){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(Y){var Y;if(this.mode==="Auto"){if(Y==="no_detail"){Y="feature spans"}else{if(Y==="summary_tree"){Y="coverage histogram"}}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+Y+")")}},incremental_slots:function(ac,Y,ab){var Z=this.view.canvas_manager.dummy_context,aa=this.slotters[ac];if(!aa||(aa.mode!==ab)){aa=new (r.FeatureSlotter)(ac,ab,w,function(ad){return Z.measureText(ad)});this.slotters[ac]=aa}return aa.slot_features(Y)},get_summary_tree_data:function(ac,af,aa,an){if(an>aa-af){an=aa-af}var aj=Math.floor((aa-af)/an),am=[],ab=0;var ad=0,ae=0,ai,al=0,ag=[],ak,ah;var Z=function(aq,ap,ar,ao){aq[0]=ap+ar*ao;aq[1]=ap+(ar+1)*ao};while(al<an&&ad!==ac.length){var Y=false;for(;al<an&&!Y;al++){Z(ag,af,al,aj);for(ae=ad;ae<ac.length;ae++){ai=ac[ae].slice(1,3);if(is_overlap(ai,ag)){Y=true;break}}if(Y){break}}data_start_index=ae;am[am.length]=ak=[ag[0],0];for(;ae<ac.length;ae++){ai=ac[ae].slice(1,3);if(is_overlap(ai,ag)){ak[1]++}else{break}}if(ak[1]>ab){ab=ak[1]}al++}return{max:ab,delta:aj,data:am}},get_mode:function(Y){if(Y.dataset_type==="summary_tree"){mode="summary_tree"}else{if(Y.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>E){mode="Squish"}else{mode="Pack"}}}return mode},get_canvas_height:function(Y,ac,ad,Z){if(ac==="summary_tree"||ac==="Histogram"){return this.summary_draw_height}else{var ab=this.incremental_slots(ad,Y.data,ac);var aa=new (this.painter)(null,null,null,this.prefs,ac);return Math.max(X,aa.get_required_height(ab,Z))}},draw_tile:function(aj,an,al,ao,ab,af,aa){var am=this,Z=an.canvas,av=ab.get("start"),Y=ab.get("end"),aA=25,ac=this.left_offset;if(al==="summary_tree"||al==="Histogram"){if(aj.dataset_type!=="summary_tree"){var ag=this.get_summary_tree_data(aj.data,av,Y,200);if(aj.max){ag.max=aj.max}aj=ag}var ax=new H.SummaryTreePainter(aj,av,Y,this.prefs);ax.draw(an,Z.width,Z.height,af);return new j(am,ab,ao,Z,aj.data,aj.max)}var ae=[],ak=this.slotters[af].slots;all_slotted=true;if(aj.data){var ah=this.filters_manager.filters;for(var ap=0,ar=aj.data.length;ap<ar;ap++){var ad=aj.data[ap];var aq=false;var ai;for(var au=0,az=ah.length;au<az;au++){ai=ah[au];ai.update_attrs(ad);if(!ai.keep(ad)){aq=true;break}}if(!aq){ae.push(ad);if(!(ad[0] in ak)){all_slotted=false}}}}var ay=(this.filters_manager.alpha_filter?new y(this.filters_manager.alpha_filter):null);var aw=(this.filters_manager.height_filter?new y(this.filters_manager.height_filter):null);var ax=new (this.painter)(ae,av,Y,this.prefs,al,ay,aw,aa);var at=null;an.fillStyle=this.prefs.block_color;an.font=an.canvas.manager.default_font;an.textAlign="right";if(aj.data){at=ax.draw(an,Z.width,Z.height,af,ak);at.translation=-ac}return new K(am,ab,ao,Z,aj.data,af,al,aj.message,all_slotted,at)},data_and_mode_compatible:function(Y,Z){if(Z==="Auto"){return true}else{if(Y.extra_info==="no_detail"||Y.dataset_type==="summary_tree"){return false}else{return true}}},can_subset:function(Y){if(Y.dataset_type==="summary_tree"||Y.message||Y.extra_info==="no_detail"){return false}return true}});var N=function(Z,Y,aa){c.call(this,Z,Y,aa);this.config=new B({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:get_random_color()},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:aa.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=H.ReadPainter};o(N.prototype,p.prototype,I.prototype,c.prototype);var Q=function(aa,Z,ac){c.call(this,aa,Z,ac);var ab=get_random_color(),Y=get_random_color([ab,"#ffffff"]);this.config=new B({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:ab},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:Y},{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:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"Clear value to set automatically"},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ac.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=H.ReadPainter;this.update_icons()};o(Q.prototype,p.prototype,I.prototype,c.prototype);R.View=W;R.DrawableGroup=L;R.LineTrack=i;R.FeatureTrack=c;R.ReadTrack=Q;R.VcfTrack=N;R.CompositeTrack=g};var slotting_module=function(c,b){var e=c("class").extend;var d=2,a=5;b.FeatureSlotter=function(i,h,f,g){this.slots={};this.start_end_dct={};this.w_scale=i;this.mode=h;this.include_label=(h==="Pack");this.max_rows=f;this.measureText=g};e(b.FeatureSlotter.prototype,{slot_features:function(m){var p=this.w_scale,h=this.start_end_dct,x=[],z=[],n=0,y=this.max_rows;for(var v=0,w=m.length;v<w;v++){var k=m[v],o=k[0];if(this.slots[o]!==undefined){n=Math.max(n,this.slots[o]);z.push(this.slots[o])}else{x.push(v)}}var q=function(E,F){for(var D=0;D<=y;D++){var B=false,G=h[D];if(G!==undefined){for(var A=0,C=G.length;A<C;A++){var i=G[A];if(F>i[0]&&E<i[1]){B=true;break}}}if(!B){return D}}return -1};for(var v=0,w=x.length;v<w;v++){var k=m[x[v]],o=k[0],t=k[1],f=k[2],r=k[3],g=Math.floor(t*p),l=Math.ceil(f*p),u=this.measureText(r).width,j;if(r!==undefined&&this.include_label){u+=(d+a);if(g-u>=0){g-=u;j="left"}else{l+=u;j="right"}}var s=q(g,l);if(s>=0){if(h[s]===undefined){h[s]=[]}h[s].push([g,l]);this.slots[o]=s;n=Math.max(n,s)}}return n+1}})};var painters_module=function(i,x){var u=i("class").extend;var p=function(I,A,G,z,F,D){if(D===undefined){D=4}var C=z-A;var B=F-G;var E=Math.floor(Math.sqrt(C*C+B*B)/D);var J=C/E;var H=B/E;var y;for(y=0;y<E;y++,A+=J,G+=H){if(y%2!==0){continue}I.fillRect(A,G,D,1)}};var q=function(B,A,z,E){var D=A-E/2,C=A+E/2,F=z-Math.sqrt(E*3/2);B.beginPath();B.moveTo(D,F);B.lineTo(C,F);B.lineTo(A,z);B.lineTo(D,F);B.strokeStyle=this.fillStyle;B.fill();B.stroke();B.closePath()};var d=function(y){this.default_val=(y?y:1)};d.prototype.gen_val=function(y){return this.default_val};var l=function(A,C,y,z,B){this.data=A;this.view_start=C;this.view_end=y;this.prefs=u({},this.default_prefs,z);this.mode=B};l.prototype.default_prefs={};l.prototype.draw=function(z,A,y,B){};var v=function(A,C,y,z,B){l.call(this,A,C,y,z,B)};v.prototype.default_prefs={show_counts:false};v.prototype.draw=function(L,z,K,M){var E=this.view_start,N=this.view_end-this.view_start,I=this.data.data,G=(this.prefs.histogram_max?this.prefs.histogram_max:this.data.max),B=K;delta_x_px=Math.ceil(this.data.delta*M);L.save();for(var C=0,D=I.length;C<D;C++){var H=Math.floor((I[C][0]-E)*M);var F=I[C][1];if(!F){continue}var J=F/G*K;if(F!==0&&J<1){J=1}L.fillStyle=this.prefs.block_color;L.fillRect(H,B-J,delta_x_px,J);var A=4;if(this.prefs.show_counts&&(L.measureText(F).width+A)<delta_x_px){L.fillStyle=this.prefs.label_color;L.textAlign="center";L.fillText(F,H+(delta_x_px/2),10)}}L.restore()};var b=function(y,C,E,F,A){l.call(this,y,C,E,F,A);if(this.prefs.min_value===undefined){var G=Infinity;for(var z=0,B=this.data.length;z<B;z++){G=Math.min(G,this.data[z][1])}this.prefs.min_value=G}if(this.prefs.max_value===undefined){var D=-Infinity;for(var z=0,B=this.data.length;z<B;z++){D=Math.max(D,this.data[z][1])}this.prefs.max_value=D}};b.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};b.prototype.draw=function(S,Q,N,D){var I=false,K=this.prefs.min_value,F=this.prefs.max_value,M=F-K,B=N,C=this.view_start,P=this.view_end-this.view_start,L=this.mode,aa=this.data;S.save();var ac=Math.round(N+K/M*N);if(L!=="Intensity"){S.fillStyle="#aaa";S.fillRect(0,ac,Q,1)}S.beginPath();var Y,G,E;if(aa.length>1){E=Math.ceil((aa[1][0]-aa[0][0])*D)}else{E=10}var A=parseInt(this.prefs.color.slice(1),16),H=(A&16711680)>>16,R=(A&65280)>>8,V=A&255;for(var T=0,U=aa.length;T<U;T++){S.fillStyle=S.strokeStyle=this.prefs.color;Y=Math.round((aa[T][0]-C)*D);G=aa[T][1];var W=false,J=false;if(G===null){if(I&&L==="Filled"){S.lineTo(Y,B)}I=false;continue}if(G<K){J=true;G=K}else{if(G>F){W=true;G=F}}if(L==="Histogram"){G=Math.round(G/M*B);S.fillRect(Y,ac,E,-G)}else{if(L==="Intensity"){var z=(G-K)/M,O=Math.round(H+(255-H)*(1-z)),X=Math.round(R+(255-R)*(1-z)),ab=Math.round(V+(255-V)*(1-z));S.fillStyle="rgb("+O+","+X+","+ab+")";S.fillRect(Y,0,E,B)}else{G=Math.round(B-(G-K)/M*B);if(I){S.lineTo(Y,G)}else{I=true;if(L==="Filled"){S.moveTo(Y,B);S.lineTo(Y,G)}else{S.moveTo(Y,G)}}}}S.fillStyle=this.prefs.overflow_color;if(W||J){var Z;if(L==="Histogram"||L==="Intensity"){Z=E}else{Y-=2;Z=4}if(W){S.fillRect(Y,0,Z,3)}if(J){S.fillRect(Y,B-3,Z,3)}}S.fillStyle=this.prefs.color}if(L==="Filled"){if(I){S.lineTo(Y,ac);S.lineTo(0,ac)}S.fill()}else{S.stroke()}S.restore()};var m=function(y){this.feature_positions={};this.slot_height=y;this.translation=0;this.y_translation=0};m.prototype.map_feature_data=function(z,B,y,A){if(!this.feature_positions[B]){this.feature_positions[B]=[]}this.feature_positions[B].push({data:z,x_start:y,x_end:A})};m.prototype.get_feature_data=function(z,D){var C=Math.floor((D-this.y_translation)/this.slot_height),B;if(!this.feature_positions[C]){return null}z+=this.translation;for(var A=0;A<this.feature_positions[C].length;A++){B=this.feature_positions[C][A];if(z>=B.x_start&&z<=B.x_end){return B.data}}};var o=function(A,D,y,z,C,E,B){l.call(this,A,D,y,z,C);this.alpha_scaler=(E?E:new d());this.height_scaler=(B?B:new d())};o.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};u(o.prototype,{get_required_height:function(A,z){var y=y_scale=this.get_row_height(),B=this.mode;if(B==="no_detail"||B==="Squish"||B==="Pack"){y=A*y_scale}return y+this.get_top_padding(z)+this.get_bottom_padding(z)},get_top_padding:function(y){return 0},get_bottom_padding:function(y){return Math.max(Math.round(this.get_row_height()/2),5)},draw:function(K,I,G,E,F){var Q=this.data,D=this.view_start,M=this.view_end;K.save();K.fillStyle=this.prefs.block_color;K.textAlign="right";var H=this.view_end-this.view_start,L=this.get_row_height(),P=new m(L),B;for(var N=0,O=Q.length;N<O;N++){var A=Q[N],C=A[0],J=A[1],y=A[2],z=(F&&F[C]!==undefined?F[C]:null);if((J<M&&y>D)&&(this.mode==="Dense"||z!==null)){B=this.draw_element(K,this.mode,A,z,D,M,E,L,I);P.map_feature_data(A,z,B[0],B[1])}}K.restore();P.y_translation=this.get_top_padding(I);return P},draw_element:function(E,A,G,C,B,D,F,z,y){console.log("WARNING: Unimplemented function.");return[0,0]}});var c=10,h=3,k=5,w=10,f=1,s=9,e=3,a=9,j=2,g="#ccc";var r=function(A,D,y,z,C,E,B){o.call(this,A,D,y,z,C,E,B);this.draw_background_connector=true;this.draw_individual_connectors=false};u(r.prototype,o.prototype,{get_row_height:function(){var z=this.mode,y;if(z==="Dense"){y=c}else{if(z==="no_detail"){y=h}else{if(z==="Squish"){y=k}else{y=w}}}return y},draw_element:function(M,D,X,H,O,ai,am,ao,y){var T=X[0],ak=X[1],ad=X[2]-1,Q=X[3],K=X[4],ae=Math.floor(Math.max(0,(ak-O)*am)),N=Math.ceil(Math.min(y,Math.max(0,(ad-O)*am))),ac=ae,an=N,aa=(D==="Dense"?0:(0+H))*ao+this.get_top_padding(y),L,ag,R=null,aq=null,B=B=(!K||K==="+"||K==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;M.globalAlpha=this.alpha_scaler.gen_val(X);if(D==="Dense"){H=1}if(D==="no_detail"){M.fillStyle=B;M.fillRect(ae,aa+5,N-ae,f)}else{var Z=X[5],af=X[6],C=X[7],V=true;if(Z&&af){R=Math.floor(Math.max(0,(Z-O)*am));aq=Math.ceil(Math.min(y,Math.max(0,(af-O)*am)))}var al,U;if(D==="Squish"){al=1;U=e;V=false}else{if(D==="Dense"){al=5;U=s}else{al=5;U=a}}if(!C){M.fillStyle=B;M.fillRect(ae,aa+1,N-ae,U);if(K&&V){if(K==="+"){M.fillStyle=M.canvas.manager.get_pattern("right_strand_inv")}else{if(K==="-"){M.fillStyle=M.canvas.manager.get_pattern("left_strand_inv")}}M.fillRect(ae,aa+1,N-ae,U)}}else{var J,W;if(D==="Squish"||D==="Dense"){J=aa+Math.floor(e/2)+1;W=1}else{if(K){J=aa;W=U}else{J+=(e/2)+1;W=1}}if(this.draw_background_connector){if(D==="Squish"||D==="Dense"){M.fillStyle=g}else{if(K){if(K==="+"){M.fillStyle=M.canvas.manager.get_pattern("right_strand")}else{if(K==="-"){M.fillStyle=M.canvas.manager.get_pattern("left_strand")}}}else{M.fillStyle=g}}M.fillRect(ae,J,N-ae,W)}var E;for(var aj=0,A=C.length;aj<A;aj++){var F=C[aj],z=Math.floor(Math.max(0,(F[0]-O)*am)),Y=Math.ceil(Math.min(y,Math.max((F[1]-1-O)*am))),S,ab;if(z>Y){continue}M.fillStyle=B;M.fillRect(z,aa+(U-al)/2+1,Y-z,al);if(R!==undefined&&af>Z&&!(z>aq||Y<R)){var ah=Math.max(z,R),I=Math.min(Y,aq);M.fillRect(ah,aa+1,I-ah,U)}if(this.draw_individual_connectors&&S){this.draw_connector(M,S,ab,z,Y,aa)}S=z;ab=Y}if(D==="Pack"){M.globalAlpha=1;M.fillStyle="white";var G=this.height_scaler.gen_val(X),P=Math.ceil(U*G),ap=Math.round((U-P)/2);if(G!==1){M.fillRect(ae,J+1,N-ae,ap);M.fillRect(ae,J+U-ap+1,N-ae,ap)}}}M.globalAlpha=1;if(D==="Pack"&&ak>O){M.fillStyle=label_color;if(O===0&&ae-M.measureText(Q).width<0){M.textAlign="left";M.fillText(Q,N+j,aa+8);an+=M.measureText(Q).width+j}else{M.textAlign="right";M.fillText(Q,ae-j,aa+8);ac-=M.measureText(Q).width+j}}}M.globalAlpha=1;return[ac,an]}});var t=function(B,E,y,A,D,F,C,z){o.call(this,B,E,y,A,D,F,C);this.ref_seq=(z?z.data:null)};u(t.prototype,o.prototype,{get_row_height:function(){var y,z=this.mode;if(z==="Dense"){y=c}else{if(z==="Squish"){y=k}else{y=w;if(this.prefs.show_insertions){y*=2}}}return y},draw_read:function(K,A,ag,V,L,aa,ad,C,B,M){K.textAlign="center";var J=this,R=[L,aa],Z=0,W=0,D=0,F=K.canvas.manager.char_width_px,y=(B==="+"?this.prefs.block_color:this.prefs.reverse_strand_color);var O=[];if((A==="Pack"||this.mode==="Auto")&&M!==undefined&&ag>F){D=Math.round(ag/2)}if(!C){C=[[0,M.length]]}for(var G=0,I=C.length;G<I;G++){var z=C[G],E="MIDNSHP=X"[z[0]],S=z[1];if(E==="H"||E==="S"){Z-=S}var U=ad+Z,Y=Math.floor(Math.max(0,(U-L)*ag)),ab=Math.floor(Math.max(0,(U+S-L)*ag));if(Y===ab){ab+=1}switch(E){case"H":break;case"S":case"M":case"=":if(is_overlap([U,U+S],R)){var N=M.slice(W,W+S);if(D>0){K.fillStyle=y;K.fillRect(Y-D,V+1,ab-Y,9);K.fillStyle=g;for(var af=0,H=N.length;af<H;af++){if(this.prefs.show_differences){if(this.ref_seq){var P=this.ref_seq[U-L+af];if(!P||P.toLowerCase()===N[af].toLowerCase()){continue}}else{continue}}if(U+af>=L&&U+af<=aa){var X=Math.floor(Math.max(0,(U+af-L)*ag));K.fillText(N[af],X,V+9)}}}else{K.fillStyle=y;K.fillRect(Y,V+4,ab-Y,e)}}W+=S;Z+=S;break;case"N":K.fillStyle=g;K.fillRect(Y-D,V+5,ab-Y,1);Z+=S;break;case"D":K.fillStyle="red";K.fillRect(Y-D,V+4,ab-Y,3);Z+=S;break;case"P":break;case"I":var ah=Y-D;if(is_overlap([U,U+S],R)){var N=M.slice(W,W+S);if(this.prefs.show_insertions){var T=Y-(ab-Y)/2;if((A==="Pack"||this.mode==="Auto")&&M!==undefined&&ag>F){K.fillStyle="yellow";K.fillRect(T-D,V-9,ab-Y,9);O[O.length]={type:"triangle",data:[ah,V+4,5]};K.fillStyle=g;switch(compute_overlap([U,U+S],R)){case (OVERLAP_START):N=N.slice(L-U);break;case (OVERLAP_END):N=N.slice(0,U-aa);break;case (CONTAINED_BY):break;case (CONTAINS):N=N.slice(L-U,U-aa);break}for(var af=0,H=N.length;af<H;af++){var X=Math.floor(Math.max(0,(U+af-L)*ag));K.fillText(N[af],X-(ab-Y)/2,V)}}else{K.fillStyle="yellow";K.fillRect(T,V+(this.mode!=="Dense"?2:5),ab-Y,(A!=="Dense"?e:s))}}else{if((A==="Pack"||this.mode==="Auto")&&M!==undefined&&ag>F){O.push({type:"text",data:[N.length,ah,V+9]})}else{}}}W+=S;break;case"X":W+=S;break}}K.fillStyle="yellow";var Q,ai,ae;for(var ac=0;ac<O.length;ac++){Q=O[ac];ai=Q.type;ae=Q.data;if(ai==="text"){K.save();K.font="bold "+K.font;K.fillText(ae[0],ae[1],ae[2]);K.restore()}else{if(ai==="triangle"){q(K,ae[0],ae[1],ae[2])}}}},draw_element:function(R,M,E,B,U,z,I,S,P){var H=E[0],Q=E[1],A=E[2],J=E[3],D=Math.floor(Math.max(0,(Q-U)*I)),F=Math.ceil(Math.min(P,Math.max(0,(A-U)*I))),C=(M==="Dense"?0:(0+B))*S,G=this.prefs.label_color,O=0;if((M==="Pack"||this.mode==="Auto")&&I>R.canvas.manager.char_width_px){var O=Math.round(I/2)}if(E[5] instanceof Array){var N=Math.floor(Math.max(0,(E[4][0]-U)*I)),L=Math.ceil(Math.min(P,Math.max(0,(E[4][1]-U)*I))),K=Math.floor(Math.max(0,(E[5][0]-U)*I)),y=Math.ceil(Math.min(P,Math.max(0,(E[5][1]-U)*I)));if(E[4][1]>=U&&E[4][0]<=z&&E[4][2]){this.draw_read(R,M,I,C,U,z,E[4][0],E[4][2],E[4][3],E[4][4])}if(E[5][1]>=U&&E[5][0]<=z&&E[5][2]){this.draw_read(R,M,I,C,U,z,E[5][0],E[5][2],E[5][3],E[5][4])}if(K>L){R.fillStyle=g;p(R,L-O,C+5,K-O,C+5)}}else{this.draw_read(R,M,I,C,U,z,Q,E[4],E[5],E[6])}if(M==="Pack"&&Q>U&&J!=="."){R.fillStyle=this.prefs.label_color;var T=1;if(T===0&&D-R.measureText(J).width<0){R.textAlign="left";R.fillText(J,F+j-O,C+8)}else{R.textAlign="right";R.fillText(J,D-j-O,C+8)}}return[0,0]}});var n=function(A,D,y,z,C,E,B){r.call(this,A,D,y,z,C,E,B);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};u(n.prototype,o.prototype,r.prototype,{calculate_longest_feature_length:function(){var z=0;for(var C=0,y=this.data.length;C<y;C++){var B=this.data[C],A=B[1],D=B[2];z=Math.max(z,D-A)}return z},get_top_padding:function(z){var y=this.view_end-this.view_start,A=z/y;return Math.min(128,Math.ceil((this.longest_feature_length/2)*A))},draw_connector:function(G,B,F,H,E,D){var y=(F+H)/2,C=H-y;var A=Math.PI,z=0;if(C>0){G.beginPath();G.arc(y,D,H-y,Math.PI,0);G.stroke()}}});x.Scaler=d;x.SummaryTreePainter=v;x.LinePainter=b;x.LinkedFeaturePainter=r;x.ReadPainter=t;x.ArcLinkedFeaturePainter=n};(function(d){var c={};var b=function(e){return c[e]};var a=function(f,g){var e={};g(b,e);c[f]=e};a("class",class_module);a("slotting",slotting_module);a("painters",painters_module);a("trackster",trackster_module);for(key in c.trackster){d[key]=c.trackster[key]}})(window);
\ No newline at end of file
diff -r 9b7cf76169b41729ee6253d9722145347e9f5213 -r 05f25cefa1751a165d76882919ba3f7ecafe0bb1 static/scripts/packed/viz/visualization.js
--- a/static/scripts/packed/viz/visualization.js
+++ b/static/scripts/packed/viz/visualization.js
@@ -1,1 +1,1 @@
-var ServerStateDeferred=Backbone.Model.extend({defaults:{ajax_settings:{},interval:1000,success_fn:function(a){return true}},go:function(){var d=$.Deferred(),c=this,f=c.get("ajax_settings"),e=c.get("success_fn"),b=c.get("interval"),a=function(){$.ajax(f).success(function(g){if(e(g)){d.resolve(g)}else{setTimeout(a,b)}})};a();return d}});var CanvasManager=function(a){this.default_font=a!==undefined?a:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};_.extend(CanvasManager.prototype,{load_pattern:function(a,e){var b=this.patterns,c=this.dummy_context,d=new Image();d.src=galaxy_paths.attributes.image_path+e;d.onload=function(){b[a]=c.createPattern(d,"repeat")}},get_pattern:function(a){return this.patterns[a]},new_canvas:function(){var a=$("<canvas/>")[0];if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(a)}a.manager=this;return a}});var Cache=Backbone.Model.extend({defaults:{num_elements:20,obj_cache:null,key_ary:null},initialize:function(a){this.clear()},get_elt:function(b){var c=this.attributes.obj_cache,d=this.attributes.key_ary,a=d.indexOf(b);if(a!==-1){if(c[b].stale){d.splice(a,1);delete c[b]}else{this.move_key_to_end(b,a)}}return c[b]},set_elt:function(b,d){var e=this.attributes.obj_cache,f=this.attributes.key_ary,c=this.attributes.num_elements;if(!e[b]){if(f.length>=c){var a=f.shift();delete e[a]}f.push(b)}e[b]=d;return d},move_key_to_end:function(b,a){this.attributes.key_ary.splice(a,1);this.attributes.key_ary.push(b)},clear:function(){this.attributes.obj_cache={};this.attributes.key_ary=[]},size:function(){return this.attributes.key_ary.length}});var GenomeDataManager=Cache.extend({defaults:_.extend({},Cache.prototype.defaults,{dataset:null,filters_manager:null,data_url:null,dataset_state_url:null,data_mode_compatible:function(a,b){return true},can_subset:function(a){return false}}),data_is_ready:function(){var c=this.get("dataset"),b=$.Deferred(),a=new ServerStateDeferred({ajax_settings:{url:this.get("dataset_state_url"),data:{dataset_id:c.id,hda_ldda:c.get("hda_ldda")},dataType:"json"},interval:5000,success_fn:function(d){return d!=="pending"}});$.when(a.go()).then(function(d){b.resolve(d==="ok"||d==="data")});return b},load_data:function(h,g,b,f){var d={chrom:h.get("chrom"),low:h.get("start"),high:h.get("end"),mode:g,resolution:b};dataset=this.get("dataset");if(dataset){d.dataset_id=dataset.id;d.hda_ldda=dataset.get("hda_ldda")}$.extend(d,f);var j=this.get("filters_manager");if(j){var k=[];var a=j.filters;for(var e=0;e<a.length;e++){k.push(a[e].name)}d.filter_cols=JSON.stringify(k)}var c=this;return $.getJSON(this.get("data_url"),d,function(i){c.set_data(h,i)})},get_data:function(g,f,c,e){var h=this.get_elt(g);if(h&&(is_deferred(h)||this.get("data_mode_compatible")(h,f))){return h}var j=this.get("key_ary"),b=this.get("obj_cache"),k,a;for(var d=0;d<j.length;d++){a=new GenomeRegion({from_str:j[d]});if(a.contains(g)){h=b[k];if(is_deferred(h)||(this.get("data_mode_compatible")(h,f)&&this.get("can_subset")(h))){this.move_key_to_end(k,d);return h}}}h=this.load_data(g,f,c,e);this.set_data(g,h);return h},set_data:function(b,a){this.set_elt(b,a)},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(i,h,d,g,e){var k=this.get_elt(i);if(!(k&&this.get("data_mode_compatible")(k,h))){console.log("ERROR: no current data for: ",dataset,i.toString(),h,d,g);return}k.stale=true;var c=i.get("start");if(e===this.DEEP_DATA_REQ){$.extend(g,{start_val:k.data.length+1})}else{if(e===this.BROAD_DATA_REQ){c=(k.max_high?k.max_high:k.data[k.data.length-1][2])+1}}var j=i.copy().set("start",c);var b=this,f=this.load_data(j,h,d,g),a=$.Deferred();this.set_data(i,a);$.when(f).then(function(l){if(l.data){l.data=k.data.concat(l.data);if(l.max_low){l.max_low=k.max_low}if(l.message){l.message=l.message.replace(/[0-9]+/,l.data.length)}}b.set_data(i,l);a.resolve(l)});return a},get_elt:function(a){return Cache.prototype.get_elt.call(this,a.toString())},set_elt:function(b,a){return Cache.prototype.set_elt.call(this,b.toString(),a)}});var ReferenceTrackDataManager=GenomeDataManager.extend({load_data:function(a,d,e,b,c){if(b>1){return{data:null}}return GenomeDataManager.prototype.load_data.call(this,a,d,e,b,c)}});var Genome=Backbone.Model.extend({defaults:{name:null,key:null,chroms_info:null},get_chroms_info:function(){return this.attributes.chroms_info.chrom_info}});var GenomeRegion=Backbone.RelationalModel.extend({defaults:{chrom:null,start:0,end:0,DIF_CHROMS:1000,BEFORE:1001,CONTAINS:1002,OVERLAP_START:1003,OVERLAP_END:1004,CONTAINED_BY:1005,AFTER:1006},initialize:function(b){if(b.from_str){var d=b.from_str.split(":"),c=d[0],a=d[1].split("-");this.set({chrom:c,start:parseInt(a[0],10),end:parseInt(a[1],10)})}},copy:function(){return new GenomeRegion({chrom:this.get("chrom"),start:this.get("start"),end:this.get("end")})},length:function(){return this.get("end")-this.get("start")},toString:function(){return this.get("chrom")+":"+this.get("start")+"-"+this.get("end")},toJSON:function(){return{chrom:this.get("chrom"),start:this.get("start"),end:this.get("end")}},compute_overlap:function(h){var b=this.get("chrom"),g=h.get("chrom"),f=this.get("start"),d=h.get("start"),e=this.get("end"),c=h.get("end"),a;if(b&&g&&b!==g){return this.get("DIF_CHROMS")}if(f<d){if(e<d){a=this.get("BEFORE")}else{if(e<=c){a=this.get("OVERLAP_START")}else{a=this.get("CONTAINS")}}}else{if(f>c){a=this.get("AFTER")}else{if(e<=c){a=this.get("CONTAINED_BY")}else{a=this.get("OVERLAP_END")}}}return a},contains:function(a){return this.compute_overlap(a)===this.get("CONTAINS")},overlaps:function(a){return _.intersection([this.compute_overlap(a)],[this.get("DIF_CHROMS"),this.get("BEFORE"),this.get("AFTER")]).length===0}});var GenomeRegionCollection=Backbone.Collection.extend({model:GenomeRegion});var BrowserBookmark=Backbone.Model.extend({defaults:{region:null,note:""}});var BrowserBookmarks=Backbone.Collection.extend({model:BrowserBookmark});var Visualization=Backbone.RelationalModel.extend({defaults:{id:"",title:"",type:"",dbkey:"",datasets:[]},url:function(){return galaxy_paths.get("visualization_url")},save:function(){return $.ajax({url:this.url(),type:"POST",dataType:"json",data:{vis_json:JSON.stringify(this)}})}});var TracksterVisualization=Visualization.extend({defaults:{bookmarks:[],viewport:{}}});var CircsterVisualization=Visualization.extend({});var HistogramDataset=Backbone.Model.extend({initialize:function(a){this.attributes.data=a;this.attributes.max=_.max(a,function(b){if(!b||typeof b==="string"){return 0}return b[1]})[1]}});var TrackConfig=Backbone.Model.extend({});var CircsterHistogramDatasetLayout=Backbone.Model.extend({chroms_layout:function(){var b=this.attributes.genome.get_chroms_info(),d=d3.layout.pie().value(function(f){return f.len}).sort(null),e=d(b),a=this.attributes.total_gap/b.length,c=_.map(e,function(h,g){var f=h.endAngle-a;h.endAngle=(f>h.startAngle?f:h.startAngle);return h});return c},chrom_data_layout:function(j,b,g,f,h){if(!b||typeof b==="string"){return null}var d=b[0],i=b[3],c=d3.scale.linear().domain([0,h]).range([g,f]),e=d3.layout.pie().value(function(k){return i}).startAngle(j.startAngle).endAngle(j.endAngle),a=e(d);_.each(d,function(k,l){a[l].outerRadius=c(k[1])});return a}});var CircsterView=Backbone.View.extend({className:"circster",initialize:function(a){this.width=a.width;this.height=a.height;this.total_gap=a.total_gap;this.genome=a.genome;this.dataset=a.dataset;this.radius_start=a.radius_start;this.dataset_arc_height=a.dataset_arc_height},render:function(){var d=this.radius_start,e=this.dataset_arc_height,j=new CircsterHistogramDatasetLayout({genome:this.genome,total_gap:this.total_gap}),i=j.chroms_layout(),g=_.zip(i,this.dataset.attributes.data),h=this.dataset.attributes.max,b=_.map(g,function(m){var n=m[0],l=m[1];return j.chrom_data_layout(n,l,d,d+e,h)});var c=d3.select(this.$el[0]).append("svg").attr("width",this.width).attr("height",this.height).append("g").attr("transform","translate("+this.width/2+","+this.height/2+")");var k=c.append("g").attr("id","inner-arc"),f=d3.svg.arc().innerRadius(d).outerRadius(d+e),a=k.selectAll("#inner-arc>path").data(i).enter().append("path").attr("d",f).style("stroke","#ccc").style("fill","#ccc").append("title").text(function(l){return l.data.chrom});_.each(b,function(l){if(!l){return}var o=c.append("g"),n=d3.svg.arc().innerRadius(d),m=o.selectAll("path").data(l).enter().append("path").attr("d",n).style("stroke","red").style("fill","red")})}});var TrackBrowserRouter=Backbone.Router.extend({initialize:function(b){this.view=b.view;this.route(/([\w]+)$/,"change_location");this.route(/([\w]+\:[\d,]+-[\d,]+)$/,"change_location");var a=this;a.view.on("navigate",function(c){a.navigate(c)})},change_location:function(a){this.view.go_to(a)}});var add_datasets=function(a,c,b){$.ajax({url:a,data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(d){show_modal("Select datasets for new tracks",d,{Cancel:function(){hide_modal()},Add:function(){var e=[];$("input[name=id]:checked,input[name=ldda_ids]:checked").each(function(){var f,g=$(this).val();if($(this).attr("name")==="id"){f={hda_id:g}}else{f={ldda_id:g}}e[e.length]=$.ajax({url:c,data:f,dataType:"json"})});$.when.apply($,e).then(function(){var f=(arguments[0] instanceof Array?$.map(arguments,function(g){return g[0]}):[arguments[0]]);b(f)});hide_modal()}})}})};
\ No newline at end of file
+var ServerStateDeferred=Backbone.Model.extend({defaults:{ajax_settings:{},interval:1000,success_fn:function(a){return true}},go:function(){var d=$.Deferred(),c=this,f=c.get("ajax_settings"),e=c.get("success_fn"),b=c.get("interval"),a=function(){$.ajax(f).success(function(g){if(e(g)){d.resolve(g)}else{setTimeout(a,b)}})};a();return d}});var CanvasManager=function(a){this.default_font=a!==undefined?a:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};_.extend(CanvasManager.prototype,{load_pattern:function(a,e){var b=this.patterns,c=this.dummy_context,d=new Image();d.src=galaxy_paths.attributes.image_path+e;d.onload=function(){b[a]=c.createPattern(d,"repeat")}},get_pattern:function(a){return this.patterns[a]},new_canvas:function(){var a=$("<canvas/>")[0];if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(a)}a.manager=this;return a}});var Cache=Backbone.Model.extend({defaults:{num_elements:20,obj_cache:null,key_ary:null},initialize:function(a){this.clear()},get_elt:function(b){var c=this.attributes.obj_cache,d=this.attributes.key_ary,a=d.indexOf(b);if(a!==-1){if(c[b].stale){d.splice(a,1);delete c[b]}else{this.move_key_to_end(b,a)}}return c[b]},set_elt:function(b,d){var e=this.attributes.obj_cache,f=this.attributes.key_ary,c=this.attributes.num_elements;if(!e[b]){if(f.length>=c){var a=f.shift();delete e[a]}f.push(b)}e[b]=d;return d},move_key_to_end:function(b,a){this.attributes.key_ary.splice(a,1);this.attributes.key_ary.push(b)},clear:function(){this.attributes.obj_cache={};this.attributes.key_ary=[]},size:function(){return this.attributes.key_ary.length}});var GenomeDataManager=Cache.extend({defaults:_.extend({},Cache.prototype.defaults,{dataset:null,filters_manager:null,data_url:null,dataset_state_url:null,data_mode_compatible:function(a,b){return true},can_subset:function(a){return false}}),data_is_ready:function(){var c=this.get("dataset"),b=$.Deferred(),a=new ServerStateDeferred({ajax_settings:{url:this.get("dataset_state_url"),data:{dataset_id:c.id,hda_ldda:c.get("hda_ldda")},dataType:"json"},interval:5000,success_fn:function(d){return d!=="pending"}});$.when(a.go()).then(function(d){b.resolve(d==="ok"||d==="data")});return b},load_data:function(h,g,b,f){var d={chrom:h.get("chrom"),low:h.get("start"),high:h.get("end"),mode:g,resolution:b};dataset=this.get("dataset");if(dataset){d.dataset_id=dataset.id;d.hda_ldda=dataset.get("hda_ldda")}$.extend(d,f);var j=this.get("filters_manager");if(j){var k=[];var a=j.filters;for(var e=0;e<a.length;e++){k.push(a[e].name)}d.filter_cols=JSON.stringify(k)}var c=this;return $.getJSON(this.get("data_url"),d,function(i){c.set_data(h,i)})},get_data:function(g,f,c,e){var h=this.get_elt(g);if(h&&(is_deferred(h)||this.get("data_mode_compatible")(h,f))){return h}var j=this.get("key_ary"),b=this.get("obj_cache"),k,a;for(var d=0;d<j.length;d++){k=j[d];a=new GenomeRegion({from_str:k});if(a.contains(g)){h=b[k];if(is_deferred(h)||(this.get("data_mode_compatible")(h,f)&&this.get("can_subset")(h))){this.move_key_to_end(k,d);return h}}}h=this.load_data(g,f,c,e);this.set_data(g,h);return h},set_data:function(b,a){this.set_elt(b,a)},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(i,h,d,g,e){var k=this.get_elt(i);if(!(k&&this.get("data_mode_compatible")(k,h))){console.log("ERROR: no current data for: ",dataset,i.toString(),h,d,g);return}k.stale=true;var c=i.get("start");if(e===this.DEEP_DATA_REQ){$.extend(g,{start_val:k.data.length+1})}else{if(e===this.BROAD_DATA_REQ){c=(k.max_high?k.max_high:k.data[k.data.length-1][2])+1}}var j=i.copy().set("start",c);var b=this,f=this.load_data(j,h,d,g),a=$.Deferred();this.set_data(i,a);$.when(f).then(function(l){if(l.data){l.data=k.data.concat(l.data);if(l.max_low){l.max_low=k.max_low}if(l.message){l.message=l.message.replace(/[0-9]+/,l.data.length)}}b.set_data(i,l);a.resolve(l)});return a},get_elt:function(a){return Cache.prototype.get_elt.call(this,a.toString())},set_elt:function(b,a){return Cache.prototype.set_elt.call(this,b.toString(),a)}});var ReferenceTrackDataManager=GenomeDataManager.extend({load_data:function(a,d,e,b,c){if(b>1){return{data:null}}return GenomeDataManager.prototype.load_data.call(this,a,d,e,b,c)}});var Genome=Backbone.Model.extend({defaults:{name:null,key:null,chroms_info:null},get_chroms_info:function(){return this.attributes.chroms_info.chrom_info}});var GenomeRegion=Backbone.RelationalModel.extend({defaults:{chrom:null,start:0,end:0,DIF_CHROMS:1000,BEFORE:1001,CONTAINS:1002,OVERLAP_START:1003,OVERLAP_END:1004,CONTAINED_BY:1005,AFTER:1006},initialize:function(b){if(b.from_str){var d=b.from_str.split(":"),c=d[0],a=d[1].split("-");this.set({chrom:c,start:parseInt(a[0],10),end:parseInt(a[1],10)})}},copy:function(){return new GenomeRegion({chrom:this.get("chrom"),start:this.get("start"),end:this.get("end")})},length:function(){return this.get("end")-this.get("start")},toString:function(){return this.get("chrom")+":"+this.get("start")+"-"+this.get("end")},toJSON:function(){return{chrom:this.get("chrom"),start:this.get("start"),end:this.get("end")}},compute_overlap:function(h){var b=this.get("chrom"),g=h.get("chrom"),f=this.get("start"),d=h.get("start"),e=this.get("end"),c=h.get("end"),a;if(b&&g&&b!==g){return this.get("DIF_CHROMS")}if(f<d){if(e<d){a=this.get("BEFORE")}else{if(e<=c){a=this.get("OVERLAP_START")}else{a=this.get("CONTAINS")}}}else{if(f>c){a=this.get("AFTER")}else{if(e<=c){a=this.get("CONTAINED_BY")}else{a=this.get("OVERLAP_END")}}}return a},contains:function(a){return this.compute_overlap(a)===this.get("CONTAINS")},overlaps:function(a){return _.intersection([this.compute_overlap(a)],[this.get("DIF_CHROMS"),this.get("BEFORE"),this.get("AFTER")]).length===0}});var GenomeRegionCollection=Backbone.Collection.extend({model:GenomeRegion});var BrowserBookmark=Backbone.Model.extend({defaults:{region:null,note:""}});var BrowserBookmarks=Backbone.Collection.extend({model:BrowserBookmark});var Visualization=Backbone.RelationalModel.extend({defaults:{id:"",title:"",type:"",dbkey:"",datasets:[]},url:function(){return galaxy_paths.get("visualization_url")},save:function(){return $.ajax({url:this.url(),type:"POST",dataType:"json",data:{vis_json:JSON.stringify(this)}})}});var TracksterVisualization=Visualization.extend({defaults:{bookmarks:[],viewport:{}}});var CircsterVisualization=Visualization.extend({});var HistogramDataset=Backbone.Model.extend({initialize:function(a){this.attributes.data=a;this.attributes.max=_.max(a,function(b){if(!b||typeof b==="string"){return 0}return b[1]})[1]}});var TrackConfig=Backbone.Model.extend({});var CircsterHistogramDatasetLayout=Backbone.Model.extend({chroms_layout:function(){var b=this.attributes.genome.get_chroms_info(),d=d3.layout.pie().value(function(f){return f.len}).sort(null),e=d(b),a=this.attributes.total_gap/b.length,c=_.map(e,function(h,g){var f=h.endAngle-a;h.endAngle=(f>h.startAngle?f:h.startAngle);return h});return c},chrom_data_layout:function(j,b,g,f,h){if(!b||typeof b==="string"){return null}var d=b[0],i=b[3],c=d3.scale.linear().domain([0,h]).range([g,f]),e=d3.layout.pie().value(function(k){return i}).startAngle(j.startAngle).endAngle(j.endAngle),a=e(d);_.each(d,function(k,l){a[l].outerRadius=c(k[1])});return a}});var CircsterView=Backbone.View.extend({className:"circster",initialize:function(a){this.width=a.width;this.height=a.height;this.total_gap=a.total_gap;this.genome=a.genome;this.dataset=a.dataset;this.radius_start=a.radius_start;this.dataset_arc_height=a.dataset_arc_height},render:function(){var d=this.radius_start,e=this.dataset_arc_height,j=new CircsterHistogramDatasetLayout({genome:this.genome,total_gap:this.total_gap}),i=j.chroms_layout(),g=_.zip(i,this.dataset.attributes.data),h=this.dataset.attributes.max,b=_.map(g,function(m){var n=m[0],l=m[1];return j.chrom_data_layout(n,l,d,d+e,h)});var c=d3.select(this.$el[0]).append("svg").attr("width",this.width).attr("height",this.height).append("g").attr("transform","translate("+this.width/2+","+this.height/2+")");var k=c.append("g").attr("id","inner-arc"),f=d3.svg.arc().innerRadius(d).outerRadius(d+e),a=k.selectAll("#inner-arc>path").data(i).enter().append("path").attr("d",f).style("stroke","#ccc").style("fill","#ccc").append("title").text(function(l){return l.data.chrom});_.each(b,function(l){if(!l){return}var o=c.append("g"),n=d3.svg.arc().innerRadius(d),m=o.selectAll("path").data(l).enter().append("path").attr("d",n).style("stroke","red").style("fill","red")})}});var TrackBrowserRouter=Backbone.Router.extend({initialize:function(b){this.view=b.view;this.route(/([\w]+)$/,"change_location");this.route(/([\w]+\:[\d,]+-[\d,]+)$/,"change_location");var a=this;a.view.on("navigate",function(c){a.navigate(c)})},change_location:function(a){this.view.go_to(a)}});var add_datasets=function(a,c,b){$.ajax({url:a,data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(d){show_modal("Select datasets for new tracks",d,{Cancel:function(){hide_modal()},Add:function(){var e=[];$("input[name=id]:checked,input[name=ldda_ids]:checked").each(function(){var f,g=$(this).val();if($(this).attr("name")==="id"){f={hda_id:g}}else{f={ldda_id:g}}e[e.length]=$.ajax({url:c,data:f,dataType:"json"})});$.when.apply($,e).then(function(){var f=(arguments[0] instanceof Array?$.map(arguments,function(g){return g[0]}):[arguments[0]]);b(f)});hide_modal()}})}})};
\ No newline at end of file
diff -r 9b7cf76169b41729ee6253d9722145347e9f5213 -r 05f25cefa1751a165d76882919ba3f7ecafe0bb1 static/scripts/viz/trackster.js
--- a/static/scripts/viz/trackster.js
+++ b/static/scripts/viz/trackster.js
@@ -87,9 +87,6 @@
* Helper to determine if object is jQuery deferred.
*/
var is_deferred = function ( d ) {
- if (d === 'pending') {
- console.log('pending');
- }
return ( 'isResolved' in d );
};
diff -r 9b7cf76169b41729ee6253d9722145347e9f5213 -r 05f25cefa1751a165d76882919ba3f7ecafe0bb1 static/scripts/viz/visualization.js
--- a/static/scripts/viz/visualization.js
+++ b/static/scripts/viz/visualization.js
@@ -269,7 +269,8 @@
obj_cache = this.get('obj_cache'),
key, entry_region;
for (var i = 0; i < key_ary.length; i++) {
- entry_region = new GenomeRegion({from_str: key_ary[i]});
+ key = key_ary[i];
+ entry_region = new GenomeRegion({from_str: key});
if (entry_region.contains(region)) {
// This entry has data in the requested range. Return if data
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: jgoecks: Enhancements to enable paramamonster to be used via accessible/published visualizations. Pack scripts.
by Bitbucket 01 Jul '12
by Bitbucket 01 Jul '12
01 Jul '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/9b7cf76169b4/
changeset: 9b7cf76169b4
user: jgoecks
date: 2012-07-02 04:04:40
summary: Enhancements to enable paramamonster to be used via accessible/published visualizations. Pack scripts.
affected #: 13 files
diff -r f7d0c01430f761a73db0f7dc18bd025ad6768575 -r 9b7cf76169b41729ee6253d9722145347e9f5213 lib/galaxy/web/controllers/tracks.py
--- a/lib/galaxy/web/controllers/tracks.py
+++ b/lib/galaxy/web/controllers/tracks.py
@@ -470,8 +470,10 @@
return self.tracks_grid( trans, **kwargs )
@web.expose
- @web.require_login( "use Galaxy visualizations", use_panels=True )
def paramamonster( self, trans, id=None, hda_ldda=None, dataset_id=None, regions=None ):
+ # Need to create history if necessary in order to create tool form.
+ trans.get_history( create=True )
+
if id:
# Loading a shared visualization.
viz = self.get_visualization( trans, id )
@@ -495,7 +497,6 @@
return trans.fill_template_mako( "visualization/paramamonster.mako", config=viz_config )
@web.expose
- @web.require_login( "use Galaxy visualizations", use_panels=True )
def circster( self, trans, hda_ldda, dataset_id ):
# Get dataset.
dataset = self.get_hda_or_ldda( trans, hda_ldda, dataset_id )
diff -r f7d0c01430f761a73db0f7dc18bd025ad6768575 -r 9b7cf76169b41729ee6253d9722145347e9f5213 static/scripts/packed/libs/backbone-relational.js
--- a/static/scripts/packed/libs/backbone-relational.js
+++ b/static/scripts/packed/libs/backbone-relational.js
@@ -1,1 +1,1 @@
-(function(g){var d,h,b;if(typeof window==="undefined"){d=require("underscore");h=require("backbone");b=module.exports=h}else{var d=window._;h=window.Backbone;b=window}h.Relational={showWarnings:true};h.Semaphore={_permitsAvailable:null,_permitsUsed:0,acquire:function(){if(this._permitsAvailable&&this._permitsUsed>=this._permitsAvailable){throw new Error("Max permits acquired")}else{this._permitsUsed++}},release:function(){if(this._permitsUsed===0){throw new Error("All permits released")}else{this._permitsUsed--}},isLocked:function(){return this._permitsUsed>0},setAvailablePermits:function(i){if(this._permitsUsed>i){throw new Error("Available permits cannot be less than used permits")}this._permitsAvailable=i}};h.BlockingQueue=function(){this._queue=[]};d.extend(h.BlockingQueue.prototype,h.Semaphore,{_queue:null,add:function(i){if(this.isBlocked()){this._queue.push(i)}else{i()}},process:function(){while(this._queue&&this._queue.length){this._queue.shift()()}},block:function(){this.acquire()},unblock:function(){this.release();if(!this.isBlocked()){this.process()}},isBlocked:function(){return this.isLocked()}});h.Relational.eventQueue=new h.BlockingQueue();h.Store=function(){this._collections=[];this._reverseRelations=[]};d.extend(h.Store.prototype,h.Events,{_collections:null,_reverseRelations:null,addReverseRelation:function(j){var i=d.any(this._reverseRelations,function(k){return d.all(j,function(m,l){return m===k[l]})});if(!i&&j.model&&j.type){this._reverseRelations.push(j);if(!j.model.prototype.relations){j.model.prototype.relations=[]}j.model.prototype.relations.push(j);this.retroFitRelation(j)}},retroFitRelation:function(j){var i=this.getCollection(j.model);i.each(function(k){new j.type(k,j)},this)},getCollection:function(i){var j=d.detect(this._collections,function(k){return i===k.model||i.constructor===k.model});if(!j){j=this._createCollection(i)}return j},getObjectByName:function(i){var j=d.reduce(i.split("."),function(k,l){return k[l]},b);return j!==b?j:null},_createCollection:function(j){var i;if(j instanceof h.RelationalModel){j=j.constructor}if(j.prototype instanceof h.RelationalModel.prototype.constructor){i=new h.Collection();i.model=j;this._collections.push(i)}return i},resolveIdForItem:function(i,j){var k=d.isString(j)||d.isNumber(j)?j:null;if(k==null){if(j instanceof h.RelationalModel){k=j.id}else{if(d.isObject(j)){k=j[i.prototype.idAttribute]}}}return k},find:function(j,k){var l=this.resolveIdForItem(j,k);var i=this.getCollection(j);return i&&i.get(l)},register:function(j){var i=j.collection;var k=this.getCollection(j);k&&k.add(j);j.bind("destroy",this.unregister,this);j.collection=i},update:function(i){var j=this.getCollection(i);j._onModelEvent("change:"+i.idAttribute,i,j)},unregister:function(i){i.unbind("destroy",this.unregister);var j=this.getCollection(i);j&&j.remove(i)}});h.Relational.store=new h.Store();h.Relation=function(i,j){this.instance=i;j=(typeof j==="object"&&j)||{};this.reverseRelation=d.defaults(j.reverseRelation||{},this.options.reverseRelation);this.reverseRelation.type=!d.isString(this.reverseRelation.type)?this.reverseRelation.type:h[this.reverseRelation.type]||h.Relational.store.getObjectByName(this.reverseRelation.type);this.model=j.model||this.instance.constructor;this.options=d.defaults(j,this.options,h.Relation.prototype.options);this.key=this.options.key;this.keySource=this.options.keySource||this.key;this.keyDestination=this.options.keyDestination||this.options.keySource||this.key;this.relatedModel=this.options.relatedModel;if(d.isString(this.relatedModel)){this.relatedModel=h.Relational.store.getObjectByName(this.relatedModel)}if(!this.checkPreconditions()){return false}if(i){this.keyContents=this.instance.get(this.keySource);if(this.key!==this.keySource){this.instance.unset(this.keySource,{silent:true})}this.instance._relations.push(this)}if(!this.options.isAutoRelation&&this.reverseRelation.type&&this.reverseRelation.key){h.Relational.store.addReverseRelation(d.defaults({isAutoRelation:true,model:this.relatedModel,relatedModel:this.model,reverseRelation:this.options},this.reverseRelation))}d.bindAll(this,"_modelRemovedFromCollection","_relatedModelAdded","_relatedModelRemoved");if(i){this.initialize();h.Relational.store.getCollection(this.instance).bind("relational:remove",this._modelRemovedFromCollection);h.Relational.store.getCollection(this.relatedModel).bind("relational:add",this._relatedModelAdded).bind("relational:remove",this._relatedModelRemoved)}};h.Relation.extend=h.Model.extend;d.extend(h.Relation.prototype,h.Events,h.Semaphore,{options:{createModels:true,includeInJSON:true,isAutoRelation:false},instance:null,key:null,keyContents:null,relatedModel:null,reverseRelation:null,related:null,_relatedModelAdded:function(k,l,j){var i=this;k.queue(function(){i.tryAddRelated(k,j)})},_relatedModelRemoved:function(j,k,i){this.removeRelated(j,i)},_modelRemovedFromCollection:function(i){if(i===this.instance){this.destroy()}},checkPreconditions:function(){var n=this.instance,l=this.key,j=this.model,p=this.relatedModel,q=h.Relational.showWarnings&&typeof console!=="undefined";if(!j||!l||!p){q&&console.warn("Relation=%o; no model, key or relatedModel (%o, %o, %o)",this,j,l,p);return false}if(!(j.prototype instanceof h.RelationalModel.prototype.constructor)){q&&console.warn("Relation=%o; model does not inherit from Backbone.RelationalModel (%o)",this,n);return false}if(!(p.prototype instanceof h.RelationalModel.prototype.constructor)){q&&console.warn("Relation=%o; relatedModel does not inherit from Backbone.RelationalModel (%o)",this,p);return false}if(this instanceof h.HasMany&&this.reverseRelation.type===h.HasMany.prototype.constructor){q&&console.warn("Relation=%o; relation is a HasMany, and the reverseRelation is HasMany as well.",this);return false}if(n&&n._relations.length){var o=d.any(n._relations,function(i){var k=this.reverseRelation.key&&i.reverseRelation.key;return i.relatedModel===p&&i.key===l&&(!k||this.reverseRelation.key===i.reverseRelation.key)},this);if(o){q&&console.warn("Relation=%o between instance=%o.%s and relatedModel=%o.%s already exists",this,n,l,p,this.reverseRelation.key);return false}}return true},setRelated:function(j,i){this.related=j;this.instance.acquire();this.instance.set(this.key,j,d.defaults(i||{},{silent:true}));this.instance.release()},createModel:function(i){if(this.options.createModels&&typeof(i)==="object"){return new this.relatedModel(i)}},_isReverseRelation:function(i){if(i.instance instanceof this.relatedModel&&this.reverseRelation.key===i.key&&this.key===i.reverseRelation.key){return true}return false},getReverseRelations:function(i){var j=[];var k=!d.isUndefined(i)?[i]:this.related&&(this.related.models||[this.related]);d.each(k,function(l){d.each(l.getRelations(),function(m){if(this._isReverseRelation(m)){j.push(m)}},this)},this);return j},sanitizeOptions:function(i){i=i?d.clone(i):{};if(i.silent){i=d.extend({},i,{silentChange:true});delete i.silent}return i},unsanitizeOptions:function(i){i=i?d.clone(i):{};if(i.silentChange){i=d.extend({},i,{silent:true});delete i.silentChange}return i},destroy:function(){h.Relational.store.getCollection(this.instance).unbind("relational:remove",this._modelRemovedFromCollection);h.Relational.store.getCollection(this.relatedModel).unbind("relational:add",this._relatedModelAdded).unbind("relational:remove",this._relatedModelRemoved);d.each(this.getReverseRelations(),function(i){i.removeRelated(this.instance)},this)}});h.HasOne=h.Relation.extend({options:{reverseRelation:{type:"HasMany"}},initialize:function(){d.bindAll(this,"onChange");this.instance.bind("relational:change:"+this.key,this.onChange);var j=this.findRelated({silent:true});this.setRelated(j);var i=this;d.each(i.getReverseRelations(),function(k){k.addRelated(i.instance)})},findRelated:function(j){var k=this.keyContents;var i=null;if(k instanceof this.relatedModel){i=k}else{if(k){i=h.Relational.store.find(this.relatedModel,k);if(i&&d.isObject(k)){i.set(k,j)}else{if(!i){i=this.createModel(k)}}}}return i},onChange:function(l,i,k){if(this.isLocked()){return}this.acquire();k=this.sanitizeOptions(k);var o=d.isUndefined(k._related);var m=o?this.related:k._related;if(o){this.keyContents=i;if(i instanceof this.relatedModel){this.related=i}else{if(i){var n=this.findRelated(k);this.setRelated(n)}else{this.setRelated(null)}}}if(m&&this.related!==m){d.each(this.getReverseRelations(m),function(p){p.removeRelated(this.instance,k)},this)}d.each(this.getReverseRelations(),function(p){p.addRelated(this.instance,k)},this);if(!k.silentChange&&this.related!==m){var j=this;h.Relational.eventQueue.add(function(){j.instance.trigger("update:"+j.key,j.instance,j.related,k)})}this.release()},tryAddRelated:function(j,i){if(this.related){return}i=this.sanitizeOptions(i);var k=this.keyContents;if(k){var l=h.Relational.store.resolveIdForItem(this.relatedModel,k);if(j.id===l){this.addRelated(j,i)}}},addRelated:function(j,i){if(j!==this.related){var k=this.related||null;this.setRelated(j);this.onChange(this.instance,j,{_related:k})}},removeRelated:function(j,i){if(!this.related){return}if(j===this.related){var k=this.related||null;this.setRelated(null);this.onChange(this.instance,j,{_related:k})}}});h.HasMany=h.Relation.extend({collectionType:null,options:{reverseRelation:{type:"HasOne"},collectionType:h.Collection,collectionKey:true,collectionOptions:{}},initialize:function(){d.bindAll(this,"onChange","handleAddition","handleRemoval","handleReset");this.instance.bind("relational:change:"+this.key,this.onChange);this.collectionType=this.options.collectionType;if(d(this.collectionType).isString()){this.collectionType=h.Relational.store.getObjectByName(this.collectionType)}if(!this.collectionType.prototype instanceof h.Collection.prototype.constructor){throw new Error("collectionType must inherit from Backbone.Collection")}if(this.keyContents instanceof h.Collection){this.setRelated(this._prepareCollection(this.keyContents))}else{this.setRelated(this._prepareCollection())}this.findRelated({silent:true})},_getCollectionOptions:function(){return d.isFunction(this.options.collectionOptions)?this.options.collectionOptions(this.instance):this.options.collectionOptions},_prepareCollection:function(j){if(this.related){this.related.unbind("relational:add",this.handleAddition).unbind("relational:remove",this.handleRemoval).unbind("relational:reset",this.handleReset)}if(!j||!(j instanceof h.Collection)){j=new this.collectionType([],this._getCollectionOptions())}j.model=this.relatedModel;if(this.options.collectionKey){var i=this.options.collectionKey===true?this.options.reverseRelation.key:this.options.collectionKey;if(j[i]&&j[i]!==this.instance){if(h.Relational.showWarnings&&typeof console!=="undefined"){console.warn("Relation=%o; collectionKey=%s already exists on collection=%o",this,i,this.options.collectionKey)}}else{if(i){j[i]=this.instance}}}j.bind("relational:add",this.handleAddition).bind("relational:remove",this.handleRemoval).bind("relational:reset",this.handleReset);return j},findRelated:function(i){if(this.keyContents){var j=[];if(this.keyContents instanceof h.Collection){j=this.keyContents.models}else{this.keyContents=d.isArray(this.keyContents)?this.keyContents:[this.keyContents];d.each(this.keyContents,function(l){var k=h.Relational.store.find(this.relatedModel,l);if(k&&d.isObject(l)){k.set(l,i)}else{if(!k){k=this.createModel(l)}}if(k&&!this.related.getByCid(k)&&!this.related.get(k)){j.push(k)}},this)}if(j.length){i=this.unsanitizeOptions(i);this.related.add(j,i)}}},onChange:function(l,i,k){k=this.sanitizeOptions(k);this.keyContents=i;d.each(this.getReverseRelations(),function(n){n.removeRelated(this.instance,k)},this);if(i instanceof h.Collection){this._prepareCollection(i);this.related=i}else{var m;if(this.related instanceof h.Collection){m=this.related;m.reset([],{silent:true})}else{m=this._prepareCollection()}this.setRelated(m);this.findRelated(k)}d.each(this.getReverseRelations(),function(n){n.addRelated(this.instance,k)},this);var j=this;h.Relational.eventQueue.add(function(){!k.silentChange&&j.instance.trigger("update:"+j.key,j.instance,j.related,k)})},tryAddRelated:function(j,i){i=this.sanitizeOptions(i);if(!this.related.getByCid(j)&&!this.related.get(j)){var k=d.any(this.keyContents,function(l){var m=h.Relational.store.resolveIdForItem(this.relatedModel,l);return m&&m===j.id},this);if(k){this.related.add(j,i)}}},handleAddition:function(k,l,j){if(!(k instanceof h.Model)){return}j=this.sanitizeOptions(j);d.each(this.getReverseRelations(k),function(m){m.addRelated(this.instance,j)},this);var i=this;h.Relational.eventQueue.add(function(){!j.silentChange&&i.instance.trigger("add:"+i.key,k,i.related,j)})},handleRemoval:function(k,l,j){if(!(k instanceof h.Model)){return}j=this.sanitizeOptions(j);d.each(this.getReverseRelations(k),function(m){m.removeRelated(this.instance,j)},this);var i=this;h.Relational.eventQueue.add(function(){!j.silentChange&&i.instance.trigger("remove:"+i.key,k,i.related,j)})},handleReset:function(k,j){j=this.sanitizeOptions(j);var i=this;h.Relational.eventQueue.add(function(){!j.silentChange&&i.instance.trigger("reset:"+i.key,i.related,j)})},addRelated:function(k,j){var i=this;j=this.unsanitizeOptions(j);k.queue(function(){if(i.related&&!i.related.getByCid(k)&&!i.related.get(k)){i.related.add(k,j)}})},removeRelated:function(j,i){i=this.unsanitizeOptions(i);if(this.related.getByCid(j)||this.related.get(j)){this.related.remove(j,i)}}});h.RelationalModel=h.Model.extend({relations:null,_relations:null,_isInitialized:false,_deferProcessing:false,_queue:null,constructor:function(j,k){var i=this;if(k&&k.collection){this._deferProcessing=true;var l=function(m){if(m===i){i._deferProcessing=false;i.processQueue();k.collection.unbind("relational:add",l)}};k.collection.bind("relational:add",l);d.defer(function(){l(i)})}this._queue=new h.BlockingQueue();this._queue.block();h.Relational.eventQueue.block();h.Model.prototype.constructor.apply(this,arguments);h.Relational.eventQueue.unblock()},trigger:function(j){if(j.length>5&&"change"===j.substr(0,6)){var i=this,k=arguments;h.Relational.eventQueue.add(function(){h.Model.prototype.trigger.apply(i,k)})}else{h.Model.prototype.trigger.apply(this,arguments)}return this},initializeRelations:function(){this.acquire();this._relations=[];d.each(this.relations,function(i){var j=!d.isString(i.type)?i.type:h[i.type]||h.Relational.store.getObjectByName(i.type);if(j&&j.prototype instanceof h.Relation.prototype.constructor){new j(this,i)}else{h.Relational.showWarnings&&typeof console!=="undefined"&&console.warn("Relation=%o; missing or invalid type!",i)}},this);this._isInitialized=true;this.release();this.processQueue()},updateRelations:function(i){if(this._isInitialized&&!this.isLocked()){d.each(this._relations,function(j){var k=this.attributes[j.key];if(j.related!==k){this.trigger("relational:change:"+j.key,this,k,i||{})}},this)}},queue:function(i){this._queue.add(i)},processQueue:function(){if(this._isInitialized&&!this._deferProcessing&&this._queue.isBlocked()){this._queue.unblock()}},getRelation:function(i){return d.detect(this._relations,function(j){if(j.key===i){return true}},this)},getRelations:function(){return this._relations},fetchRelated:function(n,p){p||(p={});var l,j=[],o=this.getRelation(n),q=o&&o.keyContents,m=q&&d.select(d.isArray(q)?q:[q],function(r){var s=h.Relational.store.resolveIdForItem(o.relatedModel,r);return s&&!h.Relational.store.find(o.relatedModel,s)},this);if(m&&m.length){var k=d.map(m,function(t){var s;if(typeof(t)==="object"){s=new o.relatedModel(t)}else{var r={};r[o.relatedModel.prototype.idAttribute]=t;s=new o.relatedModel(r)}return s},this);if(o.related instanceof h.Collection&&d.isFunction(o.related.url)){l=o.related.url(k)}if(l&&l!==o.related.url()){var i=d.defaults({error:function(){var r=arguments;d.each(k,function(s){s.trigger("destroy",s,s.collection,p);p.error&&p.error.apply(s,r)})},url:l},p,{add:true});j=[o.related.fetch(i)]}else{j=d.map(k,function(r){var s=d.defaults({error:function(){r.trigger("destroy",r,r.collection,p);p.error&&p.error.apply(r,arguments)}},p);return r.fetch(s)},this)}}return j},set:function(l,m,k){h.Relational.eventQueue.block();var j;if(d.isObject(l)||l==null){j=l;k=m}else{j={};j[l]=m}var i=h.Model.prototype.set.apply(this,arguments);if(!this._isInitialized&&!this.isLocked()){h.Relational.store.register(this);this.initializeRelations()}else{if(j&&this.idAttribute in j){h.Relational.store.update(this)}}if(j){this.updateRelations(k)}h.Relational.eventQueue.unblock();return i},unset:function(k,j){h.Relational.eventQueue.block();var i=h.Model.prototype.unset.apply(this,arguments);this.updateRelations(j);h.Relational.eventQueue.unblock();return i},clear:function(j){h.Relational.eventQueue.block();var i=h.Model.prototype.clear.apply(this,arguments);this.updateRelations(j);h.Relational.eventQueue.unblock();return i},change:function(k){var i=this,j=arguments;h.Relational.eventQueue.add(function(){h.Model.prototype.change.apply(i,j)})},clone:function(){var i=d.clone(this.attributes);if(!d.isUndefined(i[this.idAttribute])){i[this.idAttribute]=null}d.each(this.getRelations(),function(j){delete i[j.key]});return new this.constructor(i)},toJSON:function(){if(this.isLocked()){return this.id}this.acquire();var i=h.Model.prototype.toJSON.call(this);d.each(this._relations,function(j){var k=i[j.key];if(j.options.includeInJSON===true&&k&&d.isFunction(k.toJSON)){i[j.keyDestination]=k.toJSON()}else{if(d.isString(j.options.includeInJSON)){if(k instanceof h.Collection){i[j.keyDestination]=k.pluck(j.options.includeInJSON)}else{if(k instanceof h.Model){i[j.keyDestination]=k.get(j.options.includeInJSON)}}}else{delete i[j.key]}}if(j.keyDestination!==j.key){delete i[j.key]}},this);this.release();return i}});d.extend(h.RelationalModel.prototype,h.Semaphore);var f=h.Collection.prototype.__add=h.Collection.prototype.add;h.Collection.prototype.add=function(k,i){i||(i={});if(!d.isArray(k)){k=[k]}var j=[];d.each(k,function(m){if(!(m instanceof h.Model)){var l=h.Relational.store.find(this.model,m[this.model.prototype.idAttribute]);if(l){l.set(l.parse?l.parse(m):m,i);m=l}else{m=h.Collection.prototype._prepareModel.call(this,m,i)}}if(m instanceof h.Model&&!this.get(m)&&!this.getByCid(m)){j.push(m)}},this);if(j.length){f.call(this,j,i);d.each(j,function(l){this.trigger("relational:add",l,this,i)},this)}return this};var a=h.Collection.prototype.__remove=h.Collection.prototype.remove;h.Collection.prototype.remove=function(j,i){i||(i={});if(!d.isArray(j)){j=[j]}d.each(j,function(k){k=this.getByCid(k)||this.get(k);if(k instanceof h.Model){a.call(this,k,i);this.trigger("relational:remove",k,this,i)}},this);return this};var e=h.Collection.prototype.__reset=h.Collection.prototype.reset;h.Collection.prototype.reset=function(j,i){e.call(this,j,i);this.trigger("relational:reset",j,i);return this};var c=h.Collection.prototype.__trigger=h.Collection.prototype.trigger;h.Collection.prototype.trigger=function(j){if(j==="add"||j==="remove"||j==="reset"){var i=this,k=arguments;h.Relational.eventQueue.add(function(){c.apply(i,k)})}else{c.apply(this,arguments)}return this};h.RelationalModel.extend=function(j,k){var l=h.Model.extend.apply(this,arguments);var i=(j&&j.relations)||[];d.each(i,function(m){if(m.reverseRelation){m.model=l;var o=true;if(d.isString(m.relatedModel)){var n=h.Relational.store.getObjectByName(m.relatedModel);o=n&&(n.prototype instanceof h.RelationalModel.prototype.constructor)}var p=!d.isString(m.type)?m.type:h[m.type]||h.Relational.store.getObjectByName(m.type);if(o&&p&&p.prototype instanceof h.Relation.prototype.constructor){new p(null,m)}}});return l}})();
\ No newline at end of file
+(function(b){var h,g,c;if(typeof window==="undefined"){h=require("underscore");g=require("backbone");c=module.exports=g}else{h=window._;g=window.Backbone;c=window}g.Relational={showWarnings:true};g.Semaphore={_permitsAvailable:null,_permitsUsed:0,acquire:function(){if(this._permitsAvailable&&this._permitsUsed>=this._permitsAvailable){throw new Error("Max permits acquired")}else{this._permitsUsed++}},release:function(){if(this._permitsUsed===0){throw new Error("All permits released")}else{this._permitsUsed--}},isLocked:function(){return this._permitsUsed>0},setAvailablePermits:function(j){if(this._permitsUsed>j){throw new Error("Available permits cannot be less than used permits")}this._permitsAvailable=j}};g.BlockingQueue=function(){this._queue=[]};h.extend(g.BlockingQueue.prototype,g.Semaphore,{_queue:null,add:function(j){if(this.isBlocked()){this._queue.push(j)}else{j()}},process:function(){while(this._queue&&this._queue.length){this._queue.shift()()}},block:function(){this.acquire()},unblock:function(){this.release();if(!this.isBlocked()){this.process()}},isBlocked:function(){return this.isLocked()}});g.Relational.eventQueue=new g.BlockingQueue();g.Store=function(){this._collections=[];this._reverseRelations=[];this._subModels=[];this._modelScopes=[c]};h.extend(g.Store.prototype,g.Events,{addModelScope:function(j){this._modelScopes.push(j)},addSubModels:function(j,k){this._subModels.push({superModelType:k,subModels:j})},setupSuperModel:function(j){h.find(this._subModels,function(k){return h.find(k.subModels,function(m,n){var l=this.getObjectByName(m);if(j===l){k.superModelType._subModels[n]=j;j._superModel=k.superModelType;j._subModelTypeValue=n;j._subModelTypeAttribute=k.superModelType.prototype.subModelTypeAttribute;return true}},this)},this)},addReverseRelation:function(l){var k=h.any(this._reverseRelations,function(m){return h.all(l,function(o,n){return o===m[n]})});if(!k&&l.model&&l.type){this._reverseRelations.push(l);var j=function(m,n){if(!m.prototype.relations){m.prototype.relations=[]}m.prototype.relations.push(n);h.each(m._subModels,function(o){j(o,n)},this)};j(l.model,l);this.retroFitRelation(l)}},retroFitRelation:function(k){var j=this.getCollection(k.model);j.each(function(l){if(!(l instanceof k.model)){return}new k.type(l,k)},this)},getCollection:function(k){if(k instanceof g.RelationalModel){k=k.constructor}var j=k;while(j._superModel){j=j._superModel}var l=h.detect(this._collections,function(m){return m.model===j});if(!l){l=this._createCollection(k)}return l},getObjectByName:function(j){var l=j.split("."),k=null;h.find(this._modelScopes,function(m){k=h.reduce(l,function(n,o){return n[o]},m);if(k&&k!==m){return true}},this);return k},_createCollection:function(k){var j;if(k instanceof g.RelationalModel){k=k.constructor}if(k.prototype instanceof g.RelationalModel){j=new g.Collection();j.model=k;this._collections.push(j)}return j},resolveIdForItem:function(j,k){var l=h.isString(k)||h.isNumber(k)?k:null;if(l==null){if(k instanceof g.RelationalModel){l=k.id}else{if(h.isObject(k)){l=k[j.prototype.idAttribute]}}}return l},find:function(k,l){var n=this.resolveIdForItem(k,l);var j=this.getCollection(k);if(j){var m=j.get(n);if(m instanceof k){return m}}return null},register:function(k){var j=k.collection;var l=this.getCollection(k);l&&l.add(k);k.bind("destroy",this.unregister,this);k.collection=j},update:function(j){var k=this.getCollection(j);k._onModelEvent("change:"+j.idAttribute,j,k)},unregister:function(j){j.unbind("destroy",this.unregister);var k=this.getCollection(j);k&&k.remove(j)}});g.Relational.store=new g.Store();g.Relation=function(j,k){this.instance=j;k=h.isObject(k)?k:{};this.reverseRelation=h.defaults(k.reverseRelation||{},this.options.reverseRelation);this.reverseRelation.type=!h.isString(this.reverseRelation.type)?this.reverseRelation.type:g[this.reverseRelation.type]||g.Relational.store.getObjectByName(this.reverseRelation.type);this.model=k.model||this.instance.constructor;this.options=h.defaults(k,this.options,g.Relation.prototype.options);this.key=this.options.key;this.keySource=this.options.keySource||this.key;this.keyDestination=this.options.keyDestination||this.keySource||this.key;this.relatedModel=this.options.relatedModel;if(h.isString(this.relatedModel)){this.relatedModel=g.Relational.store.getObjectByName(this.relatedModel)}if(!this.checkPreconditions()){return false}if(j){this.keyContents=this.instance.get(this.keySource);if(this.key!==this.keySource){this.instance.unset(this.keySource,{silent:true})}this.instance._relations.push(this)}if(!this.options.isAutoRelation&&this.reverseRelation.type&&this.reverseRelation.key){g.Relational.store.addReverseRelation(h.defaults({isAutoRelation:true,model:this.relatedModel,relatedModel:this.model,reverseRelation:this.options},this.reverseRelation))}h.bindAll(this,"_modelRemovedFromCollection","_relatedModelAdded","_relatedModelRemoved");if(j){this.initialize();g.Relational.store.getCollection(this.instance).bind("relational:remove",this._modelRemovedFromCollection);g.Relational.store.getCollection(this.relatedModel).bind("relational:add",this._relatedModelAdded).bind("relational:remove",this._relatedModelRemoved)}};g.Relation.extend=g.Model.extend;h.extend(g.Relation.prototype,g.Events,g.Semaphore,{options:{createModels:true,includeInJSON:true,isAutoRelation:false},instance:null,key:null,keyContents:null,relatedModel:null,reverseRelation:null,related:null,_relatedModelAdded:function(l,m,k){var j=this;l.queue(function(){j.tryAddRelated(l,k)})},_relatedModelRemoved:function(k,l,j){this.removeRelated(k,j)},_modelRemovedFromCollection:function(j){if(j===this.instance){this.destroy()}},checkPreconditions:function(){var n=this.instance,l=this.key,j=this.model,p=this.relatedModel,q=g.Relational.showWarnings&&typeof console!=="undefined";if(!j||!l||!p){q&&console.warn("Relation=%o; no model, key or relatedModel (%o, %o, %o)",this,j,l,p);return false}if(!(j.prototype instanceof g.RelationalModel)){q&&console.warn("Relation=%o; model does not inherit from Backbone.RelationalModel (%o)",this,n);return false}if(!(p.prototype instanceof g.RelationalModel)){q&&console.warn("Relation=%o; relatedModel does not inherit from Backbone.RelationalModel (%o)",this,p);return false}if(this instanceof g.HasMany&&this.reverseRelation.type===g.HasMany){q&&console.warn("Relation=%o; relation is a HasMany, and the reverseRelation is HasMany as well.",this);return false}if(n&&n._relations.length){var o=h.any(n._relations,function(k){var m=this.reverseRelation.key&&k.reverseRelation.key;return k.relatedModel===p&&k.key===l&&(!m||this.reverseRelation.key===k.reverseRelation.key)},this);if(o){q&&console.warn("Relation=%o between instance=%o.%s and relatedModel=%o.%s already exists",this,n,l,p,this.reverseRelation.key);return false}}return true},setRelated:function(k,j){this.related=k;this.instance.acquire();this.instance.set(this.key,k,h.defaults(j||{},{silent:true}));this.instance.release()},_isReverseRelation:function(j){if(j.instance instanceof this.relatedModel&&this.reverseRelation.key===j.key&&this.key===j.reverseRelation.key){return true}return false},getReverseRelations:function(j){var k=[];var l=!h.isUndefined(j)?[j]:this.related&&(this.related.models||[this.related]);h.each(l,function(m){h.each(m.getRelations(),function(n){if(this._isReverseRelation(n)){k.push(n)}},this)},this);return k},sanitizeOptions:function(j){j=j?h.clone(j):{};if(j.silent){j.silentChange=true;delete j.silent}return j},unsanitizeOptions:function(j){j=j?h.clone(j):{};if(j.silentChange){j.silent=true;delete j.silentChange}return j},destroy:function(){g.Relational.store.getCollection(this.instance).unbind("relational:remove",this._modelRemovedFromCollection);g.Relational.store.getCollection(this.relatedModel).unbind("relational:add",this._relatedModelAdded).unbind("relational:remove",this._relatedModelRemoved);h.each(this.getReverseRelations(),function(j){j.removeRelated(this.instance)},this)}});g.HasOne=g.Relation.extend({options:{reverseRelation:{type:"HasMany"}},initialize:function(){h.bindAll(this,"onChange");this.instance.bind("relational:change:"+this.key,this.onChange);var j=this.findRelated({silent:true});this.setRelated(j);h.each(this.getReverseRelations(),function(k){k.addRelated(this.instance)},this)},findRelated:function(k){var l=this.keyContents;var j=null;if(l instanceof this.relatedModel){j=l}else{if(l){j=this.relatedModel.findOrCreate(l,{create:this.options.createModels})}}return j},onChange:function(m,j,l){if(this.isLocked()){return}this.acquire();l=this.sanitizeOptions(l);var p=h.isUndefined(l._related);var n=p?this.related:l._related;if(p){this.keyContents=j;if(j instanceof this.relatedModel){this.related=j}else{if(j){var o=this.findRelated(l);this.setRelated(o)}else{this.setRelated(null)}}}if(n&&this.related!==n){h.each(this.getReverseRelations(n),function(q){q.removeRelated(this.instance,l)},this)}h.each(this.getReverseRelations(),function(q){q.addRelated(this.instance,l)},this);if(!l.silentChange&&this.related!==n){var k=this;g.Relational.eventQueue.add(function(){k.instance.trigger("update:"+k.key,k.instance,k.related,l)})}this.release()},tryAddRelated:function(k,j){if(this.related){return}j=this.sanitizeOptions(j);var l=this.keyContents;if(l){var m=g.Relational.store.resolveIdForItem(this.relatedModel,l);if(k.id===m){this.addRelated(k,j)}}},addRelated:function(k,j){if(k!==this.related){var l=this.related||null;this.setRelated(k);this.onChange(this.instance,k,{_related:l})}},removeRelated:function(k,j){if(!this.related){return}if(k===this.related){var l=this.related||null;this.setRelated(null);this.onChange(this.instance,k,{_related:l})}}});g.HasMany=g.Relation.extend({collectionType:null,options:{reverseRelation:{type:"HasOne"},collectionType:g.Collection,collectionKey:true,collectionOptions:{}},initialize:function(){h.bindAll(this,"onChange","handleAddition","handleRemoval","handleReset");this.instance.bind("relational:change:"+this.key,this.onChange);this.collectionType=this.options.collectionType;if(h.isString(this.collectionType)){this.collectionType=g.Relational.store.getObjectByName(this.collectionType)}if(!this.collectionType.prototype instanceof g.Collection){throw new Error("collectionType must inherit from Backbone.Collection")}if(this.keyContents instanceof g.Collection){this.setRelated(this._prepareCollection(this.keyContents))}else{this.setRelated(this._prepareCollection())}this.findRelated({silent:true})},_getCollectionOptions:function(){return h.isFunction(this.options.collectionOptions)?this.options.collectionOptions(this.instance):this.options.collectionOptions},_prepareCollection:function(k){if(this.related){this.related.unbind("relational:add",this.handleAddition).unbind("relational:remove",this.handleRemoval).unbind("relational:reset",this.handleReset)}if(!k||!(k instanceof g.Collection)){k=new this.collectionType([],this._getCollectionOptions())}k.model=this.relatedModel;if(this.options.collectionKey){var j=this.options.collectionKey===true?this.options.reverseRelation.key:this.options.collectionKey;if(k[j]&&k[j]!==this.instance){if(g.Relational.showWarnings&&typeof console!=="undefined"){console.warn("Relation=%o; collectionKey=%s already exists on collection=%o",this,j,this.options.collectionKey)}}else{if(j){k[j]=this.instance}}}k.bind("relational:add",this.handleAddition).bind("relational:remove",this.handleRemoval).bind("relational:reset",this.handleReset);return k},findRelated:function(j){if(this.keyContents){var k=[];if(this.keyContents instanceof g.Collection){k=this.keyContents.models}else{this.keyContents=h.isArray(this.keyContents)?this.keyContents:[this.keyContents];h.each(this.keyContents,function(m){var l=null;if(m instanceof this.relatedModel){l=m}else{l=this.relatedModel.findOrCreate(m,{create:this.options.createModels})}if(l&&!this.related.getByCid(l)&&!this.related.get(l)){k.push(l)}},this)}if(k.length){j=this.unsanitizeOptions(j);this.related.add(k,j)}}},onChange:function(m,j,l){l=this.sanitizeOptions(l);this.keyContents=j;h.each(this.getReverseRelations(),function(o){o.removeRelated(this.instance,l)},this);if(j instanceof g.Collection){this._prepareCollection(j);this.related=j}else{var n;if(this.related instanceof g.Collection){n=this.related;n.remove(n.models)}else{n=this._prepareCollection()}this.setRelated(n);this.findRelated(l)}h.each(this.getReverseRelations(),function(o){o.addRelated(this.instance,l)},this);var k=this;g.Relational.eventQueue.add(function(){!l.silentChange&&k.instance.trigger("update:"+k.key,k.instance,k.related,l)})},tryAddRelated:function(k,j){j=this.sanitizeOptions(j);if(!this.related.getByCid(k)&&!this.related.get(k)){var l=h.any(this.keyContents,function(m){var n=g.Relational.store.resolveIdForItem(this.relatedModel,m);return n&&n===k.id},this);if(l){this.related.add(k,j)}}},handleAddition:function(l,m,k){if(!(l instanceof g.Model)){return}k=this.sanitizeOptions(k);h.each(this.getReverseRelations(l),function(n){n.addRelated(this.instance,k)},this);var j=this;g.Relational.eventQueue.add(function(){!k.silentChange&&j.instance.trigger("add:"+j.key,l,j.related,k)})},handleRemoval:function(l,m,k){if(!(l instanceof g.Model)){return}k=this.sanitizeOptions(k);h.each(this.getReverseRelations(l),function(n){n.removeRelated(this.instance,k)},this);var j=this;g.Relational.eventQueue.add(function(){!k.silentChange&&j.instance.trigger("remove:"+j.key,l,j.related,k)})},handleReset:function(l,k){k=this.sanitizeOptions(k);var j=this;g.Relational.eventQueue.add(function(){!k.silentChange&&j.instance.trigger("reset:"+j.key,j.related,k)})},addRelated:function(l,k){var j=this;k=this.unsanitizeOptions(k);l.queue(function(){if(j.related&&!j.related.getByCid(l)&&!j.related.get(l)){j.related.add(l,k)}})},removeRelated:function(k,j){j=this.unsanitizeOptions(j);if(this.related.getByCid(k)||this.related.get(k)){this.related.remove(k,j)}}});g.RelationalModel=g.Model.extend({relations:null,_relations:null,_isInitialized:false,_deferProcessing:false,_queue:null,subModelTypeAttribute:"type",subModelTypes:null,constructor:function(k,l){var j=this;if(l&&l.collection){this._deferProcessing=true;var m=function(n){if(n===j){j._deferProcessing=false;j.processQueue();l.collection.unbind("relational:add",m)}};l.collection.bind("relational:add",m);h.defer(function(){m(j)})}this._queue=new g.BlockingQueue();this._queue.block();g.Relational.eventQueue.block();g.Model.apply(this,arguments);g.Relational.eventQueue.unblock()},trigger:function(k){if(k.length>5&&"change"===k.substr(0,6)){var j=this,l=arguments;g.Relational.eventQueue.add(function(){g.Model.prototype.trigger.apply(j,l)})}else{g.Model.prototype.trigger.apply(this,arguments)}return this},initializeRelations:function(){this.acquire();this._relations=[];h.each(this.relations,function(j){var k=!h.isString(j.type)?j.type:g[j.type]||g.Relational.store.getObjectByName(j.type);if(k&&k.prototype instanceof g.Relation){new k(this,j)}else{g.Relational.showWarnings&&typeof console!=="undefined"&&console.warn("Relation=%o; missing or invalid type!",j)}},this);this._isInitialized=true;this.release();this.processQueue()},updateRelations:function(j){if(this._isInitialized&&!this.isLocked()){h.each(this._relations,function(k){var l=this.attributes[k.keySource]||this.attributes[k.key];if(k.related!==l){this.trigger("relational:change:"+k.key,this,l,j||{})}},this)}},queue:function(j){this._queue.add(j)},processQueue:function(){if(this._isInitialized&&!this._deferProcessing&&this._queue.isBlocked()){this._queue.unblock()}},getRelation:function(j){return h.detect(this._relations,function(k){if(k.key===j){return true}},this)},getRelations:function(){return this._relations},fetchRelated:function(p,r,n){r||(r={});var m,k=[],q=this.getRelation(p),s=q&&q.keyContents,o=s&&h.select(h.isArray(s)?s:[s],function(t){var u=g.Relational.store.resolveIdForItem(q.relatedModel,t);return u&&(n||!g.Relational.store.find(q.relatedModel,u))},this);if(o&&o.length){var l=h.map(o,function(v){var u;if(h.isObject(v)){u=q.relatedModel.build(v)}else{var t={};t[q.relatedModel.prototype.idAttribute]=v;u=q.relatedModel.build(t)}return u},this);if(q.related instanceof g.Collection&&h.isFunction(q.related.url)){m=q.related.url(l)}if(m&&m!==q.related.url()){var j=h.defaults({error:function(){var t=arguments;h.each(l,function(u){u.trigger("destroy",u,u.collection,r);r.error&&r.error.apply(u,t)})},url:m},r,{add:true});k=[q.related.fetch(j)]}else{k=h.map(l,function(t){var u=h.defaults({error:function(){t.trigger("destroy",t,t.collection,r);r.error&&r.error.apply(t,arguments)}},r);return t.fetch(u)},this)}}return k},set:function(m,n,l){g.Relational.eventQueue.block();var k;if(h.isObject(m)||m==null){k=m;l=n}else{k={};k[m]=n}var j=g.Model.prototype.set.apply(this,arguments);if(!this._isInitialized&&!this.isLocked()){this.constructor.initializeModelHierarchy();g.Relational.store.register(this);this.initializeRelations()}else{if(k&&this.idAttribute in k){g.Relational.store.update(this)}}if(k){this.updateRelations(l)}g.Relational.eventQueue.unblock();return j},unset:function(l,k){g.Relational.eventQueue.block();var j=g.Model.prototype.unset.apply(this,arguments);this.updateRelations(k);g.Relational.eventQueue.unblock();return j},clear:function(k){g.Relational.eventQueue.block();var j=g.Model.prototype.clear.apply(this,arguments);this.updateRelations(k);g.Relational.eventQueue.unblock();return j},change:function(l){var j=this,k=arguments;g.Relational.eventQueue.add(function(){g.Model.prototype.change.apply(j,k)})},clone:function(){var j=h.clone(this.attributes);if(!h.isUndefined(j[this.idAttribute])){j[this.idAttribute]=null}h.each(this.getRelations(),function(k){delete j[k.key]});return new this.constructor(j)},toJSON:function(){if(this.isLocked()){return this.id}this.acquire();var j=g.Model.prototype.toJSON.call(this);if(this.constructor._superModel&&!(this.constructor._subModelTypeAttribute in j)){j[this.constructor._subModelTypeAttribute]=this.constructor._subModelTypeValue}h.each(this._relations,function(k){var m=j[k.key];if(k.options.includeInJSON===true){if(m&&h.isFunction(m.toJSON)){j[k.keyDestination]=m.toJSON()}else{j[k.keyDestination]=null}}else{if(h.isString(k.options.includeInJSON)){if(m instanceof g.Collection){j[k.keyDestination]=m.pluck(k.options.includeInJSON)}else{if(m instanceof g.Model){j[k.keyDestination]=m.get(k.options.includeInJSON)}else{j[k.keyDestination]=null}}}else{if(h.isArray(k.options.includeInJSON)){if(m instanceof g.Collection){var l=[];m.each(function(o){var n={};h.each(k.options.includeInJSON,function(p){n[p]=o.get(p)});l.push(n)});j[k.keyDestination]=l}else{if(m instanceof g.Model){var l={};h.each(k.options.includeInJSON,function(n){l[n]=m.get(n)});j[k.keyDestination]=l}else{j[k.keyDestination]=null}}}else{delete j[k.key]}}}if(k.keyDestination!==k.key){delete j[k.key]}});this.release();return j}},{setup:function(j){this.prototype.relations=(this.prototype.relations||[]).slice(0);this._subModels={};this._superModel=null;if(this.prototype.hasOwnProperty("subModelTypes")){g.Relational.store.addSubModels(this.prototype.subModelTypes,this)}else{this.prototype.subModelTypes=null}h.each(this.prototype.relations,function(k){if(!k.model){k.model=this}if(k.reverseRelation&&k.model===this){var m=true;if(h.isString(k.relatedModel)){var l=g.Relational.store.getObjectByName(k.relatedModel);m=l&&(l.prototype instanceof g.RelationalModel)}var n=!h.isString(k.type)?k.type:g[k.type]||g.Relational.store.getObjectByName(k.type);if(m&&n&&n.prototype instanceof g.Relation){new n(null,k)}}},this)},build:function(l,n){var m=this;this.initializeModelHierarchy();if(this._subModels&&this.prototype.subModelTypeAttribute in l){var k=l[this.prototype.subModelTypeAttribute];var j=this._subModels[k];if(j){m=j}}return new m(l,n)},initializeModelHierarchy:function(){if(h.isUndefined(this._superModel)||h.isNull(this._superModel)){g.Relational.store.setupSuperModel(this);if(this._superModel){if(this._superModel.prototype.relations){var j=h.any(this.prototype.relations,function(k){return k.model&&k.model!==this},this);if(!j){this.prototype.relations=this._superModel.prototype.relations.concat(this.prototype.relations)}}}else{this._superModel=false}}if(this.prototype.subModelTypes&&h.keys(this.prototype.subModelTypes).length!==h.keys(this._subModels).length){h.each(this.prototype.subModelTypes,function(l){var k=g.Relational.store.getObjectByName(l);k&&k.initializeModelHierarchy()})}},findOrCreate:function(j,l){var k=g.Relational.store.find(this,j);if(h.isObject(j)){if(k){k.set(j,l)}else{if(!l||(l&&l.create!==false)){k=this.build(j,l)}}}return k}});h.extend(g.RelationalModel.prototype,g.Semaphore);g.Collection.prototype.__prepareModel=g.Collection.prototype._prepareModel;g.Collection.prototype._prepareModel=function(l,k){k||(k={});if(!(l instanceof g.Model)){var j=l;k.collection=this;if(typeof this.model.build!=="undefined"){l=this.model.build(j,k)}else{l=new this.model(j,k)}if(!l._validate(l.attributes,k)){l=false}}else{if(!l.collection){l.collection=this}}return l};var i=g.Collection.prototype.__add=g.Collection.prototype.add;g.Collection.prototype.add=function(l,j){j||(j={});if(!h.isArray(l)){l=[l]}var k=[];h.each(l,function(n){if(!(n instanceof g.Model)){var m=g.Relational.store.find(this.model,n[this.model.prototype.idAttribute]);if(m){m.set(m.parse?m.parse(n):n,j);n=m}else{n=g.Collection.prototype._prepareModel.call(this,n,j)}}if(n instanceof g.Model&&!this.get(n)&&!this.getByCid(n)){k.push(n)}},this);if(k.length){i.call(this,k,j);h.each(k,function(m){this.trigger("relational:add",m,this,j)},this)}return this};var e=g.Collection.prototype.__remove=g.Collection.prototype.remove;g.Collection.prototype.remove=function(k,j){j||(j={});if(!h.isArray(k)){k=[k]}else{k=k.slice(0)}h.each(k,function(l){l=this.getByCid(l)||this.get(l);if(l instanceof g.Model){e.call(this,l,j);this.trigger("relational:remove",l,this,j)}},this);return this};var f=g.Collection.prototype.__reset=g.Collection.prototype.reset;g.Collection.prototype.reset=function(k,j){f.call(this,k,j);this.trigger("relational:reset",this,j);return this};var d=g.Collection.prototype.__sort=g.Collection.prototype.sort;g.Collection.prototype.sort=function(j){d.call(this,j);this.trigger("relational:reset",this,j);return this};var a=g.Collection.prototype.__trigger=g.Collection.prototype.trigger;g.Collection.prototype.trigger=function(k){if(k==="add"||k==="remove"||k==="reset"){var j=this,l=arguments;g.Relational.eventQueue.add(function(){a.apply(j,l)})}else{a.apply(this,arguments)}return this};g.RelationalModel.extend=function(j,k){var l=g.Model.extend.apply(this,arguments);l.setup(this);return l}})();
\ No newline at end of file
diff -r f7d0c01430f761a73db0f7dc18bd025ad6768575 -r 9b7cf76169b41729ee6253d9722145347e9f5213 static/scripts/packed/mvc/data.js
--- /dev/null
+++ b/static/scripts/packed/mvc/data.js
@@ -0,0 +1,1 @@
+var Dataset=Backbone.RelationalModel.extend({defaults:{id:"",type:"",name:"",hda_ldda:"hda"}});var DatasetCollection=Backbone.Collection.extend({model:Dataset});
\ No newline at end of file
diff -r f7d0c01430f761a73db0f7dc18bd025ad6768575 -r 9b7cf76169b41729ee6253d9722145347e9f5213 static/scripts/packed/mvc/tools.js
--- a/static/scripts/packed/mvc/tools.js
+++ b/static/scripts/packed/mvc/tools.js
@@ -1,1 +1,1 @@
-var BaseModel=Backbone.RelationalModel.extend({defaults:{name:null,hidden:false},show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},is_visible:function(){return !this.attributes.hidden}});var Tool=BaseModel.extend({defaults:{description:null,target:null,inputs:[]},relations:[{type:Backbone.HasMany,key:"inputs",relatedModel:"ToolInput",reverseRelation:{key:"tool"}}],urlRoot:galaxy_paths.attributes.root_path+"api/tools",apply_search_results:function(a){(_.indexOf(a,this.attributes.id)!==-1?this.show():this.hide());return this.is_visible()}});var ToolInput=Backbone.RelationalModel.extend({defaults:{name:null,type:null},initialize:function(){this.attributes.html=unescape(this.attributes.html)},get_samples:function(b){var c=this.get("type"),a=[];if(c==="number"){a=d3.scale.linear().domain([this.get("min"),this.get("max")]).ticks(b)}else{if(c==="select"){a=_.map(this.get("options"),function(d){return d[0]})}}return new ParamSamples({param:this,samples:a})}});var ParamSamples=Backbone.Model.extend({defaults:{param:null,samples:null}});var ToolCollection=Backbone.Collection.extend({model:Tool});var ToolPanelLabel=BaseModel.extend({});var ToolPanelSection=BaseModel.extend({defaults:{elems:[],open:false},clear_search_results:function(){_.each(this.attributes.elems,function(a){a.show()});this.show();this.set("open",false)},apply_search_results:function(b){var c=true,a;_.each(this.attributes.elems,function(d){if(d instanceof ToolPanelLabel){a=d;a.hide()}else{if(d instanceof Tool){if(d.apply_search_results(b)){c=false;if(a){a.show()}}}}});if(c){this.hide()}else{this.show();this.set("open",true)}}});var ToolSearch=BaseModel.extend({defaults:{spinner_url:"",search_url:"",visible:true,query:"",results:null},initialize:function(){this.on("change:query",this.do_search)},do_search:function(){var c=this.attributes.query;if(c.length<3){this.set("results",null);return}var b=c+"*";if(this.timer){clearTimeout(this.timer)}$("#search-spinner").show();var a=this;this.timer=setTimeout(function(){$.get(a.attributes.search_url,{query:b},function(d){a.set("results",d);$("#search-spinner").hide()},"json")},200)}});var ToolPanel=Backbone.Collection.extend({url:"/tools",tools:new ToolCollection(),parse:function(a){var b=function(e){var d=e.type;if(d==="tool"){return new Tool(e)}else{if(d==="section"){var c=_.map(e.elems,b);e.elems=c;return new ToolPanelSection(e)}else{if(d==="label"){return new ToolPanelLabel(e)}}}};return _.map(a,b)},initialize:function(a){this.tool_search=a.tool_search;this.tool_search.on("change:results",this.apply_search_results,this);this.on("reset",this.populate_tools,this)},populate_tools:function(){var a=this;a.tools=new ToolCollection();this.each(function(b){if(b instanceof ToolPanelSection){_.each(b.attributes.elems,function(c){if(c instanceof Tool){a.tools.push(c)}})}else{if(b instanceof Tool){a.tools.push(b)}}})},clear_search_results:function(){this.each(function(a){if(a instanceof ToolPanelSection){a.clear_search_results()}else{a.show()}})},apply_search_results:function(){var b=this.tool_search.attributes.results;if(b===null){this.clear_search_results();return}var a=null;this.each(function(c){if(c instanceof ToolPanelLabel){a=c;a.hide()}else{if(c instanceof Tool){if(c.apply_search_results(b)){if(a){a.show()}}}else{a=null;c.apply_search_results(b)}}})}});var BaseView=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){(this.model.attributes.hidden?this.$el.hide():this.$el.show())}});var ToolLinkView=BaseView.extend({tagName:"div",template:Handlebars.templates.tool_link,render:function(){this.$el.append(this.template(this.model.toJSON()));return this}});var ToolPanelLabelView=BaseView.extend({tagName:"div",className:"toolPanelLabel",render:function(){this.$el.append($("<span/>").text(this.model.attributes.name));return this}});var ToolPanelSectionView=BaseView.extend({tagName:"div",className:"toolSectionWrapper",template:Handlebars.templates.panel_section,initialize:function(){BaseView.prototype.initialize.call(this);this.model.on("change:open",this.update_open,this)},render:function(){this.$el.append(this.template(this.model.toJSON()));var a=this.$el.find(".toolSectionBody");_.each(this.model.attributes.elems,function(b){if(b instanceof Tool){var c=new ToolLinkView({model:b,className:"toolTitle"});c.render();a.append(c.$el)}else{if(b instanceof ToolPanelLabel){var d=new ToolPanelLabelView({model:b});d.render();a.append(d.$el)}else{}}});return this},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.model.set("open",!this.model.attributes.open)},update_open:function(){(this.model.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"):this.$el.children(".toolSectionBody").slideUp("fast"))}});var ToolSearchView=Backbone.View.extend({tagName:"div",id:"tool-search",className:"bar",template:Handlebars.templates.tool_search,events:{click:"focus_and_select","keyup :input":"query_changed"},render:function(){this.$el.append(this.template(this.model.toJSON()));if(!this.model.is_visible()){this.$el.hide()}return this},focus_and_select:function(){this.$el.find(":input").focus().select()},query_changed:function(){this.model.set("query",this.$el.find(":input").val())}});var ToolPanelView=Backbone.View.extend({tagName:"div",className:"toolMenu",initialize:function(){this.collection.tool_search.on("change:results",this.handle_search_results,this)},render:function(){var a=this;var b=new ToolSearchView({model:this.collection.tool_search});b.render();a.$el.append(b.$el);this.collection.each(function(d){if(d instanceof ToolPanelSection){var c=new ToolPanelSectionView({model:d});c.render();a.$el.append(c.$el)}else{if(d instanceof Tool){var e=new ToolLinkView({model:d,className:"toolTitleNoSection"});e.render();a.$el.append(e.$el)}else{if(d instanceof ToolPanelLabel){var f=new ToolPanelLabelView({model:d});f.render();a.$el.append(f.$el)}}}});a.$el.find("a.tool-link").click(function(f){var d=$(this).attr("class").split(/\s+/)[0],c=a.collection.tools.get(d);a.trigger("tool_link_click",f,c)});return this},handle_search_results:function(){var a=this.collection.tool_search.attributes.results;if(a&&a.length===0){$("#search-no-results").show()}else{$("#search-no-results").hide()}}});var ToolFormView=Backbone.View.extend({className:"toolForm",template:Handlebars.templates.tool_form,render:function(){this.$el.children().remove();this.$el.append(this.template(this.model.toJSON()))}});var IntegratedToolMenuAndView=Backbone.View.extend({className:"toolMenuAndView",initialize:function(){this.tool_panel_view=new ToolPanelView({collection:this.collection});this.tool_form_view=new ToolFormView()},render:function(){this.tool_panel_view.render();this.tool_panel_view.$el.css("float","left");this.$el.append(this.tool_panel_view.$el);this.tool_form_view.$el.hide();this.$el.append(this.tool_form_view.$el);var a=this;this.tool_panel_view.on("tool_link_click",function(c,b){c.preventDefault();a.show_tool(b)})},show_tool:function(b){var a=this;b.fetch().done(function(){a.tool_form_view.model=b;a.tool_form_view.render();a.tool_form_view.$el.show();$("#left").width("650px")})}});
\ No newline at end of file
+var BaseModel=Backbone.RelationalModel.extend({defaults:{name:null,hidden:false},show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},is_visible:function(){return !this.attributes.hidden}});var Tool=BaseModel.extend({defaults:{description:null,target:null,inputs:[]},relations:[{type:Backbone.HasMany,key:"inputs",relatedModel:"ToolInput",reverseRelation:{key:"tool",includeInJSON:false}}],urlRoot:galaxy_paths.get("tool_url"),copy:function(b){var c=new Tool(this.toJSON());if(b){var a=new Backbone.Collection();c.get("inputs").each(function(d){if(d.get_samples()){a.push(d)}});c.set("inputs",a)}return c},apply_search_results:function(a){(_.indexOf(a,this.attributes.id)!==-1?this.show():this.hide());return this.is_visible()},set_input_value:function(a,b){this.get("inputs").find(function(c){return c.get("name")===a}).set("value",b)},set_input_values:function(b){var a=this;_.each(_.keys(b),function(c){a.set_input_value(c,b[c])})},run:function(){return this._run()},rerun:function(b,a){return this._run({action:"rerun",target_dataset_id:b.id,regions:a})},get_inputs_dict:function(){var a={};this.get("inputs").each(function(b){a[b.get("name")]=b.get("value")});return a},_run:function(c){var d=_.extend({tool_id:this.id,inputs:this.get_inputs_dict()},c);var b=$.Deferred(),a=new ServerStateDeferred({ajax_settings:{url:this.urlRoot,data:JSON.stringify(d),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(e){return e!=="pending"}});$.when(a.go()).then(function(e){b.resolve(new DatasetCollection().reset(e))});return b}});var ToolInput=Backbone.RelationalModel.extend({defaults:{name:null,label:null,type:null,value:null,num_samples:5},initialize:function(){this.attributes.html=unescape(this.attributes.html)},copy:function(){return new ToolInput(this.toJSON())},get_samples:function(){var b=this.get("type"),a=null;if(b==="number"){a=d3.scale.linear().domain([this.get("min"),this.get("max")]).ticks(this.get("num_samples"))}else{if(b==="select"){a=_.map(this.get("options"),function(c){return c[0]})}}return a}});var ToolCollection=Backbone.Collection.extend({model:Tool});var ToolPanelLabel=BaseModel.extend({});var ToolPanelSection=BaseModel.extend({defaults:{elems:[],open:false},clear_search_results:function(){_.each(this.attributes.elems,function(a){a.show()});this.show();this.set("open",false)},apply_search_results:function(b){var c=true,a;_.each(this.attributes.elems,function(d){if(d instanceof ToolPanelLabel){a=d;a.hide()}else{if(d instanceof Tool){if(d.apply_search_results(b)){c=false;if(a){a.show()}}}}});if(c){this.hide()}else{this.show();this.set("open",true)}}});var ToolSearch=BaseModel.extend({defaults:{spinner_url:"",search_url:"",visible:true,query:"",results:null},initialize:function(){this.on("change:query",this.do_search)},do_search:function(){var c=this.attributes.query;if(c.length<3){this.set("results",null);return}var b=c+"*";if(this.timer){clearTimeout(this.timer)}$("#search-spinner").show();var a=this;this.timer=setTimeout(function(){$.get(a.attributes.search_url,{query:b},function(d){a.set("results",d);$("#search-spinner").hide()},"json")},200)}});var ToolPanel=Backbone.Collection.extend({url:"/tools",tools:new ToolCollection(),parse:function(a){var b=function(e){var d=e.type;if(d==="tool"){return new Tool(e)}else{if(d==="section"){var c=_.map(e.elems,b);e.elems=c;return new ToolPanelSection(e)}else{if(d==="label"){return new ToolPanelLabel(e)}}}};return _.map(a,b)},initialize:function(a){this.tool_search=a.tool_search;this.tool_search.on("change:results",this.apply_search_results,this);this.on("reset",this.populate_tools,this)},populate_tools:function(){var a=this;a.tools=new ToolCollection();this.each(function(b){if(b instanceof ToolPanelSection){_.each(b.attributes.elems,function(c){if(c instanceof Tool){a.tools.push(c)}})}else{if(b instanceof Tool){a.tools.push(b)}}})},clear_search_results:function(){this.each(function(a){if(a instanceof ToolPanelSection){a.clear_search_results()}else{a.show()}})},apply_search_results:function(){var b=this.tool_search.attributes.results;if(b===null){this.clear_search_results();return}var a=null;this.each(function(c){if(c instanceof ToolPanelLabel){a=c;a.hide()}else{if(c instanceof Tool){if(c.apply_search_results(b)){if(a){a.show()}}}else{a=null;c.apply_search_results(b)}}})}});var BaseView=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){(this.model.attributes.hidden?this.$el.hide():this.$el.show())}});var ToolLinkView=BaseView.extend({tagName:"div",template:Handlebars.templates.tool_link,render:function(){this.$el.append(this.template(this.model.toJSON()));return this}});var ToolPanelLabelView=BaseView.extend({tagName:"div",className:"toolPanelLabel",render:function(){this.$el.append($("<span/>").text(this.model.attributes.name));return this}});var ToolPanelSectionView=BaseView.extend({tagName:"div",className:"toolSectionWrapper",template:Handlebars.templates.panel_section,initialize:function(){BaseView.prototype.initialize.call(this);this.model.on("change:open",this.update_open,this)},render:function(){this.$el.append(this.template(this.model.toJSON()));var a=this.$el.find(".toolSectionBody");_.each(this.model.attributes.elems,function(b){if(b instanceof Tool){var c=new ToolLinkView({model:b,className:"toolTitle"});c.render();a.append(c.$el)}else{if(b instanceof ToolPanelLabel){var d=new ToolPanelLabelView({model:b});d.render();a.append(d.$el)}else{}}});return this},events:{"click .toolSectionTitle > a":"toggle"},toggle:function(){this.model.set("open",!this.model.attributes.open)},update_open:function(){(this.model.attributes.open?this.$el.children(".toolSectionBody").slideDown("fast"):this.$el.children(".toolSectionBody").slideUp("fast"))}});var ToolSearchView=Backbone.View.extend({tagName:"div",id:"tool-search",className:"bar",template:Handlebars.templates.tool_search,events:{click:"focus_and_select","keyup :input":"query_changed"},render:function(){this.$el.append(this.template(this.model.toJSON()));if(!this.model.is_visible()){this.$el.hide()}return this},focus_and_select:function(){this.$el.find(":input").focus().select()},query_changed:function(){this.model.set("query",this.$el.find(":input").val())}});var ToolPanelView=Backbone.View.extend({tagName:"div",className:"toolMenu",initialize:function(){this.collection.tool_search.on("change:results",this.handle_search_results,this)},render:function(){var a=this;var b=new ToolSearchView({model:this.collection.tool_search});b.render();a.$el.append(b.$el);this.collection.each(function(d){if(d instanceof ToolPanelSection){var c=new ToolPanelSectionView({model:d});c.render();a.$el.append(c.$el)}else{if(d instanceof Tool){var e=new ToolLinkView({model:d,className:"toolTitleNoSection"});e.render();a.$el.append(e.$el)}else{if(d instanceof ToolPanelLabel){var f=new ToolPanelLabelView({model:d});f.render();a.$el.append(f.$el)}}}});a.$el.find("a.tool-link").click(function(f){var d=$(this).attr("class").split(/\s+/)[0],c=a.collection.tools.get(d);a.trigger("tool_link_click",f,c)});return this},handle_search_results:function(){var a=this.collection.tool_search.attributes.results;if(a&&a.length===0){$("#search-no-results").show()}else{$("#search-no-results").hide()}}});var ToolFormView=Backbone.View.extend({className:"toolForm",template:Handlebars.templates.tool_form,render:function(){this.$el.children().remove();this.$el.append(this.template(this.model.toJSON()))}});var IntegratedToolMenuAndView=Backbone.View.extend({className:"toolMenuAndView",initialize:function(){this.tool_panel_view=new ToolPanelView({collection:this.collection});this.tool_form_view=new ToolFormView()},render:function(){this.tool_panel_view.render();this.tool_panel_view.$el.css("float","left");this.$el.append(this.tool_panel_view.$el);this.tool_form_view.$el.hide();this.$el.append(this.tool_form_view.$el);var a=this;this.tool_panel_view.on("tool_link_click",function(c,b){c.preventDefault();a.show_tool(b)})},show_tool:function(b){var a=this;b.fetch().done(function(){a.tool_form_view.model=b;a.tool_form_view.render();a.tool_form_view.$el.show();$("#left").width("650px")})}});
\ No newline at end of file
diff -r f7d0c01430f761a73db0f7dc18bd025ad6768575 -r 9b7cf76169b41729ee6253d9722145347e9f5213 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 create_icon_buttons_menu=function(a){var b=new IconButtonCollection(_.map(a,function(c){return new IconButton(c)}));return new IconButtonMenuView({collection:b})};var GalaxyPaths=Backbone.Model.extend({defaults:{root_path:"",image_path:""}});var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",render:function(){var a=this;this.collection.each(function(b){$("<a/>").attr("href","javascript:void(0)").attr("title",b.attributes.title).addClass("icon-button menu-button").addClass(b.attributes.icon_class).appendTo(a.$el).click(b.attributes.on_click)});return this}});var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});
\ No newline at end of file
+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 GalaxyPaths=Backbone.Model.extend({defaults:{root_path:"",image_path:""}});var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,tipsy_config:{}}});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(c){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",c.attributes.title).addClass("icon-button menu-button").addClass(c.attributes.icon_class).appendTo(a.$el).click(c.attributes.on_click);if(c.attributes.tipsy_config){b.tipsy(c.attributes.tipsy_config)}});return this}});var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});
\ No newline at end of file
diff -r f7d0c01430f761a73db0f7dc18bd025ad6768575 -r 9b7cf76169b41729ee6253d9722145347e9f5213 static/scripts/packed/viz/paramamonster.js
--- a/static/scripts/packed/viz/paramamonster.js
+++ b/static/scripts/packed/viz/paramamonster.js
@@ -1,1 +1,1 @@
-var ToolParameterTree=Backbone.Model.extend({defaults:{tool:null,params:null,num_samples:4},initialize:function(d){var c=this.get("tool"),b=this.get("num_samples"),f=c.get("inputs").map(function(h){return h.get_samples(b)}),a=_.filter(f,function(h){return h.get("samples").length!==0});var g=function(j,h){var m=j[h],l=m.get("param"),k=l.get("name"),i=m.get("samples");if(j.length-1===h){return _.map(i,function(n){return{name:k+"="+n,param:l}})}return _.map(i,function(n){return{name:k+"="+n,param:l,children:g(a,h+1)}})};var e={name:"Parameter Tree for "+c.get("name"),children:g(a,0)};this.set("params",_.map(f,function(h){return h.get("param")}));this.set("tree_data",e)}});var Tile=Backbone.Model.extend({defaults:{track:null,index:null,region:null,resolution:null,data:null,stale:null,html_elt:null},initialize:function(a){}});var Track=Backbone.Model.extend({defaults:{dataset:null}});var FeatureTrack=Track.extend({defaults:{track:null},draw_tile:function(n,r,p,s,d,j,c){var q=this,b=r.canvas,y=d.get("start"),a=d.get("end"),D=25,e=this.left_offset;if(p==="summary_tree"||p==="Histogram"){if(n.dataset_type!=="summary_tree"){var k=this.get_summary_tree_data(n.data,y,a,200);if(n.max){k.max=n.max}n=k}var A=new painters.SummaryTreePainter(n,y,a,this.prefs);A.draw(r,b.width,b.height,j);return new SummaryTreeTile(q,tile_index,s,b,n.data,n.max)}var h=[],o=this.slotters[j].slots;all_slotted=true;if(n.data){var l=this.filters_manager.filters;for(var t=0,v=n.data.length;t<v;t++){var g=n.data[t];var u=false;var m;for(var x=0,C=l.length;x<C;x++){m=l[x];m.update_attrs(g);if(!m.keep(g)){u=true;break}}if(!u){h.push(g);if(!(g[0] in o)){all_slotted=false}}}}var B=(this.filters_manager.alpha_filter?new FilterScaler(this.filters_manager.alpha_filter):null);var z=(this.filters_manager.height_filter?new FilterScaler(this.filters_manager.height_filter):null);var A=new (this.painter)(h,y,a,this.prefs,p,B,z,c);var w=null;r.fillStyle=this.prefs.block_color;r.font=r.canvas.manager.default_font;r.textAlign="right";if(n.data){w=A.draw(r,b.width,b.height,j,o);w.translation=-e}return new FeatureTrackTile(q,tile_index,s,b,n.data,j,p,n.message,all_slotted,w)}});var TileView=Backbone.View.extend({});var ToolParameterTreeView=Backbone.View.extend({className:"tool-parameter-tree",initialize:function(a){this.model=a.model},render:function(){var e=960,b=2000;var a=d3.layout.cluster().size([b,e-160]);var d=d3.svg.diagonal().projection(function(i){return[i.y,i.x]});var h=d3.select(this.$el[0]).append("svg").attr("width",e).attr("height",b).append("g").attr("transform","translate(80, 0)");var c=a.nodes(this.model.get("tree_data"));var g=h.selectAll("path.link").data(a.links(c)).enter().append("path").attr("class","link").attr("d",d);var f=h.selectAll("g.node").data(c).enter().append("g").attr("class","node").attr("transform",function(i){return"translate("+i.y+","+i.x+")"});f.on("click",function(k,j){console.log(k,j)});f.append("circle").attr("r",4.5);f.append("text").attr("dx",function(i){return i.children?-8:8}).attr("dy",3).attr("text-anchor",function(i){return i.children?"end":"start"}).text(function(i){return i.name})}});
\ No newline at end of file
+var ToolParameterTree=Backbone.RelationalModel.extend({defaults:{tool:null,tree_data:null},initialize:function(b){var a=this;this.get("tool").get("inputs").each(function(c){if(!c.get_samples()){return}c.on("change:min change:max change:num_samples",function(d){if(d.get("in_ptree")){a.set_tree_data()}},a);c.on("change:in_ptree",function(d){if(d.get("in_ptree")){a.add_param(d)}else{a.remove_param(d)}a.set_tree_data()},a)});if(b.config){_.each(b.config,function(d){var c=a.get("tool").get("inputs").find(function(e){return e.get("name")===d.name});a.add_param(c);c.set(d)})}},add_param:function(a){if(a.get("ptree_index")){return}a.set("in_ptree",true);a.set("ptree_index",this.get_tree_params().length)},remove_param:function(a){a.set("in_ptree",false);a.set("ptree_index",null);_(this.get_tree_params()).each(function(b,c){b.set("ptree_index",c+1)})},set_tree_data:function(){var b=_.map(this.get_tree_params(),function(d){return{param:d,samples:d.get_samples()}});var a=0,c=function(g,d){var i=g[d],h=i.param,f=h.get("label"),e=i.samples;if(g.length-1===d){return _.map(e,function(j){return{id:a++,name:j,param:h,value:j}})}return _.map(e,function(j){return{id:a++,name:j,param:h,value:j,children:c(g,d+1)}})};this.set("tree_data",{name:"Root",id:a++,children:(b.length!==0?c(b,0):null)})},get_tree_params:function(){return _(this.get("tool").get("inputs").where({in_ptree:true})).sortBy(function(a){return a.get("ptree_index")})},get_num_leaves:function(){return this.get_tree_params().reduce(function(a,b){return a*b.get_samples().length},1)},get_node_settings:function(d){var b=this.get("tool").get_inputs_dict();var e=d.parent;if(e){while(e.depth!==0){b[e.param.get("name")]=e.value;e=e.parent}}var a=function(g,f){if(g.param){f[g.param.get("name")]=g.value}if(!g.children){return f}else{return _.flatten(_.map(g.children,function(h){return a(h,_.clone(f))}))}},c=a(d,b);if(!_.isArray(c)){c=[c]}return c},get_connected_nodes:function(c){var d=function(e){if(!e.children){return e}else{return _.flatten([e,_.map(e.children,function(f){return d(f)})])}};var b=[],a=c.parent;while(a){b.push(a);a=a.parent}return _.flatten([b,d(c)])},get_leaf:function(b){var c=this.get("tree_data"),a=function(d){return _.find(d,function(e){return b[e.param.get("name")]===e.value})};while(c.children){c=a(c.children)}return c},toJSON:function(){return this.get_tree_params().map(function(a){return{name:a.get("name"),min:a.get("min"),max:a.get("max"),num_samples:a.get("num_samples")}})}});var ParamaMonsterTrack=Backbone.RelationalModel.extend({defaults:{track:null,settings:null,regions:null},relations:[{type:Backbone.HasMany,key:"regions",relatedModel:"GenomeRegion"}],initialize:function(a){if(a.track){var b=_.extend({data_url:galaxy_paths.get("raw_data_url"),converted_datasets_state_url:galaxy_paths.get("dataset_state_url")},a.track);delete b.mode;this.set("track",object_from_template(b,{},null))}},same_settings:function(a){var b=this.get("settings"),c=a.get("settings");for(var d in b){if(!c[d]||b[d]!==c[d]){return false}}return true},toJSON:function(){return{track:this.get("track").to_dict(),settings:this.get("settings"),regions:this.get("regions")}}});var TrackCollection=Backbone.Collection.extend({model:ParamaMonsterTrack});var ParamaMonsterVisualization=Visualization.extend({defaults:_.extend({},Visualization.prototype.defaults,{dataset:null,tool:null,parameter_tree:null,regions:null,tracks:null}),relations:[{type:Backbone.HasOne,key:"dataset",relatedModel:"Dataset"},{type:Backbone.HasOne,key:"tool",relatedModel:"Tool"},{type:Backbone.HasMany,key:"regions",relatedModel:"GenomeRegion"},{type:Backbone.HasMany,key:"tracks",relatedModel:"ParamaMonsterTrack"}],initialize:function(a){var b=this.get("tool").copy(true);this.set("tool_with_samplable_inputs",b);this.set("parameter_tree",new ToolParameterTree({tool:b,config:a.tree_config}))},add_placeholder:function(a){this.get("tracks").add(new PlaceholderTrack(a))},add_track:function(a){this.get("tracks").add(a)},toJSON:function(){return{id:this.get("id"),title:"Parameter exploration for dataset '"+this.get("dataset").get("name")+"'",type:"paramamonster",dataset_id:this.get("dataset").id,tool_id:this.get("tool").id,regions:this.get("regions").toJSON(),tree_config:this.get("parameter_tree").toJSON(),tracks:this.get("tracks").toJSON()}}});var ParamaMonsterTrackView=Backbone.View.extend({tagName:"tr",TILE_LEN:250,initialize:function(a){this.canvas_manager=a.canvas_manager;this.render();this.model.on("change:track",this.draw_tiles,this)},render:function(){var e=this.model.get("settings"),c=$("<td/>").addClass("settings").appendTo(this.$el),b=$("<div/>").addClass("track-info").hide().appendTo(c);b.append($("<div/>").css("font-weight","bold").text("Track Settings"));_.each(_.keys(e),function(g){b.append(g+": "+e[g]+"<br/>")});var a=this,f=$("<button/>").appendTo(b).text("Run on complete dataset").click(function(){a.trigger("run_on_dataset",e)});var d=create_icon_buttons_menu([{title:"Settings",icon_class:"gear track-settings",on_click:function(){b.toggle()},tipsy_config:{gravity:"s"}},{title:"Remove",icon_class:"cross-circle",on_click:function(){a.$el.remove();$(".tipsy").remove()}}]);c.prepend(d.$el);this.model.get("regions").each(function(){a.$el.append($("<td/>").addClass("tile").html($("<img/>").attr("src",galaxy_paths.get("image_path")+"/loading_large_white_bg.gif")))});if(this.model.get("track")){this.draw_tiles()}},draw_tiles:function(){var b=this,a=this.model.get("track"),d=this.model.get("regions"),c=this.$el.find("td.tile");$.when(a.data_manager.data_is_ready()).then(function(e){d.each(function(h,g){var f=h.length()/b.TILE_LEN,j=1/f,i="Pack";$.when(a.data_manager.get_data(h,i,f,{})).then(function(l){var k=b.canvas_manager.new_canvas();k.width=b.TILE_LEN;k.height=a.get_canvas_height(l,i,j,k.width);a.draw_tile(l,k.getContext("2d"),i,f,h,j);$(c[g]).empty().append(k)})})})}});var ToolInputValOrSweepView=Backbone.View.extend({number_input_template:'<div class="form-row-input sweep"><input class="min" type="text" size="6" value="<%= min %>"> - <input class="max" type="text" size="6" value="<%= max %>"> samples: <input class="num_samples" type="text" size="1" value="<%= num_samples %>"></div>',select_input_template:'<div class="form-row-input sweep"><%= options %></div>',initialize:function(a){this.$el=a.tool_row;this.render()},render:function(){var b=this.model,f=b.get("type"),h=this.$el.find(".form-row-input"),d=null;h.find("input").change(function(){b.set("value",$(this).val())});if(f==="number"){d=$(_.template(this.number_input_template,this.model.toJSON()))}else{if(f==="select"){var c=_.map(this.$el.find("select option"),function(i){return $(i).val()}),e=c.join(", ");d=$(_.template(this.select_input_template,{options:e}))}}d.insertAfter(h);if(b.get("in_ptree")){h.hide()}else{d.hide()}var a=this,g=create_icon_buttons_menu([{title:"Add parameter to tree",icon_class:"plus-button",on_click:function(){b.set("in_ptree",true);h.hide();d.show()}},{title:"Remove parameter from tree",icon_class:"toggle",on_click:function(){b.set("in_ptree",false);d.hide();h.show()}}],{tipsy_config:{gravity:"s"}});this.$el.prepend(g.$el);_.each(["min","max","num_samples"],function(i){d.find("."+i).change(function(){b.set(i,parseFloat($(this).val()))})})}});var ToolParameterTreeDesignView=Backbone.View.extend({className:"tree-design",initialize:function(a){this.render()},render:function(){var c=new ToolFormView({model:this.model.get("tool")});c.render();this.$el.append(c.$el);var b=this,a=b.model.get("tool").get("inputs");this.$el.find(".form-row").not(".form-actions").each(function(d){var e=new ToolInputValOrSweepView({model:a.at(d),tool_row:$(this)})})}});var ToolParameterTreeView=Backbone.View.extend({className:"tool-parameter-tree",initialize:function(a){this.model.on("change:tree_data",this.render,this)},render:function(){this.$el.children().remove();var i=this.model.get_tree_params();if(!i.length){return}this.width=100*(2+i.length);this.height=15*this.model.get_num_leaves();var h=this;var g=d3.layout.cluster().size([this.height,this.width-160]);var c=d3.svg.diagonal().projection(function(j){return[j.y,j.x]});var a=g.nodes(this.model.get("tree_data"));var d=_.uniq(_.pluck(a,"y"));_.each(i,function(l,k){var j=d[k+1];h.$el.append($("<div>").addClass("label").text(l.get("label")).css("left",j+250))});var b=d3.select(this.$el[0]).append("svg").attr("width",this.width).attr("height",this.height+20).append("g").attr("transform","translate(40, 10)");var f=b.selectAll("path.link").data(g.links(a)).enter().append("path").attr("class","link").attr("d",c);var e=b.selectAll("g.node").data(a).enter().append("g").attr("class","node").attr("transform",function(j){return"translate("+j.y+","+j.x+")"}).on("mouseover",function(k){var j=_.pluck(h.model.get_connected_nodes(k),"id");e.filter(function(l){return _.find(j,function(m){return m===l.id})!==undefined}).style("fill","#f00")}).on("mouseout",function(){e.style("fill","#000")});e.append("circle").attr("r",9);e.append("text").attr("dx",function(j){return j.children?-12:12}).attr("dy",3).attr("text-anchor",function(j){return j.children?"end":"start"}).text(function(j){return j.name})}});var ParamaMonsterVisualizationView=Backbone.View.extend({className:"paramamonster",initialize:function(b){this.canvas_manager=new CanvasManager(this.$el.parents("body"));this.tool_param_tree_view=new ToolParameterTreeView({model:this.model.get("parameter_tree")});this.track_collection_container=$("<table/>").addClass("tracks");this.model.get("parameter_tree").on("change:tree_data",this.handle_node_clicks,this);var a=this;this.model.get("tracks").each(function(c){c.get("track").view=a})},render:function(){var d=new ToolParameterTreeDesignView({model:this.model.get("parameter_tree")});$("#left").append(d.$el);var a=this,e=a.model.get("regions"),b=$("<tr/>").appendTo(this.track_collection_container);e.each(function(f){b.append($("<th>").text(f.toString()))});b.children().first().attr("colspan",2);var c=$("<div>").addClass("tiles");$("#right").append(c.append(this.track_collection_container));a.model.get("tracks").each(function(f){a.add_track(f)});this.tool_param_tree_view.render();$("#center").append(this.tool_param_tree_view.$el);this.handle_node_clicks()},run_tool_on_dataset:function(b){var a=this.model.get("tool"),c=this.model.get("dataset");a.set_input_values(b);$.when(a.rerun(c)).then(function(d){})},add_track:function(d){var b=this,c=this.model.get("parameter_tree");b.model.add_track(d);var a=new ParamaMonsterTrackView({model:d,canvas_manager:b.canvas_manager});a.on("run_on_dataset",b.run_tool_on_dataset,b);b.track_collection_container.append(a.$el);a.$el.hover(function(){var f=c.get_leaf(d.get("settings"));var e=_.pluck(c.get_connected_nodes(f),"id");d3.select(b.tool_param_tree_view.$el[0]).selectAll("g.node").filter(function(g){return _.find(e,function(h){return h===g.id})!==undefined}).style("fill","#f00")},function(){d3.select(b.tool_param_tree_view.$el[0]).selectAll("g.node").style("fill","#000")});return d},handle_node_clicks:function(){var a=this,b=this.model.get("parameter_tree"),d=this.model.get("regions"),c=d3.select(this.tool_param_tree_view.$el[0]).selectAll("g.node");c.on("click",function(k,g){var f=a.model.get("tool"),j=a.model.get("dataset"),h=b.get_node_settings(k),e=$.Deferred();if(h.length>=10){show_modal("Whoa there cowboy!","You clicked on a node to try "+a.model.get("tool").get("name")+" with "+h.length+" different combinations of settings. You can only run 10 jobs at a time.",{Ok:function(){hide_modal();e.resolve(false)}})}else{e.resolve(true)}$.when(e).then(function(i){if(!i){return}var l=_.map(h,function(m){var n=new ParamaMonsterTrack({settings:m,regions:d});a.add_track(n);return n});_.each(l,function(n,m){setTimeout(function(){f.set_input_values(n.get("settings"));$.when(f.rerun(j,d)).then(function(p){var q=_.extend({data_url:galaxy_paths.get("raw_data_url"),converted_datasets_state_url:galaxy_paths.get("dataset_state_url")},p.first().get("track_config")),o=object_from_template(q,a,null);n.set("track",o)})},m*10000)})})})}});
\ No newline at end of file
diff -r f7d0c01430f761a73db0f7dc18bd025ad6768575 -r 9b7cf76169b41729ee6253d9722145347e9f5213 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 class_module=function(b,a){var c=function(){var f=arguments[0];for(var e=1;e<arguments.length;e++){var d=arguments[e];for(key in d){f[key]=d[key]}}return f};a.extend=c};var server_state_deferred=function(d,a,c,f){var b=$.Deferred(),e=function(){$.getJSON(d,a,function(g){if(f(g)){b.resolve(g)}else{setTimeout(e,c)}})};e();return b};var requestAnimationFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b,a){window.setTimeout(b,1000/60)}})();var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=BEFORE}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var is_deferred=function(a){return("isResolved" in a)};var get_random_color=function(a){if(!a){a="#ffffff"}if(typeof(a)==="string"){a=[a]}for(var j=0;j<a.length;j++){a[j]=parseInt(a[j].slice(1),16)}var n=function(t,s,i){return((t*299)+(s*587)+(i*114))/1000};var e=function(v,u,w,s,i,t){return(Math.max(v,s)-Math.min(v,s))+(Math.max(u,i)-Math.min(u,i))+(Math.max(w,t)-Math.min(w,t))};var g,o,f,k,q,h,r,c,d,b,p,m=false,l=0;do{g=Math.round(Math.random()*16777215);o=(g&16711680)>>16;f=(g&65280)>>8;k=g&255;d=n(o,f,k);m=true;for(var j=0;j<a.length;j++){q=a[j];h=(q&16711680)>>16;r=(q&65280)>>8;c=q&255;b=n(h,r,c);p=e(o,f,k,h,r,c);if((Math.abs(d-b)<40)||(p<200)){m=false;break}}l++}while(!m&&l<=10);return"#"+(16777216+g).toString(16).substr(1,6)};var create_action_icon=function(c,b,a){return $("<a/>").attr("href","javascript:void(0);").attr("title",c).addClass("icon-button").addClass(b).tipsy({gravity:"s"}).click(a)};var trackster_module=function(d,R){var o=d("class").extend,r=d("slotting"),H=d("painters");var Y=function(Z,aa){this.document=Z;this.default_font=aa!==undefined?aa:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};o(Y.prototype,{load_pattern:function(Z,ad){var aa=this.patterns,ab=this.dummy_context,ac=new Image();ac.src=galaxy_paths.attributes.image_path+ad;ac.onload=function(){aa[Z]=ab.createPattern(ac,"repeat")}},get_pattern:function(Z){return this.patterns[Z]},new_canvas:function(){var Z=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(Z)}Z.manager=this;return Z}});var m={};var k=function(Z,aa){m[Z.attr("id")]=aa};var l=function(Z,ab,ad,ac){ad=".group";var aa={};m[Z.attr("id")]=ac;Z.bind("drag",{handle:"."+ab,relative:true},function(al,am){var ak=$(this);var ap=$(this).parent(),ah=ap.children(),aj=m[$(this).attr("id")],ag,af,an,ae,ai;af=$(this).parents(ad);if(af.length!==0){an=af.position().top;ae=an+af.outerHeight();if(am.offsetY<an){$(this).insertBefore(af);var ao=m[af.attr("id")];ao.remove_drawable(aj);ao.container.add_drawable_before(aj,ao);return}else{if(am.offsetY>ae){$(this).insertAfter(af);var ao=m[af.attr("id")];ao.remove_drawable(aj);ao.container.add_drawable(aj);return}}}af=null;for(ai=0;ai<ah.length;ai++){ag=$(ah.get(ai));an=ag.position().top;ae=an+ag.outerHeight();if(ag.is(ad)&&this!==ag.get(0)&&am.offsetY>=an&&am.offsetY<=ae){if(am.offsetY-an<ae-am.offsetY){ag.find(".content-div").prepend(this)}else{ag.find(".content-div").append(this)}if(aj.container){aj.container.remove_drawable(aj)}m[ag.attr("id")].add_drawable(aj);return}}var ag;for(ai=0;ai<ah.length;ai++){ag=$(ah.get(ai));if(am.offsetY<ag.position().top&&!(ag.hasClass("reference-track")||ag.hasClass("intro"))){break}}if(ai===ah.length){if(this!==ah.get(ai-1)){ap.append(this);m[ap.attr("id")].move_drawable(aj,ai)}}else{if(this!==ah.get(ai)){$(this).insertBefore(ah.get(ai));m[ap.attr("id")].move_drawable(aj,(am.deltaY>0?ai-1:ai))}}}).bind("dragstart",function(){aa["border-top"]=Z.css("border-top");aa["border-bottom"]=Z.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(aa)})};R.moveable=l;var X=16,C=9,z=20,w=100,E=12000,O=400,G=5000,t=100,n="There was an error in indexing this dataset. ",F="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",A="No data for this chrom/contig.",s="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",u="Tool cannot be rerun: ",a="Loading data...",S="Ready for display",M=10,D=20;function T(aa,Z){if(!Z){Z=0}var ab=Math.pow(10,Z);return Math.round(aa*ab)/ab}var p=function(aa,Z,ac){if(!p.id_counter){p.id_counter=0}this.id=p.id_counter++;this.name=ac.name;this.view=aa;this.container=Z;this.config=new B({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:ac.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=ac.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(ad){ad.stopPropagation()});var ab=this;this.container_div.hover(function(){ab.icons_div.show()},function(){ab.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};p.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(Z){if(Z.content_visible){Z.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");Z.hide_contents();Z.content_visible=false}else{Z.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");Z.content_visible=true;Z.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(aa){var ac=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},Z=function(){aa.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ab=function(ad){if((ad.keyCode||ad.which)===27){ac()}else{if((ad.keyCode||ad.which)===13){Z()}}};$(window).bind("keypress.check_enter_esc",ab);show_modal("Configure",aa.config.build_form(),{Cancel:ac,OK:Z})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(Z){$(".tipsy").remove();Z.remove()}}];o(p.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(){},to_dict:function(){},update_icons:function(){},set_name:function(Z){this.old_name=this.name;this.name=Z;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 Z=this.view;this.container_div.hide(0,function(){$(this).remove();Z.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(aa,af,ae,ad,Z,ac){var ab=this;this.action_icons[aa]=$("<a/>").attr("href","javascript:void(0);").attr("title",af).addClass("icon-button").addClass(ae).tipsy({gravity:"s"}).click(function(){ad(ab)}).appendTo(this.icons_div);if(ac){this.action_icons[aa].hide()}},build_action_icons:function(Z){var ab;for(var aa=0;aa<Z.length;aa++){ab=Z[aa];this.add_action_icon(ab.name,ab.title,ab.css_class,ab.on_click_fn,ab.prepend,ab.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){}});var v=function(aa,Z,ab){p.call(this,aa,Z,ab);this.obj_type=ab.obj_type;this.drawables=[]};o(v.prototype,p.prototype,{unpack_drawables:function(ab){this.drawables=[];var aa;for(var Z=0;Z<ab.length;Z++){aa=object_from_template(ab[Z],this);this.add_drawable(aa)}},init:function(){for(var Z=0;Z<this.drawables.length;Z++){this.drawables[Z].init()}},_draw:function(){for(var Z=0;Z<this.drawables.length;Z++){this.drawables[Z]._draw()}},to_dict:function(){var aa=[];for(var Z=0;Z<this.drawables.length;Z++){aa.push(this.drawables[Z].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:aa}},add_drawable:function(Z){this.drawables.push(Z);Z.container=this;this.changed()},add_drawable_before:function(ab,Z){this.changed();var aa=this.drawables.indexOf(Z);if(aa!==-1){this.drawables.splice(aa,0,ab);return true}return false},replace_drawable:function(ab,Z,aa){var ac=this.drawables.indexOf(ab);if(ac!==-1){this.drawables[ac]=Z;if(aa){ab.container_div.replaceWith(Z.container_div)}this.changed()}return ac},remove_drawable:function(aa){var Z=this.drawables.indexOf(aa);if(Z!==-1){this.drawables.splice(Z,1);aa.container=null;this.changed();return true}return false},move_drawable:function(aa,ab){var Z=this.drawables.indexOf(aa);if(Z!==-1){this.drawables.splice(Z,1);this.drawables.splice(ab,0,aa);this.changed();return true}return false}});var L=function(aa,Z,ac){o(ac,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});v.call(this,aa,Z,ac);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);k(this.container_div,this);k(this.content_div,this);l(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new U(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in ac){this.unpack_drawables(ac.drawables)}if("filters" in ac){var ab=this.filters_manager;this.filters_manager=new U(this,ac.filters);ab.parent_div.replaceWith(this.filters_manager.parent_div);if(ac.filters.visible){this.setup_multitrack_filtering()}}};o(L.prototype,p.prototype,v.prototype,{action_icons_def:[p.prototype.action_icons_def[0],p.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(Z){$(".tipsy").remove();Z.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(Z){if(Z.filters_manager.visible()){Z.filters_manager.clear_filters();Z._restore_filter_managers()}else{Z.setup_multitrack_filtering();Z.request_draw(true)}Z.filters_manager.toggle()}},p.prototype.action_icons_def[2]],build_container_div:function(){var Z=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(Z)}return Z},build_header_div:function(){var Z=$("<div/>").addClass("track-header");Z.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(Z);return Z},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var ab=this.drawables.length;if(ab===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(ab===1){if(this.drawables[0] instanceof g){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var af,al=true,ad=this.drawables[0].get_type(),Z=0;for(var ai=0;ai<ab;ai++){af=this.drawables[ai];if(af.get_type()!==ad){can_composite=false;break}if(af instanceof c){Z++}}if(al||Z===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".tipsy").remove()}if(Z>1&&Z===this.drawables.length){var am={},aa;af=this.drawables[0];for(var ah=0;ah<af.filters_manager.filters.length;ah++){aa=af.filters_manager.filters[ah];am[aa.name]=[aa]}for(var ai=1;ai<this.drawables.length;ai++){af=this.drawables[ai];for(var ah=0;ah<af.filters_manager.filters.length;ah++){aa=af.filters_manager.filters[ah];if(aa.name in am){am[aa.name].push(aa)}}}this.filters_manager.remove_all();var ac,ae,ag,aj;for(var ak in am){ac=am[ak];if(ac.length===Z){ae=new P({name:ac[0].name,index:ac[0].index});this.filters_manager.add_filter(ae)}}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 Z=0;Z<this.drawables.length;Z++){this.drawables[Z].filters_manager=this.saved_filters_managers[Z]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var Z=0;Z<this.drawables.length;Z++){drawable=this.drawables[Z];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=[];for(var aa=0;aa<this.drawables.length;aa++){ad.push(this.drawables[aa].name)}var ab="Composite Track of "+this.drawables.length+" tracks ("+ad.join(", ")+")";var ac=new g(this.view,this.view,{name:ab,drawables:this.drawables});var Z=this.container.replace_drawable(this,ac,true);ac.request_draw()},add_drawable:function(Z){v.prototype.add_drawable.call(this,Z);this.update_icons()},remove_drawable:function(Z){v.prototype.remove_drawable.call(this,Z);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var Z=o(v.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return Z},request_draw:function(Z,ab){for(var aa=0;aa<this.drawables.length;aa++){this.drawables[aa].request_draw(Z,ab)}}});var W=function(Z){o(Z,{obj_type:"View"});v.call(this,"View",Z.container,Z);this.chrom=null;this.vis_id=Z.vis_id;this.dbkey=Z.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.init();this.canvas_manager=new Y(this.container.get(0).ownerDocument);this.reset()};_.extend(W.prototype,Backbone.Events);o(W.prototype,v.prototype,{init:function(){this.requested_redraw=false;var ab=this.container,Z=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ab);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ab);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ab);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;k(this.viewport_container,Z);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var ac=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_datasets(add_datasets_url,add_track_async_url,function(ad){_.each(ad,function(ae){Z.add_drawable(object_from_template(ae,Z))})})});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").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var aa=function(ad){if(ad.type==="focusout"||(ad.keyCode||ad.which)===13||(ad.keyCode||ad.which)===27){if((ad.keyCode||ad.which)!==27){Z.go_to($(this).val())}$(this).hide();$(this).val("");Z.location_span.show();Z.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",aa).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").attr("original-title","Click to change location").tipsy({gravity:"n"}).appendTo(this.nav_controls);this.location_span.click(function(){Z.location_span.hide();Z.chrom_select.hide();Z.nav_input.val(Z.chrom+":"+Z.low+"-"+Z.high);Z.nav_input.css("display","inline-block");Z.nav_input.select();Z.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a/>").attr("id","zoom-out").attr("title","Zoom out").tipsy({gravity:"n"}).click(function(){Z.zoom_out();Z.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tipsy({gravity:"n"}).click(function(){Z.zoom_in();Z.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){Z.change_chrom(Z.chrom_select.val())});this.browser_content_div.click(function(ad){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ad){Z.zoom_in(ad.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ad,ae){this.current_x=ae.offsetX}).bind("drag",function(ad,af){var ag=af.offsetX-this.current_x;this.current_x=af.offsetX;var ae=Math.round(ag/Z.viewport_container.width()*(Z.max_high-Z.max_low));Z.move_delta(-ae)});this.overview_close.click(function(){Z.reset_overview()});this.viewport_container.bind("draginit",function(ad,ae){if(ad.clientX>Z.viewport_container.width()-16){return false}}).bind("dragstart",function(ad,ae){ae.original_low=Z.low;ae.current_height=ad.clientY;ae.current_x=ae.offsetX}).bind("drag",function(af,ah){var ad=$(this);var ai=ah.offsetX-ah.current_x;var ae=ad.scrollTop()-(af.clientY-ah.current_height);ad.scrollTop(ae);ah.current_height=af.clientY;ah.current_x=ah.offsetX;var ag=Math.round(ai/Z.viewport_container.width()*(Z.high-Z.low));Z.move_delta(ag)}).bind("mousewheel",function(af,ah,ae,ad){if(ae){ae*=50;var ag=Math.round(-ae/Z.viewport_container.width()*(Z.high-Z.low));Z.move_delta(ag)}});this.top_labeltrack.bind("dragstart",function(ad,ae){return $("<div />").css({height:Z.browser_content_div.height()+Z.top_labeltrack.height()+Z.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ah,ai){$(ai.proxy).css({left:Math.min(ah.pageX,ai.startX)-Z.container.offset().left,width:Math.abs(ah.pageX-ai.startX)});var ae=Math.min(ah.pageX,ai.startX)-Z.container.offset().left,ad=Math.max(ah.pageX,ai.startX)-Z.container.offset().left,ag=(Z.high-Z.low),af=Z.viewport_container.width();Z.update_location(Math.round(ae/af*ag)+Z.low,Math.round(ad/af*ag)+Z.low)}).bind("dragend",function(ai,aj){var ae=Math.min(ai.pageX,aj.startX),ad=Math.max(ai.pageX,aj.startX),ag=(Z.high-Z.low),af=Z.viewport_container.width(),ah=Z.low;Z.low=Math.round(ae/af*ag)+ah;Z.high=Math.round(ad/af*ag)+ah;$(aj.proxy).remove();Z.request_redraw()});this.add_label_track(new V(this,{content_div:this.top_labeltrack}));this.add_label_track(new V(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){Z.resize_window()},500)});$(document).bind("redraw",function(){Z.redraw()});this.reset();$(window).trigger("resize")},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(aa,ac,Z,ad){if(this.timer){clearTimeout(this.timer)}if(ad){var ab=this;this.timer=setTimeout(function(){ab.trigger("navigate",aa+":"+ac+"-"+Z)},500)}else{view.trigger("navigate",aa+":"+ac+"-"+Z)}},update_location:function(Z,ab){this.location_span.text(commatize(Z)+" - "+commatize(ab));this.nav_input.val(this.chrom+":"+commatize(Z)+"-"+commatize(ab));var aa=view.chrom_select.val();if(aa!==""){this.trigger_navigate(aa,view.low,view.high,true)}},load_chroms:function(ab){ab.num=t;ab.dbkey=this.dbkey;var Z=this,aa=$.Deferred();$.ajax({url:chrom_url,data:ab,dataType:"json",success:function(ad){if(ad.chrom_info.length===0){alert("Invalid chromosome: "+ab.chrom);return}if(ad.reference){Z.add_label_track(new x(Z))}Z.chrom_data=ad.chrom_info;var ag='<option value="">Select Chrom/Contig</option>';for(var af=0,ac=Z.chrom_data.length;af<ac;af++){var ae=Z.chrom_data[af].chrom;ag+='<option value="'+ae+'">'+ae+"</option>"}if(ad.prev_chroms){ag+='<option value="previous">Previous '+t+"</option>"}if(ad.next_chroms){ag+='<option value="next">Next '+t+"</option>"}Z.chrom_select.html(ag);Z.chrom_start_index=ad.start_index;aa.resolve(ad)},error:function(){alert("Could not load chroms for this dbkey:",Z.dbkey)}});return aa},change_chrom:function(ae,aa,ag){var ab=this;if(!ab.chrom_data){ab.load_chroms_deferred.then(function(){ab.change_chrom(ae,aa,ag)});return}if(!ae||ae==="None"){return}var ab=this;if(ae==="previous"){ab.load_chroms({low:this.chrom_start_index-t});return}if(ae==="next"){ab.load_chroms({low:this.chrom_start_index+t});return}var af=$.grep(ab.chrom_data,function(ah,ai){return ah.chrom===ae})[0];if(af===undefined){ab.load_chroms({chrom:ae},function(){ab.change_chrom(ae,aa,ag)});return}else{if(ae!==ab.chrom){ab.chrom=ae;ab.chrom_select.val(ab.chrom);ab.max_high=af.len-1;ab.reset();ab.request_redraw(true);for(var ad=0,Z=ab.drawables.length;ad<Z;ad++){var ac=ab.drawables[ad];if(ac.init){ac.init()}}if(ab.reference_track){ab.reference_track.init()}}if(aa!==undefined&&ag!==undefined){ab.low=Math.max(aa,0);ab.high=Math.min(ag,ab.max_high)}else{ab.low=0;ab.high=ab.max_high}ab.reset_overview();ab.request_redraw()}},go_to:function(ad){ad=ad.replace(/ |,/g,"");var ah=this,Z,ac,aa=ad.split(":"),af=aa[0],ag=aa[1];if(ag!==undefined){try{var ae=ag.split("-");Z=parseInt(ae[0],10);ac=parseInt(ae[1],10)}catch(ab){return false}}ah.change_chrom(af,Z,ac)},move_fraction:function(ab){var Z=this;var aa=Z.high-Z.low;this.move_delta(ab*aa)},move_delta:function(ac){var Z=this;var ab=Z.high-Z.low;if(Z.low-ac<Z.max_low){Z.low=Z.max_low;Z.high=Z.max_low+ab}else{if(Z.high-ac>Z.max_high){Z.high=Z.max_high;Z.low=Z.max_high-ab}else{Z.high-=ac;Z.low-=ac}}Z.request_redraw();var aa=Z.chrom_select.val();this.trigger_navigate(aa,Z.low,Z.high,true)},add_drawable:function(Z){v.prototype.add_drawable.call(this,Z);Z.init();this.changed();this.update_intro_div()},add_label_track:function(Z){Z.view=this;Z.init();this.label_tracks.push(Z)},remove_drawable:function(ab,aa){v.prototype.remove_drawable.call(this,ab);if(aa){var Z=this;ab.container_div.hide(0,function(){$(this).remove();Z.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ah,Z,ag,aa){var af=this,ad=(aa?[aa]:af.drawables),ab;var aa;for(var ae=0;ae<ad.length;ae++){aa=ad[ae];ab=-1;for(var ac=0;ac<af.tracks_to_be_redrawn.length;ac++){if(af.tracks_to_be_redrawn[ac][0]===aa){ab=ac;break}}if(ab<0){af.tracks_to_be_redrawn.push([aa,Z,ag])}else{af.tracks_to_be_redrawn[ae][1]=Z;af.tracks_to_be_redrawn[ae][2]=ag}}if(!this.requested_redraw){requestAnimationFrame(function(){af._redraw(ah)});this.requested_redraw=true}},_redraw:function(aj){this.requested_redraw=false;var ag=this.low,ac=this.high;if(ag<this.max_low){ag=this.max_low}if(ac>this.max_high){ac=this.max_high}var ai=this.high-this.low;if(this.high!==0&&ai<this.min_separation){ac=ag+this.min_separation}this.low=Math.floor(ag);this.high=Math.ceil(ac);this.update_location(this.low,this.high);this.resolution_b_px=(this.high-this.low)/this.viewport_container.width();this.resolution_px_b=this.viewport_container.width()/(this.high-this.low);var Z=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var af=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ak=13;this.overview_box.css({left:Z,width:Math.max(ak,af)}).show();if(af<ak){this.overview_box.css("left",Z-(ak-af)/2)}if(this.overview_highlight){this.overview_highlight.css({left:Z,width:af})}if(!aj){var ab,aa,ah;for(var ad=0,ae=this.tracks_to_be_redrawn.length;ad<ae;ad++){ab=this.tracks_to_be_redrawn[ad][0];aa=this.tracks_to_be_redrawn[ad][1];ah=this.tracks_to_be_redrawn[ad][2];if(ab){ab._draw(aa,ah)}}this.tracks_to_be_redrawn=[];for(ad=0,ae=this.label_tracks.length;ad<ae;ad++){this.label_tracks[ad]._draw()}}},zoom_in:function(aa,ab){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var ac=this.high-this.low,ad=ac/2+this.low,Z=(ac/this.zoom_factor)/2;if(aa){ad=aa/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ad-Z);this.high=Math.round(ad+Z);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var aa=this.high-this.low,ab=aa/2+this.low,Z=(aa*this.zoom_factor)/2;this.low=Math.round(ab-Z);this.high=Math.round(ab+Z);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(ab){if(this.overview_drawable){if(this.overview_drawable.dataset_id===ab.dataset_id){return}this.overview_viewport.find(".track").remove()}var aa=ab.copy({content_div:this.overview_viewport}),Z=this;aa.header_div.hide();aa.is_overview=true;Z.overview_drawable=aa;this.overview_drawable.postdraw_actions=function(){Z.overview_highlight.show().height(Z.overview_drawable.content_div.height());Z.overview_viewport.height(Z.overview_drawable.content_div.height()+Z.overview_box.outerHeight());Z.overview_close.show();Z.resize_window()};Z.overview_drawable.request_draw();this.changed()},reset_overview:function(){$(".tipsy").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 q=function(ab,ag,ac){this.track=ab;this.name=ag.name;this.params=[];var an=ag.params;for(var ad=0;ad<an.length;ad++){var ai=an[ad],aa=ai.name,am=ai.label,ae=unescape(ai.html),ao=ai.value,ak=ai.type;if(ak==="number"){this.params.push(new e(aa,am,ae,(aa in ac?ac[aa]:ao),ai.min,ai.max))}else{if(ak==="select"){this.params.push(new J(aa,am,ae,(aa in ac?ac[aa]:ao)))}else{console.log("WARNING: unrecognized tool parameter type:",aa,ak)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(aq){aq.stopPropagation()}).click(function(aq){aq.stopPropagation()}).bind("dblclick",function(aq){aq.stopPropagation()});var al=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var aj=this.params;var ah=this;$.each(this.params,function(ar,av){var au=$("<div>").addClass("param-row").appendTo(ah.parent_div);var aq=$("<div>").addClass("param-label").text(av.label).appendTo(au);var at=$("<div/>").addClass("param-input").html(av.html).appendTo(au);at.find(":input").val(av.value);$("<div style='clear: both;'/>").appendTo(au)});this.parent_div.find("input").click(function(){$(this).select()});var ap=$("<div>").addClass("param-row").appendTo(this.parent_div);var af=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(ap);var Z=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(ap);var ah=this;Z.click(function(){ah.run_on_region()});af.click(function(){ah.run_on_dataset()});if("visible" in ac&&ac.visible){this.parent_div.show()}};o(q.prototype,{update_params:function(){for(var Z=0;Z<this.params.length;Z++){this.params[Z].update_value()}},state_dict:function(){var aa={};for(var Z=0;Z<this.params.length;Z++){aa[this.params[Z].name]=this.params[Z].value}aa.visible=this.parent_div.is(":visible");return aa},get_param_values_dict:function(){var Z={};this.parent_div.find(":input").each(function(){var aa=$(this).attr("name"),ab=$(this).val();Z[aa]=JSON.stringify(ab)});return Z},get_param_values:function(){var aa=[];var Z={};this.parent_div.find(":input").each(function(){var ab=$(this).attr("name"),ac=$(this).val();if(ab){aa[aa.length]=ac}});return aa},run_on_dataset:function(){var Z=this;Z.run({dataset_id:this.track.original_dataset_id,tool_id:Z.name},null,function(aa){show_modal(Z.name+" is Running",Z.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var aa={dataset_id:this.track.original_dataset_id,chrom:this.track.view.chrom,low:this.track.view.low,high:this.track.view.high,tool_id:this.name},ae=this.track,ab=aa.tool_id+ae.tool_region_and_parameters_str(aa.chrom,aa.low,aa.high),Z;if(ae.container===view){var ad=new L(view,view,{name:this.name});var ac=ae.container.replace_drawable(ae,ad,false);ad.container_div.insertBefore(ae.view.content_div.children()[ac]);ad.add_drawable(ae);ae.container_div.appendTo(ad.content_div);Z=ad}else{Z=ae.container}var af=new ae.constructor(view,Z,{name:ab,hda_ldda:"hda"});af.init_for_tool_data();af.change_mode(ae.mode);af.set_filters_manager(ae.filters_manager.copy(af));af.update_icons();Z.add_drawable(af);af.tiles_div.text("Starting job.");this.update_params();this.run(aa,af,function(ag){af.dataset_id=ag.dataset_id;af.tiles_div.text("Running job.");af.init()})},run:function(aa,ab,ac){$.extend(aa,this.get_param_values_dict());var Z=function(){$.getJSON(rerun_tool_url,aa,function(ad){if(ad==="no converter"){ab.container_div.addClass("error");ab.content_div.text(F)}else{if(ad.error){ab.container_div.addClass("error");ab.content_div.text(u+ad.message)}else{if(ad==="pending"){ab.container_div.addClass("pending");ab.content_div.text("Converting input data so that it can be used quickly with tool.");setTimeout(Z,2000)}else{ac(ad)}}}})};Z()}});var J=function(aa,Z,ab,ac){this.name=aa;this.label=Z;this.html=$(ab);this.value=ac};o(J.prototype,{update_value:function(){this.value=$(this.html).val()}});var e=function(ab,aa,ad,ae,ac,Z){J.call(this,ab,aa,ad,ae);this.min=ac;this.max=Z};o(e.prototype,J.prototype,{update_value:function(){J.prototype.update_value.call(this);this.value=parseFloat(this.value)}});var f=function(Z){this.manager=null;this.name=Z.name;this.index=Z.index;this.tool_id=Z.tool_id;this.tool_exp_name=Z.tool_exp_name};o(f.prototype,{to_dict:function(){return{name:this.name,index:this.index,tool_id:this.tool_id,tool_exp_name:this.tool_exp_name}}});var P=function(ai){f.call(this,ai);this.low=("low" in ai?ai.low:-Number.MAX_VALUE);this.high=("high" in ai?ai.high:Number.MAX_VALUE);this.min=("min" in ai?ai.min:Number.MAX_VALUE);this.max=("max" in ai?ai.max:-Number.MAX_VALUE);this.container=null;this.slider=null;this.slider_label=null;var ae=function(aj,ak,al){aj.click(function(){var aq=ak.text(),ao=parseFloat(al.slider("option","max")),an=(ao<=1?4:ao<=1000000?ao.toString().length:6),ap=false,am=$(this).parents(".slider-row");am.addClass("input");if(al.slider("option","values")){an=2*an+1;ap=true}ak.text("");$("<input type='text'/>").attr("size",an).attr("maxlength",an).attr("value",aq).appendTo(ak).focus().select().click(function(ar){ar.stopPropagation()}).blur(function(){$(this).remove();ak.text(aq);am.removeClass("input")}).keyup(function(aw){if(aw.keyCode===27){$(this).trigger("blur")}else{if(aw.keyCode===13){var au=al.slider("option","min"),ar=al.slider("option","max"),av=function(ax){return(isNaN(ax)||ax>ar||ax<au)},at=$(this).val();if(!ap){at=parseFloat(at);if(av(at)){alert("Parameter value must be in the range ["+au+"-"+ar+"]");return $(this)}}else{at=at.split("-");at=[parseFloat(at[0]),parseFloat(at[1])];if(av(at[0])||av(at[1])){alert("Parameter value must be in the range ["+au+"-"+ar+"]");return $(this)}}al.slider((ap?"values":"value"),at);am.removeClass("input")}}})})};var aa=this;aa.parent_div=$("<div/>").addClass("filter-row slider-row");var Z=$("<div/>").addClass("elt-label").appendTo(aa.parent_div),ag=$("<span/>").addClass("slider-name").text(aa.name+" ").appendTo(Z),ab=$("<span/>").text(this.low+"-"+this.high),ac=$("<span/>").addClass("slider-value").appendTo(Z).append("[").append(ab).append("]");aa.values_span=ab;var af=$("<div/>").addClass("slider").appendTo(aa.parent_div);aa.control_element=$("<div/>").attr("id",aa.name+"-filter-control").appendTo(af);var ad=[0,0];aa.control_element.slider({range:true,min:this.min,max:this.max,step:this.get_slider_step(this.min,this.max),values:[this.low,this.high],slide:function(aj,ak){aa.slide(aj,ak)},change:function(aj,ak){aa.control_element.slider("option","slide").call(aa.control_element,aj,ak)}});aa.slider=aa.control_element;aa.slider_label=ab;ae(ac,ab,aa.control_element);var ah=$("<div/>").addClass("display-controls").appendTo(aa.parent_div);this.transparency_icon=create_action_icon("Use filter for data transparency","layer-transparent",function(){if(aa.manager.alpha_filter!==aa){aa.manager.alpha_filter=aa;aa.manager.parent_div.find(".layer-transparent").removeClass("active").hide();aa.transparency_icon.addClass("active").show()}else{aa.manager.alpha_filter=null;aa.transparency_icon.removeClass("active")}aa.manager.track.request_draw(true,true)}).appendTo(ah).hide();this.height_icon=create_action_icon("Use filter for data height","arrow-resize-090",function(){if(aa.manager.height_filter!==aa){aa.manager.height_filter=aa;aa.manager.parent_div.find(".arrow-resize-090").removeClass("active").hide();aa.height_icon.addClass("active").show()}else{aa.manager.height_filter=null;aa.height_icon.removeClass("active")}aa.manager.track.request_draw(true,true)}).appendTo(ah).hide();aa.parent_div.hover(function(){aa.transparency_icon.show();aa.height_icon.show()},function(){if(aa.manager.alpha_filter!==aa){aa.transparency_icon.hide()}if(aa.manager.height_filter!==aa){aa.height_icon.hide()}});$("<div style='clear: both;'/>").appendTo(aa.parent_div)};o(P.prototype,{to_dict:function(){var Z=f.prototype.to_dict.call(this);return o(Z,{type:"number",min:this.min,max:this.max,low:this.low,high:this.high})},copy:function(){return new P({name:this.name,index:this.index,tool_id:this.tool_id,tool_exp_name:this.tool_exp_name})},get_slider_step:function(ab,Z){var aa=Z-ab;return(aa<=2?0.01:1)},slide:function(aa,ab){var Z=ab.values;this.values_span.text(Z[0]+"-"+Z[1]);this.low=Z[0];this.high=Z[1];this.manager.track.request_draw(true,true)},applies_to:function(Z){if(Z.length>this.index){return true}return false},_keep_val:function(Z){return(isNaN(Z)||(Z>=this.low&&Z<=this.high))},keep:function(aa){if(!this.applies_to(aa)){return true}var ac=this;var ad=aa[this.index];if(ad instanceof Array){var ab=true;for(var Z=0;Z<ad.length;Z++){if(!this._keep_val(ad[Z])){ab=false;break}}return ab}else{return this._keep_val(aa[this.index])}},update_attrs:function(ac){var Z=false;if(!this.applies_to(ac)){return Z}var aa=ac[this.index];if(!(aa instanceof Array)){aa=[aa]}for(var ab=0;ab<aa.length;ab++){var ad=aa[ab];if(ad<this.min){this.min=Math.floor(ad);Z=true}if(ad>this.max){this.max=Math.ceil(ad);Z=true}}return Z},update_ui_elt:function(){if(this.min<this.max){this.parent_div.show()}else{this.parent_div.hide()}var aa=this.slider.slider("option","min"),Z=this.slider.slider("option","max");if(this.min<aa||this.max>Z){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",this.get_slider_step(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var U=function(ab,ah){this.track=ab;this.alpha_filter=null;this.height_filter=null;this.filters=[];this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(aj){aj.stopPropagation()}).click(function(aj){aj.stopPropagation()}).bind("dblclick",function(aj){aj.stopPropagation()}).bind("keydown",function(aj){aj.stopPropagation()});if(ah&&"filters" in ah){var Z=("alpha_filter" in ah?ah.alpha_filter:null),ac=("height_filter" in ah?ah.height_filter:null),ae=ah.filters,aa;for(var af=0;af<ae.length;af++){if(ae[af].type==="number"){aa=new P(ae[af]);this.add_filter(aa);if(aa.name===Z){this.alpha_filter=aa;aa.transparency_icon.addClass("active").show()}if(aa.name===ac){this.height_filter=aa;aa.height_icon.addClass("active").show()}}else{console.log("ERROR: unsupported filter: ",name,type)}}if("visible" in ah&&ah.visible){this.parent_div.show()}}if(this.filters.length!==0){var ai=$("<div/>").addClass("param-row").appendTo(this.parent_div);var ag=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(ai);var ad=this;ag.click(function(){ad.run_on_dataset()})}};o(U.prototype,{show:function(){this.parent_div.show()},hide:function(){this.parent_div.hide()},toggle:function(){this.parent_div.toggle()},visible:function(){return this.parent_div.is(":visible")},to_dict:function(){var ac={},ab=[],aa;for(var Z=0;Z<this.filters.length;Z++){aa=this.filters[Z];ab.push(aa.to_dict())}ac.filters=ab;ac.alpha_filter=(this.alpha_filter?this.alpha_filter.name:null);ac.height_filter=(this.height_filter?this.height_filter.name:null);ac.visible=this.parent_div.is(":visible");return ac},copy:function(aa){var ab=new U(aa);for(var Z=0;Z<this.filters.length;Z++){ab.add_filter(this.filters[Z].copy())}return ab},add_filter:function(Z){Z.manager=this;this.parent_div.append(Z.parent_div);this.filters.push(Z)},remove_all:function(){this.filters=[];this.parent_div.children().remove()},init_filters:function(){for(var Z=0;Z<this.filters.length;Z++){var aa=this.filters[Z];aa.update_ui_elt()}},clear_filters:function(){for(var Z=0;Z<this.filters.length;Z++){var aa=this.filters[Z];aa.slider.slider("option","values",[aa.min,aa.max])}this.alpha_filter=null;this.height_filter=null;this.parent_div.find(".icon-button").hide()},run_on_dataset:function(){var ah=function(al,aj,ak){if(!(aj in al)){al[aj]=ak}return al[aj]};var ab={},Z,aa,ac;for(var ad=0;ad<this.filters.length;ad++){Z=this.filters[ad];if(Z.tool_id){if(Z.min!==Z.low){aa=ah(ab,Z.tool_id,[]);aa[aa.length]=Z.tool_exp_name+" >= "+Z.low}if(Z.max!==Z.high){aa=ah(ab,Z.tool_id,[]);aa[aa.length]=Z.tool_exp_name+" <= "+Z.high}}}var af=[];for(var ai in ab){af[af.length]=[ai,ab[ai]]}var ag=af.length;(function ae(ap,am){var ak=am[0],al=ak[0],ao=ak[1],an="("+ao.join(") and (")+")",aj={cond:an,input:ap,target_dataset_id:ap,tool_id:al},am=am.slice(1);$.getJSON(run_tool_url,aj,function(aq){if(aq.error){show_modal("Filter Dataset","Error running tool "+al,{Close:hide_modal})}else{if(am.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{ae(aq.dataset_id,am)}}})})(this.track.dataset_id,af)}});var y=function(Z,aa){H.Scaler.call(this,aa);this.filter=Z};y.prototype.gen_val=function(Z){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(Z[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var B=function(Z){this.track=Z.track;this.params=Z.params;this.values={};this.restore_values((Z.saved_values?Z.saved_values:{}));this.onchange=Z.onchange};o(B.prototype,{restore_values:function(Z){var aa=this;$.each(this.params,function(ab,ac){if(Z[ac.key]!==undefined){aa.values[ac.key]=Z[ac.key]}else{aa.values[ac.key]=ac.default_value}})},build_form:function(){var ac=this;var Z=$("<div />");var ab;function aa(ag,ad){for(var ak=0;ak<ag.length;ak++){ab=ag[ak];if(ab.hidden){continue}var ae="param_"+ak;var ao=ac.values[ab.key];var ar=$("<div class='form-row' />").appendTo(ad);ar.append($("<label />").attr("for",ae).text(ab.label+":"));if(ab.type==="bool"){ar.append($('<input type="checkbox" />').attr("id",ae).attr("name",ae).attr("checked",ao))}else{if(ab.type==="text"){ar.append($('<input type="text"/>').attr("id",ae).val(ao).click(function(){$(this).select()}))}else{if(ab.type==="select"){var am=$("<select />").attr("id",ae);for(var ai=0;ai<ab.options.length;ai++){$("<option/>").text(ab.options[ai].label).attr("value",ab.options[ai].value).appendTo(am)}am.val(ao);ar.append(am)}else{if(ab.type==="color"){var aq=$("<div/>").appendTo(ar),al=$("<input />").attr("id",ae).attr("name",ae).val(ao).css("float","left").appendTo(aq).click(function(au){$(".tipsy").hide();var at=$(this).siblings(".tipsy");at.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(at).height()/2)+($(this).height()/2)}).show();at.click(function(av){av.stopPropagation()});$(document).bind("click.color-picker",function(){at.hide();$(document).unbind("click.color-picker")});au.stopPropagation()}),aj=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(aq).attr("title","Set new random color").tipsy({gravity:"s"}),an=$("<div class='tipsy tipsy-west' style='position: absolute;' />").appendTo(aq).hide(),af=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(an),ap=$("<div/>").appendTo(af),ah=$.farbtastic(ap,{width:100,height:100,callback:al,color:ao});aq.append($("<div/>").css("clear","both"));(function(at){aj.click(function(){at.setColor(get_random_color())})})(ah)}else{ar.append($("<input />").attr("id",ae).attr("name",ae).val(ao))}}}}if(ab.help){ar.append($("<div class='help'/>").text(ab.help))}}}aa(this.params,Z);return Z},update_from_form:function(Z){var ab=this;var aa=false;$.each(this.params,function(ac,ae){if(!ae.hidden){var af="param_"+ac;var ad=Z.find("#"+af).val();if(ae.type==="float"){ad=parseFloat(ad)}else{if(ae.type==="int"){ad=parseInt(ad)}else{if(ae.type==="bool"){ad=Z.find("#"+af).is(":checked")}}}if(ad!==ab.values[ae.key]){ab.values[ae.key]=ad;aa=true}}});if(aa){this.onchange();this.track.changed()}}});var b=function(Z,ac,ab,aa,ad){this.track=Z;this.index=ac;var ae=this.track._get_tile_bounds(ac,ab);this.low=ae[0];this.high=ae[1];this.resolution=ab;this.html_elt=$("<div class='track-tile'/>").append(aa).height($(aa).attr("height"));this.data=ad;this.stale=false};b.prototype.predisplay_actions=function(){};var j=function(Z,ac,ab,aa,ad,ae){b.call(this,Z,ac,ab,aa,ad);this.max_val=ae};o(j.prototype,b.prototype);var K=function(ac,ah,ad,ab,af,am,ag,an,aa,ak){b.call(this,ac,ah,ad,ab,af);this.mode=ag;this.all_slotted=aa;this.feature_mapper=ak;this.has_icons=false;if(an){this.has_icons=true;var ai=this;ab=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:z-1,width:ab.width}).prependTo(this.html_elt);var aj=new GenomeRegion({chrom:ac.view.chrom,start:this.low,end:this.high}),al=af.length,ae=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+al+" features in this region were obtained from server. Click to get more data including depth").tipsy({gravity:"s"}).appendTo(message_div),Z=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+al+" features in this region were obtained from server. Click to get more data excluding depth").tipsy({gravity:"s"}).appendTo(message_div);ae.click(function(){ai.stale=true;ac.data_manager.get_more_data(aj,ac.mode,ai.resolution,{},ac.data_manager.DEEP_DATA_REQ);$(".tipsy").hide();ac.request_draw(true)}).dblclick(function(ao){ao.stopPropagation()});Z.click(function(){ai.stale=true;ac.data_manager.get_more_data(aj,ac.mode,ai.resolution,{},ac.data_manager.BROAD_DATA_REQ);$(".tipsy").hide();ac.request_draw(true)}).dblclick(function(ao){ao.stopPropagation()})}};o(K.prototype,b.prototype);K.prototype.predisplay_actions=function(){var aa=this,Z={};if(aa.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(al){if(!this.hovered){return}var ag=$(this).offset(),ak=al.pageX-ag.left,aj=al.pageY-ag.top,ap=aa.feature_mapper.get_feature_data(ak,aj),ah=(ap?ap[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!ah||$(this).attr("id")!==ah.toString()){$(this).remove()}});if(ap){var ac=Z[ah];if(!ac){var ah=ap[0],am={name:ap[3],start:ap[1],end:ap[2],strand:ap[4]},af=aa.track.filters_manager.filters,ae;for(var ai=0;ai<af.length;ai++){ae=af[ai];am[ae.name]=ap[ae.index]}var ac=$("<div/>").attr("id",ah).addClass("feature-popup"),aq=$("<table/>"),ao,an,ar;for(ao in am){an=am[ao];ar=$("<tr/>").appendTo(aq);$("<th/>").appendTo(ar).text(ao);$("<td/>").attr("align","left").appendTo(ar).text(typeof(an)==="number"?T(an,2):an)}ac.append($("<div class='feature-popup-inner'>").append(aq));Z[ah]=ac}ac.appendTo($(this).parents(".track-content").children(".overlay"));var ad=ak+parseInt(aa.html_elt.css("left"))-ac.width()/2,ab=aj+parseInt(aa.html_elt.css("top"))+7;ac.css("left",ad+"px").css("top",ab+"px")}else{if(!al.isPropagationStopped()){al.stopPropagation();$(this).siblings().each(function(){$(this).trigger(al)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var h=function(aa,Z,ac){o(ac,{drag_handle_class:"draghandle"});p.call(this,aa,Z,ac);this.data_url=("data_url" in ac?ac.data_url:default_data_url);this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in ac?ac.data_query_wait:G);this.dataset_check_url=converted_datasets_state_url;var ab=new Dataset({id:ac.dataset_id,hda_ldda:ac.hda_ldda});this.data_manager=("data_manager" in ac?ac.data_manager:new GenomeDataManager({dataset:ab,data_url:default_data_url,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 ac)||ac.resize){this.add_resize_handle()}}};o(h.prototype,p.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},p.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(Z){Z.view.set_overview(Z)}},p.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(Z){if(Z.filters_manager.visible()){Z.filters_manager.clear_filters()}else{Z.filters_manager.init_filters()}Z.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(Z){Z.dynamic_tool_div.toggle();if(Z.dynamic_tool_div.is(":visible")){Z.set_name(Z.name+Z.tool_region_and_parameters_str())}else{Z.revert_name()}$(".tipsy").remove()}},p.prototype.action_icons_def[2]],can_draw:function(){if(this.dataset_id&&p.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 Z=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(Z)}this.name_div=$("<div/>").addClass("track-name").appendTo(Z).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return Z},on_resize:function(){},add_resize_handle:function(){var Z=this;var ac=false;var ab=false;var aa=$("<div class='track-resize'>");$(Z.container_div).hover(function(){if(Z.content_visible){ac=true;aa.show()}},function(){ac=false;if(!ab){aa.hide()}});aa.hide().bind("dragstart",function(ad,ae){ab=true;ae.original_height=$(Z.content_div).height()}).bind("drag",function(ae,af){var ad=Math.min(Math.max(af.original_height+af.deltaY,Z.min_height_px),Z.max_height_px);$(Z.tiles_div).css("height",ad);Z.visible_height_px=(Z.max_height_px===ad?0:ad);Z.on_resize()}).bind("dragend",function(ad,ae){Z.tile_cache.clear();ab=false;if(!ac){aa.hide()}Z.config.values.height=Z.visible_height_px;Z.changed()}).appendTo(Z.container_div)},set_display_modes:function(ac,af){this.display_modes=ac;this.mode=(af?af:(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 aa=this,ad={};for(var ab=0,Z=aa.display_modes.length;ab<Z;ab++){var ae=aa.display_modes[ab];ad[ae]=function(ag){return function(){aa.change_mode(ag);aa.icons_div.show();aa.container_div.mouseleave(function(){aa.icons_div.hide()})}}(ae)}make_popupmenu(this.action_icons.mode_icon,ad)},build_action_icons:function(){p.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 V){return"LabelTrack"}else{if(this instanceof x){return"ReferenceTrack"}else{if(this instanceof i){return"LineTrack"}else{if(this instanceof Q){return"ReadTrack"}else{if(this instanceof N){return"VcfTrack"}else{if(this instanceof g){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(){var aa=this;aa.enabled=false;aa.tile_cache.clear();aa.data_manager.clear();aa.content_div.css("height","auto");aa.tiles_div.children().remove();aa.container_div.removeClass("nodata error pending");if(!aa.dataset_id){return}var Z=$.Deferred();$.getJSON(this.dataset_check_url,{hda_ldda:aa.hda_ldda,dataset_id:aa.dataset_id,chrom:aa.view.chrom},function(ab){if(!ab||ab==="error"||ab.kind==="error"){aa.container_div.addClass("error");aa.tiles_div.text(n);if(ab.message){var ac=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ab.message+"</pre>",{Close:hide_modal})});aa.tiles_div.append(ac)}}else{if(ab==="no converter"){aa.container_div.addClass("error");aa.tiles_div.text(F)}else{if(ab==="no data"||(ab.data!==undefined&&(ab.data===null||ab.data.length===0))){aa.container_div.addClass("nodata");aa.tiles_div.text(A)}else{if(ab==="pending"){aa.container_div.addClass("pending");aa.tiles_div.html(s);setTimeout(function(){aa.init()},aa.data_query_wait)}else{if(ab==="data"||ab.status==="data"){if(ab.valid_chroms){aa.valid_chroms=ab.valid_chroms;aa.update_icons()}aa.tiles_div.text(S);if(aa.view.chrom){aa.tiles_div.text("");aa.tiles_div.css("height",aa.visible_height_px+"px");aa.enabled=true;$.when(aa.predraw_init()).done(function(){Z.resolve();aa.container_div.removeClass("nodata error pending");aa.request_draw()})}else{Z.resolve()}}}}}}});this.update_icons();return Z},predraw_init:function(){}});var I=function(ab,aa,ac){h.call(this,ab,aa,ac);var Z=this,ab=Z.view;l(Z.container_div,Z.drag_handle_class,".group",Z);this.filters_manager=new U(this,("filters" in ac?ac.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=("tool" in ac&&ac.tool?new q(this,ac.tool,ac.tool_state):null);this.tile_cache=new Cache(M);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(ac.mode){this.change_mode(ac.mode)}};o(I.prototype,p.prototype,h.prototype,{action_icons_def:h.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(Z){$(".tipsy").remove();Z.slotters[Z.view.resolution_px_b].max_rows*=2;Z.request_draw(true)},hide:true}]),copy:function(Z){var aa=this.to_dict();o(aa,{data_manager:this.data_manager});var ab=new this.constructor(this.view,Z,aa);ab.change_mode(this.mode);ab.enabled=this.enabled;return ab},set_filters_manager:function(Z){this.filters_manager=Z;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},change_mode:function(aa){var Z=this;Z.mode=aa;Z.config.values.mode=aa;Z.tile_cache.clear();Z.request_draw();this.action_icons.mode_icon.attr("title","Set display mode (now: "+Z.mode+")");return Z},update_icons:function(){var Z=this;if(Z.filters_available){Z.action_icons.filters_icon.show()}else{Z.action_icons.filters_icon.hide()}if(Z.tool){Z.action_icons.tools_icon.show()}else{Z.action_icons.tools_icon.hide()}},_gen_tile_cache_key:function(aa,ab,Z){return aa+"_"+ab+"_"+Z},request_draw:function(aa,Z){this.view.request_redraw(false,aa,Z,this)},before_draw:function(){},_draw:function(aa,ak){if(!this.can_draw()){return}var ai=this.view.low,ae=this.view.high,ag=ae-ai,ab=this.view.container.width(),am=this.view.resolution_px_b,ad=this.view.resolution_b_px;if(this.is_overview){ai=this.view.max_low;ae=this.view.max_high;ad=Math.pow(RESOLUTION,Math.ceil(Math.log((view.max_high-view.max_low)/O)/Math.log(RESOLUTION)));am=ab/(view.max_high-view.max_low)}this.before_draw();this.tiles_div.children().addClass("remove");var Z=Math.floor(ai/(ad*O)),ah=true,al=[],af=function(an){return(an&&"track" in an)};while((Z*O*ad)<ae){var aj=this.draw_helper(aa,ab,Z,ad,this.tiles_div,am);if(af(aj)){al.push(aj)}else{ah=false}Z+=1}if(!ak){this.tiles_div.children(".remove").removeClass("remove").remove()}var ac=this;if(ah){this.tiles_div.children(".remove").remove();ac.postdraw_actions(al,ab,am,ak)}},postdraw_actions:function(ac,ad,af,Z){var ab=this;var ae=false;for(var aa=0;aa<ac.length;aa++){if(ac[aa].has_icons){ae=true;break}}if(ae){for(var aa=0;aa<ac.length;aa++){tile=ac[aa];if(!tile.has_icons){tile.html_elt.css("padding-top",z)}}}},draw_helper:function(Z,am,ar,ap,af,ag,an){var al=this,av=this._gen_tile_cache_key(am,ag,ar),ad=this._get_tile_bounds(ar,ap),ac=new GenomeRegion({chrom:this.view.chrom,start:ad[0],end:ad[1]});if(!an){an={}}var au=(Z?undefined:al.tile_cache.get_elt(av));if(au){al.show_tile(au,af,ag);return au}var aj=true;var aq=al.data_manager.get_data(ac,al.mode,ap,al.data_url_extra_params);if(is_deferred(aq)){aj=false}var ah;if(view.reference_track&&ag>view.canvas_manager.char_width_px){ah=view.reference_track.data_manager.get_data(ac,al.mode,ap,view.reference_track.data_url_extra_params);if(is_deferred(ah)){aj=false}}if(aj){o(aq,an.more_tile_data);var ai=al.mode;if(ai==="Auto"){ai=al.get_mode(aq);al.update_auto_mode(ai)}var ab=al.view.canvas_manager.new_canvas(),at=ac.get("start"),aa=ac.get("end"),am=Math.ceil((aa-at)*ag)+al.left_offset,ak=al.get_canvas_height(aq,ai,ag,am);ab.width=am;ab.height=ak;var ao=ab.getContext("2d");ao.translate(this.left_offset,0);var au=al.draw_tile(aq,ao,ai,ap,ar,ag,ah);if(au!==undefined){al.tile_cache.set_elt(av,au);al.show_tile(au,af,ag)}return au}var ae=$.Deferred();$.when(aq,ah).then(function(){view.request_redraw(false,false,false,al);ae.resolve()});return ae},get_canvas_height:function(Z,ab,ac,aa){return this.visible_height_px},draw_tile:function(Z,ab,ae,ad,aa,af,ac){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(ab,ad,ae){var aa=this,Z=ab.html_elt;ab.predisplay_actions();var ac=(ab.low-(this.is_overview?this.view.max_low:this.view.low))*ae;if(this.left_offset){ac-=this.left_offset}Z.css({position:"absolute",top:0,left:ac});if(Z.hasClass("remove")){Z.removeClass("remove")}else{ad.append(Z)}aa.after_show_tile(ab)},after_show_tile:function(Z){},_get_tile_bounds:function(Z,aa){var ac=Math.floor(Z*O*aa),ad=Math.ceil(O*aa),ab=(ac+ad<=this.view.max_high?ac+ad:this.view.max_high);return[ac,ab]},tool_region_and_parameters_str:function(ab,Z,ac){var aa=this,ad=(ab!==undefined&&Z!==undefined&&ac!==undefined?ab+":"+Z+"-"+ac:"all");return" - region=["+ad+"], parameters=["+aa.tool.get_param_values().join(", ")+"]"},data_and_mode_compatible:function(Z,aa){return true},can_subset:function(Z){return false},init_for_tool_data:function(){this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url;this.normal_postdraw_actions=this.postdraw_actions;this.postdraw_actions=function(ab,ac,ad,Z){var aa=this;aa.normal_postdraw_actions(ab,ac,ad,Z);aa.dataset_state_url=converted_datasets_state_url;aa.data_query_wait=G;$.when(server_state_deferred(aa.dataset_state_url,{dataset_id:aa.dataset_id,hda_ldda:aa.hda_ldda},aa.data_query_wait,function(ae){return ae!=="pending"})).then(function(){aa.data_url=default_data_url});aa.postdraw_actions=aa.normal_postdraw_actions}}});var V=function(aa,Z){var ab={resize:false};h.call(this,aa,Z,ab);this.container_div.addClass("label-track")};o(V.prototype,h.prototype,{build_header_div:function(){},init:function(){this.enabled=true},_draw:function(){var ab=this.view,ac=ab.high-ab.low,af=Math.floor(Math.pow(10,Math.floor(Math.log(ac)/Math.log(10)))),Z=Math.floor(ab.low/af)*af,ad=this.view.container.width(),aa=$("<div style='position: relative; height: 1.3em;'></div>");while(Z<ab.high){var ae=(Z-ab.low)/ac*ad;aa.append($("<div class='label'>"+commatize(Z)+"</div>").css({position:"absolute",left:ae-1}));Z+=af}this.content_div.children(":first").remove();this.content_div.append(aa)}});var g=function(aa,Z,ad){I.call(this,aa,Z,ad);this.drawables=[];this.left_offset=0;if("drawables" in ad){var ac;for(var ab=0;ab<ad.drawables.length;ab++){ac=ad.drawables[ab];this.drawables[ab]=object_from_template(ac);if(ac.left_offset>this.left_offset){this.left_offset=ac.left_offset}}this.enabled=true}if(this.drawables.length!==0){this.set_display_modes(this.drawables[0].display_modes,this.drawables[0].mode)}this.update_icons();this.obj_type="CompositeTrack"};o(g.prototype,I.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(Z){$(".tipsy").remove();Z.show_group()}}].concat(I.prototype.action_icons_def),to_dict:v.prototype.to_dict,add_drawable:v.prototype.add_drawable,unpack_drawables:v.prototype.unpack_drawables,change_mode:function(Z){I.prototype.change_mode.call(this,Z);for(var aa=0;aa<this.drawables.length;aa++){this.drawables[aa].change_mode(Z)}},init:function(){var ab=[];for(var aa=0;aa<this.drawables.length;aa++){ab.push(this.drawables[aa].init())}var Z=this;$.when.apply($,ab).then(function(){Z.enabled=true;Z.request_draw()})},update_icons:function(){this.action_icons.filters_icon.hide();this.action_icons.tools_icon.hide()},can_draw:p.prototype.can_draw,draw_helper:function(aa,ao,av,ar,ag,ai,ap){var an=this,az=this._gen_tile_cache_key(ao,ai,av),ae=this._get_tile_bounds(av,ar),aw=ae[0],ab=ae[1];if(!ap){ap={}}var ay=(aa?undefined:an.tile_cache.get_elt(az));if(ay){an.show_tile(ay,ag,ai);return ay}var ah=[],an,al=true,at,aj;for(var au=0;au<this.drawables.length;au++){an=this.drawables[au];at=an.data_manager.get_data(aw,ab,an.mode,ar,an.data_url_extra_params);if(is_deferred(at)){al=false}ah.push(at);aj=null;if(view.reference_track&&ai>view.canvas_manager.char_width_px){aj=view.reference_track.data_manager.get_data(aw,ab,an.mode,ar,view.reference_track.data_url_extra_params);if(is_deferred(aj)){al=false}}ah.push(aj)}if(al){o(at,ap.more_tile_data);this.tile_predraw_init();var ad=an.view.canvas_manager.new_canvas(),ae=an._get_tile_bounds(av,ar),aw=ae[0],ab=ae[1],ax=0,ao=Math.ceil((ab-aw)*ai)+this.left_offset,am=0,ac=[];var Z=0;for(var au=0;au<this.drawables.length;au++,ax+=2){an=this.drawables[au];at=ah[ax];var ak=an.mode;if(ak==="Auto"){ak=an.get_mode(at);an.update_auto_mode(ak)}ac.push(ak);Z=an.get_canvas_height(at,ak,ai,ao);if(Z>am){am=Z}}ad.width=ao;ad.height=(ap.height?ap.height:am);ax=0;var aq=ad.getContext("2d");aq.translate(this.left_offset,0);aq.globalAlpha=0.5;aq.globalCompositeOperation="source-over";for(var au=0;au<this.drawables.length;au++,ax+=2){an=this.drawables[au];at=ah[ax];aj=ah[ax+1];ay=an.draw_tile(at,aq,ac[au],ar,av,ai,aj)}this.tile_cache.set_elt(az,ay);this.show_tile(ay,ag,ai);return ay}var af=$.Deferred(),an=this;$.when.apply($,ah).then(function(){view.request_redraw(false,false,false,an);af.resolve()});return af},show_group:function(){var ac=new L(this.view,this.container,{name:this.name}),Z;for(var ab=0;ab<this.drawables.length;ab++){Z=this.drawables[ab];ac.add_drawable(Z);Z.container=ac;ac.content_div.append(Z.container_div)}var aa=this.container.replace_drawable(this,ac,true);ac.request_draw()},tile_predraw_init:function(){var ac=Number.MAX_VALUE,Z=-ac,aa;for(var ab=0;ab<this.drawables.length;ab++){aa=this.drawables[ab];if(aa instanceof i){if(aa.prefs.min_value<ac){ac=aa.prefs.min_value}if(aa.prefs.max_value>Z){Z=aa.prefs.max_value}}}for(var ab=0;ab<this.drawables.length;ab++){aa=this.drawables[ab];aa.prefs.min_value=ac;aa.prefs.max_value=Z}},postdraw_actions:function(ab,ae,ag,aa){I.prototype.postdraw_actions.call(this,ab,ae,ag,aa);var ad=-1;for(var ac=0;ac<ab.length;ac++){var Z=ab[ac].html_elt.find("canvas").height();if(Z>ad){ad=Z}}for(var ac=0;ac<ab.length;ac++){var af=ab[ac];if(af.html_elt.find("canvas").height()!==ad){this.draw_helper(true,ae,af.index,af.resolution,af.html_elt.parent(),ag,{height:ad});af.html_elt.remove()}}}});var x=function(Z){I.call(this,Z,{content_div:Z.top_labeltrack},{resize:false});Z.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=reference_url;this.data_url_extra_params={dbkey:Z.dbkey};this.data_manager=new ReferenceTrackDataManager({data_url:reference_url});this.hide_contents()};o(x.prototype,p.prototype,I.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},can_draw:p.prototype.can_draw,draw_tile:function(ah,ai,ae,ad,aa,aj){var ac=this;if(aj>this.view.canvas_manager.char_width_px){if(ah.data===null){this.hide_contents();return}var ab=ai.canvas;ai.font=ai.canvas.manager.default_font;ai.textAlign="center";ah=ah.data;for(var af=0,ag=ah.length;af<ag;af++){var Z=Math.floor(af*aj);ai.fillText(ah[af],Z,10)}this.show_contents();return new b(ac,aa,ad,ab,ah)}this.hide_contents()}});var i=function(ab,aa,ac){var Z=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";I.call(this,ab,aa,ac);this.hda_ldda=ac.hda_ldda;this.dataset_id=ac.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;this.config=new B({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value: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:ac.prefs,onchange:function(){Z.set_name(Z.prefs.name);Z.vertical_range=Z.prefs.max_value-Z.prefs.min_value;Z.set_min_value(Z.prefs.min_value);Z.set_max_value(Z.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};o(i.prototype,p.prototype,I.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(Z){this.prefs.min_value=Z;$("#linetrack_"+this.dataset_id+"_minval").text(this.prefs.min_value);this.tile_cache.clear();this.request_draw()},set_max_value:function(Z){this.prefs.max_value=Z;$("#linetrack_"+this.dataset_id+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.request_draw()},predraw_init:function(){var Z=this;Z.vertical_range=undefined;return $.getJSON(Z.data_url,{stats:true,chrom:Z.view.chrom,low:null,high:null,hda_ldda:Z.hda_ldda,dataset_id:Z.dataset_id},function(aa){Z.container_div.addClass("line-track");var ad=aa.data;if(isNaN(parseFloat(Z.prefs.min_value))||isNaN(parseFloat(Z.prefs.max_value))){var ab=ad.min;var af=ad.max;ab=Math.floor(Math.min(0,Math.max(ab,ad.mean-2*ad.sd)));af=Math.ceil(Math.max(0,Math.min(af,ad.mean+2*ad.sd)));Z.prefs.min_value=ab;Z.prefs.max_value=af;$("#track_"+Z.dataset_id+"_minval").val(Z.prefs.min_value);$("#track_"+Z.dataset_id+"_maxval").val(Z.prefs.max_value)}Z.vertical_range=Z.prefs.max_value-Z.prefs.min_value;Z.total_frequency=ad.total_frequency;Z.container_div.find(".yaxislabel").remove();var ae=$("<div/>").text(T(Z.prefs.min_value,3)).make_text_editable({num_cols:6,on_finish:function(ag){$(".tipsy").remove();var ag=parseFloat(ag);if(!isNaN(ag)){Z.set_min_value(ag)}},help_text:"Set min value"}).addClass("yaxislabel bottom").attr("id","linetrack_"+Z.dataset_id+"_minval").prependTo(Z.container_div),ac=$("<div/>").text(T(Z.prefs.max_value,3)).make_text_editable({num_cols:6,on_finish:function(ag){$(".tipsy").remove();var ag=parseFloat(ag);if(!isNaN(ag)){Z.set_max_value(ag)}},help_text:"Set max value"}).addClass("yaxislabel top").attr("id","linetrack_"+Z.dataset_id+"_maxval").prependTo(Z.container_div)})},draw_tile:function(aj,ah,ae,ac,aa,ai){var ab=ah.canvas,Z=this._get_tile_bounds(aa,ac),ad=Z[0],ag=Z[1],af=new H.LinePainter(aj.data,ad,ag,this.prefs,ae);af.draw(ah,ab.width,ab.height,ai);return new b(this,aa,ac,ab,aj.data)},can_subset:function(Z){return false},});var c=function(ac,ab,ae){var aa=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];I.call(this,ac,ab,ae);var ad=get_random_color(),Z=get_random_color([ad,"#ffffff"]);this.config=new B({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:ad},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:Z},{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:"histogram_max",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:ae.prefs,onchange:function(){aa.set_name(aa.prefs.name);aa.tile_cache.clear();aa.set_painter_from_config();aa.request_draw()}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.hda_ldda=ae.hda_ldda;this.dataset_id=ae.dataset_id;this.original_dataset_id=ae.dataset_id;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()};o(c.prototype,p.prototype,I.prototype,{set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=H.ArcLinkedFeaturePainter}else{this.painter=H.LinkedFeaturePainter}},before_draw:function(){this.max_height_px=0},after_show_tile:function(Z){this.max_height_px=Math.max(this.max_height_px,Z.html_elt.height());Z.html_elt.parent().children().css("height",this.max_height_px+"px");var aa=this.max_height_px;if(this.visible_height_px!==0){aa=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",aa+"px")},postdraw_actions:function(ao,aj,ae,ad){I.prototype.postdraw_actions.call(this,ao,ad);var ai=this;if(ai.mode==="Histogram"){var aa=-1;for(var al=0;al<ao.length;al++){var ak=ao[al].max_val;if(ak>aa){aa=ak}}for(var al=0;al<ao.length;al++){var aq=ao[al];if(aq.max_val!==aa){aq.html_elt.remove();ai.draw_helper(true,aj,aq.index,aq.resolution,aq.html_elt.parent(),ae,{more_tile_data:{max:aa}})}}}if(ai.filters_manager){var af=ai.filters_manager.filters;for(var an=0;an<af.length;an++){af[an].update_ui_elt()}var ap=false,Z,ag;for(var al=0;al<ao.length;al++){if(ao[al].data.length){Z=ao[al].data[0];for(var an=0;an<af.length;an++){ag=af[an];if(ag.applies_to(Z)&&ag.min!==ag.max){ap=true;break}}}}if(ai.filters_available!==ap){ai.filters_available=ap;if(!ai.filters_available){ai.filters_manager.hide()}ai.update_icons()}}this.container_div.find(".yaxislabel").remove();var ac=ao[0];if(ac instanceof j){var ah=(this.prefs.histogram_max?this.prefs.histogram_max:ac.max_val),ab=$("<div/>").text(ah).make_text_editable({num_cols:12,on_finish:function(ar){$(".tipsy").remove();var ar=parseFloat(ar);ai.prefs.histogram_max=(!isNaN(ar)?ar:null);ai.tile_cache.clear();ai.request_draw()},help_text:"Set max value; leave blank to use default"}).addClass("yaxislabel top").css("color",this.prefs.label_color);this.container_div.prepend(ab)}if(ac instanceof K){var am=true;for(var al=0;al<ao.length;al++){if(!ao[al].all_slotted){am=false;break}}if(!am){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(Z){var Z;if(this.mode==="Auto"){if(Z==="no_detail"){Z="feature spans"}else{if(Z==="summary_tree"){Z="coverage histogram"}}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+Z+")")}},incremental_slots:function(ad,Z,ac){var aa=this.view.canvas_manager.dummy_context,ab=this.slotters[ad];if(!ab||(ab.mode!==ac)){ab=new (r.FeatureSlotter)(ad,ac,w,function(ae){return aa.measureText(ae)});this.slotters[ad]=ab}return ab.slot_features(Z)},get_summary_tree_data:function(ad,ag,ab,ao){if(ao>ab-ag){ao=ab-ag}var ak=Math.floor((ab-ag)/ao),an=[],ac=0;var ae=0,af=0,aj,am=0,ah=[],al,ai;var aa=function(ar,aq,at,ap){ar[0]=aq+at*ap;ar[1]=aq+(at+1)*ap};while(am<ao&&ae!==ad.length){var Z=false;for(;am<ao&&!Z;am++){aa(ah,ag,am,ak);for(af=ae;af<ad.length;af++){aj=ad[af].slice(1,3);if(is_overlap(aj,ah)){Z=true;break}}if(Z){break}}data_start_index=af;an[an.length]=al=[ah[0],0];for(;af<ad.length;af++){aj=ad[af].slice(1,3);if(is_overlap(aj,ah)){al[1]++}else{break}}if(al[1]>ac){ac=al[1]}am++}return{max:ac,delta:ak,data:an}},get_mode:function(Z){if(Z.dataset_type==="summary_tree"){mode="summary_tree"}else{if(Z.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>E){mode="Squish"}else{mode="Pack"}}}return mode},get_canvas_height:function(Z,ad,ae,aa){if(ad==="summary_tree"||ad==="Histogram"){return this.summary_draw_height}else{var ac=this.incremental_slots(ae,Z.data,ad);var ab=new (this.painter)(null,null,null,this.prefs,ad);return Math.max(X,ab.get_required_height(ac,aa))}},draw_tile:function(ak,ao,am,ap,au,ag,ab){var an=this,aa=ao.canvas,ad=this._get_tile_bounds(au,ap),ax=ad[0],Z=ad[1],aC=25,ac=this.left_offset;if(am==="summary_tree"||am==="Histogram"){if(ak.dataset_type!=="summary_tree"){var ah=this.get_summary_tree_data(ak.data,ax,Z,200);if(ak.max){ah.max=ak.max}ak=ah}var az=new H.SummaryTreePainter(ak,ax,Z,this.prefs);az.draw(ao,aa.width,aa.height,ag);return new j(an,au,ap,aa,ak.data,ak.max)}var af=[],al=this.slotters[ag].slots;all_slotted=true;if(ak.data){var ai=this.filters_manager.filters;for(var aq=0,at=ak.data.length;aq<at;aq++){var ae=ak.data[aq];var ar=false;var aj;for(var aw=0,aB=ai.length;aw<aB;aw++){aj=ai[aw];aj.update_attrs(ae);if(!aj.keep(ae)){ar=true;break}}if(!ar){af.push(ae);if(!(ae[0] in al)){all_slotted=false}}}}var aA=(this.filters_manager.alpha_filter?new y(this.filters_manager.alpha_filter):null);var ay=(this.filters_manager.height_filter?new y(this.filters_manager.height_filter):null);var az=new (this.painter)(af,ax,Z,this.prefs,am,aA,ay,ab);var av=null;ao.fillStyle=this.prefs.block_color;ao.font=ao.canvas.manager.default_font;ao.textAlign="right";if(ak.data){av=az.draw(ao,aa.width,aa.height,ag,al);av.translation=-ac}return new K(an,au,ap,aa,ak.data,ag,am,ak.message,all_slotted,av)},data_and_mode_compatible:function(Z,aa){if(aa==="Auto"){return true}else{if(Z.extra_info==="no_detail"||Z.dataset_type==="summary_tree"){return false}else{return true}}},can_subset:function(Z){if(Z.dataset_type==="summary_tree"||Z.message||Z.extra_info==="no_detail"){return false}return true},});var N=function(aa,Z,ab){c.call(this,aa,Z,ab);this.config=new B({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:get_random_color()},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ab.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=H.ReadPainter};o(N.prototype,p.prototype,I.prototype,c.prototype);var Q=function(ab,aa,ad){c.call(this,ab,aa,ad);var ac=get_random_color(),Z=get_random_color([ac,"#ffffff"]);this.config=new B({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:ac},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:Z},{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:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"Clear value to set automatically"},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ad.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=H.ReadPainter;this.update_icons()};o(Q.prototype,p.prototype,I.prototype,c.prototype);R.View=W;R.DrawableGroup=L;R.LineTrack=i;R.FeatureTrack=c;R.ReadTrack=Q;R.VcfTrack=N;R.CompositeTrack=g};var slotting_module=function(c,b){var e=c("class").extend;var d=2,a=5;b.FeatureSlotter=function(i,h,f,g){this.slots={};this.start_end_dct={};this.w_scale=i;this.mode=h;this.include_label=(h==="Pack");this.max_rows=f;this.measureText=g};e(b.FeatureSlotter.prototype,{slot_features:function(m){var p=this.w_scale,h=this.start_end_dct,x=[],z=[],n=0,y=this.max_rows;for(var v=0,w=m.length;v<w;v++){var k=m[v],o=k[0];if(this.slots[o]!==undefined){n=Math.max(n,this.slots[o]);z.push(this.slots[o])}else{x.push(v)}}var q=function(E,F){for(var D=0;D<=y;D++){var B=false,G=h[D];if(G!==undefined){for(var A=0,C=G.length;A<C;A++){var i=G[A];if(F>i[0]&&E<i[1]){B=true;break}}}if(!B){return D}}return -1};for(var v=0,w=x.length;v<w;v++){var k=m[x[v]],o=k[0],t=k[1],f=k[2],r=k[3],g=Math.floor(t*p),l=Math.ceil(f*p),u=this.measureText(r).width,j;if(r!==undefined&&this.include_label){u+=(d+a);if(g-u>=0){g-=u;j="left"}else{l+=u;j="right"}}var s=q(g,l);if(s>=0){if(h[s]===undefined){h[s]=[]}h[s].push([g,l]);this.slots[o]=s;n=Math.max(n,s)}}return n+1}})};var painters_module=function(i,x){var u=i("class").extend;var p=function(I,A,G,z,F,D){if(D===undefined){D=4}var C=z-A;var B=F-G;var E=Math.floor(Math.sqrt(C*C+B*B)/D);var J=C/E;var H=B/E;var y;for(y=0;y<E;y++,A+=J,G+=H){if(y%2!==0){continue}I.fillRect(A,G,D,1)}};var q=function(B,A,z,E){var D=A-E/2,C=A+E/2,F=z-Math.sqrt(E*3/2);B.beginPath();B.moveTo(D,F);B.lineTo(C,F);B.lineTo(A,z);B.lineTo(D,F);B.strokeStyle=this.fillStyle;B.fill();B.stroke();B.closePath()};var d=function(y){this.default_val=(y?y:1)};d.prototype.gen_val=function(y){return this.default_val};var l=function(A,C,y,z,B){this.data=A;this.view_start=C;this.view_end=y;this.prefs=u({},this.default_prefs,z);this.mode=B};l.prototype.default_prefs={};l.prototype.draw=function(z,A,y,B){};var v=function(A,C,y,z,B){l.call(this,A,C,y,z,B)};v.prototype.default_prefs={show_counts:false};v.prototype.draw=function(L,z,K,M){var E=this.view_start,N=this.view_end-this.view_start,I=this.data.data,G=(this.prefs.histogram_max?this.prefs.histogram_max:this.data.max),B=K;delta_x_px=Math.ceil(this.data.delta*M);L.save();for(var C=0,D=I.length;C<D;C++){var H=Math.floor((I[C][0]-E)*M);var F=I[C][1];if(!F){continue}var J=F/G*K;if(F!==0&&J<1){J=1}L.fillStyle=this.prefs.block_color;L.fillRect(H,B-J,delta_x_px,J);var A=4;if(this.prefs.show_counts&&(L.measureText(F).width+A)<delta_x_px){L.fillStyle=this.prefs.label_color;L.textAlign="center";L.fillText(F,H+(delta_x_px/2),10)}}L.restore()};var b=function(y,C,E,F,A){l.call(this,y,C,E,F,A);if(this.prefs.min_value===undefined){var G=Infinity;for(var z=0,B=this.data.length;z<B;z++){G=Math.min(G,this.data[z][1])}this.prefs.min_value=G}if(this.prefs.max_value===undefined){var D=-Infinity;for(var z=0,B=this.data.length;z<B;z++){D=Math.max(D,this.data[z][1])}this.prefs.max_value=D}};b.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};b.prototype.draw=function(S,Q,N,D){var I=false,K=this.prefs.min_value,F=this.prefs.max_value,M=F-K,B=N,C=this.view_start,P=this.view_end-this.view_start,L=this.mode,aa=this.data;S.save();var ac=Math.round(N+K/M*N);if(L!=="Intensity"){S.fillStyle="#aaa";S.fillRect(0,ac,Q,1)}S.beginPath();var Y,G,E;if(aa.length>1){E=Math.ceil((aa[1][0]-aa[0][0])*D)}else{E=10}var A=parseInt(this.prefs.color.slice(1),16),H=(A&16711680)>>16,R=(A&65280)>>8,V=A&255;for(var T=0,U=aa.length;T<U;T++){S.fillStyle=S.strokeStyle=this.prefs.color;Y=Math.round((aa[T][0]-C)*D);G=aa[T][1];var W=false,J=false;if(G===null){if(I&&L==="Filled"){S.lineTo(Y,B)}I=false;continue}if(G<K){J=true;G=K}else{if(G>F){W=true;G=F}}if(L==="Histogram"){G=Math.round(G/M*B);S.fillRect(Y,ac,E,-G)}else{if(L==="Intensity"){var z=(G-K)/M,O=Math.round(H+(255-H)*(1-z)),X=Math.round(R+(255-R)*(1-z)),ab=Math.round(V+(255-V)*(1-z));S.fillStyle="rgb("+O+","+X+","+ab+")";S.fillRect(Y,0,E,B)}else{G=Math.round(B-(G-K)/M*B);if(I){S.lineTo(Y,G)}else{I=true;if(L==="Filled"){S.moveTo(Y,B);S.lineTo(Y,G)}else{S.moveTo(Y,G)}}}}S.fillStyle=this.prefs.overflow_color;if(W||J){var Z;if(L==="Histogram"||L==="Intensity"){Z=E}else{Y-=2;Z=4}if(W){S.fillRect(Y,0,Z,3)}if(J){S.fillRect(Y,B-3,Z,3)}}S.fillStyle=this.prefs.color}if(L==="Filled"){if(I){S.lineTo(Y,ac);S.lineTo(0,ac)}S.fill()}else{S.stroke()}S.restore()};var m=function(y){this.feature_positions={};this.slot_height=y;this.translation=0;this.y_translation=0};m.prototype.map_feature_data=function(z,B,y,A){if(!this.feature_positions[B]){this.feature_positions[B]=[]}this.feature_positions[B].push({data:z,x_start:y,x_end:A})};m.prototype.get_feature_data=function(z,D){var C=Math.floor((D-this.y_translation)/this.slot_height),B;if(!this.feature_positions[C]){return null}z+=this.translation;for(var A=0;A<this.feature_positions[C].length;A++){B=this.feature_positions[C][A];if(z>=B.x_start&&z<=B.x_end){return B.data}}};var o=function(A,D,y,z,C,E,B){l.call(this,A,D,y,z,C);this.alpha_scaler=(E?E:new d());this.height_scaler=(B?B:new d())};o.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};u(o.prototype,{get_required_height:function(A,z){var y=y_scale=this.get_row_height(),B=this.mode;if(B==="no_detail"||B==="Squish"||B==="Pack"){y=A*y_scale}return y+this.get_top_padding(z)+this.get_bottom_padding(z)},get_top_padding:function(y){return 0},get_bottom_padding:function(y){return Math.max(Math.round(this.get_row_height()/2),5)},draw:function(K,I,G,E,F){var Q=this.data,D=this.view_start,M=this.view_end;K.save();K.fillStyle=this.prefs.block_color;K.textAlign="right";var H=this.view_end-this.view_start,L=this.get_row_height(),P=new m(L),B;for(var N=0,O=Q.length;N<O;N++){var A=Q[N],C=A[0],J=A[1],y=A[2],z=(F&&F[C]!==undefined?F[C]:null);if((J<M&&y>D)&&(this.mode==="Dense"||z!==null)){B=this.draw_element(K,this.mode,A,z,D,M,E,L,I);P.map_feature_data(A,z,B[0],B[1])}}K.restore();P.y_translation=this.get_top_padding(I);return P},draw_element:function(E,A,G,C,B,D,F,z,y){console.log("WARNING: Unimplemented function.");return[0,0]}});var c=10,h=3,k=5,w=10,f=1,s=9,e=3,a=9,j=2,g="#ccc";var r=function(A,D,y,z,C,E,B){o.call(this,A,D,y,z,C,E,B);this.draw_background_connector=true;this.draw_individual_connectors=false};u(r.prototype,o.prototype,{get_row_height:function(){var z=this.mode,y;if(z==="Dense"){y=c}else{if(z==="no_detail"){y=h}else{if(z==="Squish"){y=k}else{y=w}}}return y},draw_element:function(M,D,X,H,O,ai,am,ao,y){var T=X[0],ak=X[1],ad=X[2]-1,Q=X[3],K=X[4],ae=Math.floor(Math.max(0,(ak-O)*am)),N=Math.ceil(Math.min(y,Math.max(0,(ad-O)*am))),ac=ae,an=N,aa=(D==="Dense"?0:(0+H))*ao+this.get_top_padding(y),L,ag,R=null,aq=null,B=B=(!K||K==="+"||K==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;M.globalAlpha=this.alpha_scaler.gen_val(X);if(D==="Dense"){H=1}if(D==="no_detail"){M.fillStyle=B;M.fillRect(ae,aa+5,N-ae,f)}else{var Z=X[5],af=X[6],C=X[7],V=true;if(Z&&af){R=Math.floor(Math.max(0,(Z-O)*am));aq=Math.ceil(Math.min(y,Math.max(0,(af-O)*am)))}var al,U;if(D==="Squish"){al=1;U=e;V=false}else{if(D==="Dense"){al=5;U=s}else{al=5;U=a}}if(!C){M.fillStyle=B;M.fillRect(ae,aa+1,N-ae,U);if(K&&V){if(K==="+"){M.fillStyle=M.canvas.manager.get_pattern("right_strand_inv")}else{if(K==="-"){M.fillStyle=M.canvas.manager.get_pattern("left_strand_inv")}}M.fillRect(ae,aa+1,N-ae,U)}}else{var J,W;if(D==="Squish"||D==="Dense"){J=aa+Math.floor(e/2)+1;W=1}else{if(K){J=aa;W=U}else{J+=(e/2)+1;W=1}}if(this.draw_background_connector){if(D==="Squish"||D==="Dense"){M.fillStyle=g}else{if(K){if(K==="+"){M.fillStyle=M.canvas.manager.get_pattern("right_strand")}else{if(K==="-"){M.fillStyle=M.canvas.manager.get_pattern("left_strand")}}}else{M.fillStyle=g}}M.fillRect(ae,J,N-ae,W)}var E;for(var aj=0,A=C.length;aj<A;aj++){var F=C[aj],z=Math.floor(Math.max(0,(F[0]-O)*am)),Y=Math.ceil(Math.min(y,Math.max((F[1]-1-O)*am))),S,ab;if(z>Y){continue}M.fillStyle=B;M.fillRect(z,aa+(U-al)/2+1,Y-z,al);if(R!==undefined&&af>Z&&!(z>aq||Y<R)){var ah=Math.max(z,R),I=Math.min(Y,aq);M.fillRect(ah,aa+1,I-ah,U)}if(this.draw_individual_connectors&&S){this.draw_connector(M,S,ab,z,Y,aa)}S=z;ab=Y}if(D==="Pack"){M.globalAlpha=1;M.fillStyle="white";var G=this.height_scaler.gen_val(X),P=Math.ceil(U*G),ap=Math.round((U-P)/2);if(G!==1){M.fillRect(ae,J+1,N-ae,ap);M.fillRect(ae,J+U-ap+1,N-ae,ap)}}}M.globalAlpha=1;if(D==="Pack"&&ak>O){M.fillStyle=label_color;if(O===0&&ae-M.measureText(Q).width<0){M.textAlign="left";M.fillText(Q,N+j,aa+8);an+=M.measureText(Q).width+j}else{M.textAlign="right";M.fillText(Q,ae-j,aa+8);ac-=M.measureText(Q).width+j}}}M.globalAlpha=1;return[ac,an]}});var t=function(B,E,y,A,D,F,C,z){o.call(this,B,E,y,A,D,F,C);this.ref_seq=(z?z.data:null)};u(t.prototype,o.prototype,{get_row_height:function(){var y,z=this.mode;if(z==="Dense"){y=c}else{if(z==="Squish"){y=k}else{y=w;if(this.prefs.show_insertions){y*=2}}}return y},draw_read:function(K,A,ag,V,L,aa,ad,C,B,M){K.textAlign="center";var J=this,R=[L,aa],Z=0,W=0,D=0,F=K.canvas.manager.char_width_px,y=(B==="+"?this.prefs.block_color:this.prefs.reverse_strand_color);var O=[];if((A==="Pack"||this.mode==="Auto")&&M!==undefined&&ag>F){D=Math.round(ag/2)}if(!C){C=[[0,M.length]]}for(var G=0,I=C.length;G<I;G++){var z=C[G],E="MIDNSHP=X"[z[0]],S=z[1];if(E==="H"||E==="S"){Z-=S}var U=ad+Z,Y=Math.floor(Math.max(0,(U-L)*ag)),ab=Math.floor(Math.max(0,(U+S-L)*ag));if(Y===ab){ab+=1}switch(E){case"H":break;case"S":case"M":case"=":if(is_overlap([U,U+S],R)){var N=M.slice(W,W+S);if(D>0){K.fillStyle=y;K.fillRect(Y-D,V+1,ab-Y,9);K.fillStyle=g;for(var af=0,H=N.length;af<H;af++){if(this.prefs.show_differences){if(this.ref_seq){var P=this.ref_seq[U-L+af];if(!P||P.toLowerCase()===N[af].toLowerCase()){continue}}else{continue}}if(U+af>=L&&U+af<=aa){var X=Math.floor(Math.max(0,(U+af-L)*ag));K.fillText(N[af],X,V+9)}}}else{K.fillStyle=y;K.fillRect(Y,V+4,ab-Y,e)}}W+=S;Z+=S;break;case"N":K.fillStyle=g;K.fillRect(Y-D,V+5,ab-Y,1);Z+=S;break;case"D":K.fillStyle="red";K.fillRect(Y-D,V+4,ab-Y,3);Z+=S;break;case"P":break;case"I":var ah=Y-D;if(is_overlap([U,U+S],R)){var N=M.slice(W,W+S);if(this.prefs.show_insertions){var T=Y-(ab-Y)/2;if((A==="Pack"||this.mode==="Auto")&&M!==undefined&&ag>F){K.fillStyle="yellow";K.fillRect(T-D,V-9,ab-Y,9);O[O.length]={type:"triangle",data:[ah,V+4,5]};K.fillStyle=g;switch(compute_overlap([U,U+S],R)){case (OVERLAP_START):N=N.slice(L-U);break;case (OVERLAP_END):N=N.slice(0,U-aa);break;case (CONTAINED_BY):break;case (CONTAINS):N=N.slice(L-U,U-aa);break}for(var af=0,H=N.length;af<H;af++){var X=Math.floor(Math.max(0,(U+af-L)*ag));K.fillText(N[af],X-(ab-Y)/2,V)}}else{K.fillStyle="yellow";K.fillRect(T,V+(this.mode!=="Dense"?2:5),ab-Y,(A!=="Dense"?e:s))}}else{if((A==="Pack"||this.mode==="Auto")&&M!==undefined&&ag>F){O.push({type:"text",data:[N.length,ah,V+9]})}else{}}}W+=S;break;case"X":W+=S;break}}K.fillStyle="yellow";var Q,ai,ae;for(var ac=0;ac<O.length;ac++){Q=O[ac];ai=Q.type;ae=Q.data;if(ai==="text"){K.save();K.font="bold "+K.font;K.fillText(ae[0],ae[1],ae[2]);K.restore()}else{if(ai==="triangle"){q(K,ae[0],ae[1],ae[2])}}}},draw_element:function(R,M,E,B,U,z,I,S,P){var H=E[0],Q=E[1],A=E[2],J=E[3],D=Math.floor(Math.max(0,(Q-U)*I)),F=Math.ceil(Math.min(P,Math.max(0,(A-U)*I))),C=(M==="Dense"?0:(0+B))*S,G=this.prefs.label_color,O=0;if((M==="Pack"||this.mode==="Auto")&&I>R.canvas.manager.char_width_px){var O=Math.round(I/2)}if(E[5] instanceof Array){var N=Math.floor(Math.max(0,(E[4][0]-U)*I)),L=Math.ceil(Math.min(P,Math.max(0,(E[4][1]-U)*I))),K=Math.floor(Math.max(0,(E[5][0]-U)*I)),y=Math.ceil(Math.min(P,Math.max(0,(E[5][1]-U)*I)));if(E[4][1]>=U&&E[4][0]<=z&&E[4][2]){this.draw_read(R,M,I,C,U,z,E[4][0],E[4][2],E[4][3],E[4][4])}if(E[5][1]>=U&&E[5][0]<=z&&E[5][2]){this.draw_read(R,M,I,C,U,z,E[5][0],E[5][2],E[5][3],E[5][4])}if(K>L){R.fillStyle=g;p(R,L-O,C+5,K-O,C+5)}}else{this.draw_read(R,M,I,C,U,z,Q,E[4],E[5],E[6])}if(M==="Pack"&&Q>U&&J!=="."){R.fillStyle=this.prefs.label_color;var T=1;if(T===0&&D-R.measureText(J).width<0){R.textAlign="left";R.fillText(J,F+j-O,C+8)}else{R.textAlign="right";R.fillText(J,D-j-O,C+8)}}return[0,0]}});var n=function(A,D,y,z,C,E,B){r.call(this,A,D,y,z,C,E,B);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};u(n.prototype,o.prototype,r.prototype,{calculate_longest_feature_length:function(){var z=0;for(var C=0,y=this.data.length;C<y;C++){var B=this.data[C],A=B[1],D=B[2];z=Math.max(z,D-A)}return z},get_top_padding:function(z){var y=this.view_end-this.view_start,A=z/y;return Math.min(128,Math.ceil((this.longest_feature_length/2)*A))},draw_connector:function(G,B,F,H,E,D){var y=(F+H)/2,C=H-y;var A=Math.PI,z=0;if(C>0){G.beginPath();G.arc(y,D,H-y,Math.PI,0);G.stroke()}}});x.Scaler=d;x.SummaryTreePainter=v;x.LinePainter=b;x.LinkedFeaturePainter=r;x.ReadPainter=t;x.ArcLinkedFeaturePainter=n};(function(d){var c={};var b=function(e){return c[e]};var a=function(f,g){var e={};g(b,e);c[f]=e};a("class",class_module);a("slotting",slotting_module);a("painters",painters_module);a("trackster",trackster_module);for(key in c.trackster){d[key]=c.trackster[key]}})(window);
\ No newline at end of file
+var class_module=function(b,a){var c=function(){var g=arguments[0];for(var f=1;f<arguments.length;f++){var d=arguments[f];for(var e in d){g[e]=d[e]}}return g};a.extend=c};var requestAnimationFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b,a){window.setTimeout(b,1000/60)}})();var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=BEFORE}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var is_deferred=function(a){if(a==="pending"){console.log("pending")}return("isResolved" in a)};var get_random_color=function(a){if(!a){a="#ffffff"}if(typeof(a)==="string"){a=[a]}for(var j=0;j<a.length;j++){a[j]=parseInt(a[j].slice(1),16)}var n=function(t,s,i){return((t*299)+(s*587)+(i*114))/1000};var e=function(v,u,w,s,i,t){return(Math.max(v,s)-Math.min(v,s))+(Math.max(u,i)-Math.min(u,i))+(Math.max(w,t)-Math.min(w,t))};var g,o,f,k,q,h,r,c,d,b,p,m=false,l=0;do{g=Math.round(Math.random()*16777215);o=(g&16711680)>>16;f=(g&65280)>>8;k=g&255;d=n(o,f,k);m=true;for(j=0;j<a.length;j++){q=a[j];h=(q&16711680)>>16;r=(q&65280)>>8;c=q&255;b=n(h,r,c);p=e(o,f,k,h,r,c);if((Math.abs(d-b)<40)||(p<200)){m=false;break}}l++}while(!m&&l<=10);return"#"+(16777216+g).toString(16).substr(1,6)};var create_action_icon=function(c,b,a){return $("<a/>").attr("href","javascript:void(0);").attr("title",c).addClass("icon-button").addClass(b).tipsy({gravity:"s"}).click(a)};var trackster_module=function(d,R){var o=d("class").extend,r=d("slotting"),H=d("painters");var m={};var k=function(Y,Z){m[Y.attr("id")]=Z};var l=function(Y,aa,ac,ab){ac=".group";var Z={};m[Y.attr("id")]=ab;Y.bind("drag",{handle:"."+aa,relative:true},function(ak,al){var aj=$(this),ao=$(this).parent(),ag=ao.children(),ai=m[$(this).attr("id")],af,ae,am,ad,ah;ae=$(this).parents(ac);if(ae.length!==0){am=ae.position().top;ad=am+ae.outerHeight();if(al.offsetY<am){$(this).insertBefore(ae);var an=m[ae.attr("id")];an.remove_drawable(ai);an.container.add_drawable_before(ai,an);return}else{if(al.offsetY>ad){$(this).insertAfter(ae);var an=m[ae.attr("id")];an.remove_drawable(ai);an.container.add_drawable(ai);return}}}ae=null;for(ah=0;ah<ag.length;ah++){af=$(ag.get(ah));am=af.position().top;ad=am+af.outerHeight();if(af.is(ac)&&this!==af.get(0)&&al.offsetY>=am&&al.offsetY<=ad){if(al.offsetY-am<ad-al.offsetY){af.find(".content-div").prepend(this)}else{af.find(".content-div").append(this)}if(ai.container){ai.container.remove_drawable(ai)}m[af.attr("id")].add_drawable(ai);return}}for(ah=0;ah<ag.length;ah++){af=$(ag.get(ah));if(al.offsetY<af.position().top&&!(af.hasClass("reference-track")||af.hasClass("intro"))){break}}if(ah===ag.length){if(this!==ag.get(ah-1)){ao.append(this);m[ao.attr("id")].move_drawable(ai,ah)}}else{if(this!==ag.get(ah)){$(this).insertBefore(ag.get(ah));m[ao.attr("id")].move_drawable(ai,(al.deltaY>0?ah-1:ah))}}}).bind("dragstart",function(){Z["border-top"]=Y.css("border-top");Z["border-bottom"]=Y.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(Z)})};R.moveable=l;var X=16,C=9,z=20,w=100,E=12000,O=400,G=5000,t=100,n="There was an error in indexing this dataset. ",F="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",A="No data for this chrom/contig.",s="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",u="Tool cannot be rerun: ",a="Loading data...",S="Ready for display",M=10,D=20;function T(Z,Y){if(!Y){Y=0}var aa=Math.pow(10,Y);return Math.round(Z*aa)/aa}var p=function(Z,Y,ab){if(!p.id_counter){p.id_counter=0}this.id=p.id_counter++;this.name=ab.name;this.view=Z;this.container=Y;this.config=new B({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:ab.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=ab.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(ac){ac.stopPropagation()});var aa=this;this.container_div.hover(function(){aa.icons_div.show()},function(){aa.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};p.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(Y){if(Y.content_visible){Y.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");Y.hide_contents();Y.content_visible=false}else{Y.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");Y.content_visible=true;Y.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(Z){var ab=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},Y=function(){Z.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},aa=function(ac){if((ac.keyCode||ac.which)===27){ab()}else{if((ac.keyCode||ac.which)===13){Y()}}};$(window).bind("keypress.check_enter_esc",aa);show_modal("Configure",Z.config.build_form(),{Cancel:ab,OK:Y})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(Y){$(".tipsy").remove();Y.remove()}}];o(p.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(){},to_dict:function(){},set_name:function(Y){this.old_name=this.name;this.name=Y;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 Y=this.view;this.container_div.hide(0,function(){$(this).remove();Y.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(Z,ae,ad,ac,Y,ab){var aa=this;this.action_icons[Z]=$("<a/>").attr("href","javascript:void(0);").attr("title",ae).addClass("icon-button").addClass(ad).tipsy({gravity:"s"}).click(function(){ac(aa)}).appendTo(this.icons_div);if(ab){this.action_icons[Z].hide()}},build_action_icons:function(Y){var aa;for(var Z=0;Z<Y.length;Z++){aa=Y[Z];this.add_action_icon(aa.name,aa.title,aa.css_class,aa.on_click_fn,aa.prepend,aa.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){}});var v=function(Z,Y,aa){p.call(this,Z,Y,aa);this.obj_type=aa.obj_type;this.drawables=[]};o(v.prototype,p.prototype,{unpack_drawables:function(aa){this.drawables=[];var Z;for(var Y=0;Y<aa.length;Y++){Z=object_from_template(aa[Y],this);this.add_drawable(Z)}},init:function(){for(var Y=0;Y<this.drawables.length;Y++){this.drawables[Y].init()}},_draw:function(){for(var Y=0;Y<this.drawables.length;Y++){this.drawables[Y]._draw()}},to_dict:function(){var Z=[];for(var Y=0;Y<this.drawables.length;Y++){Z.push(this.drawables[Y].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:Z}},add_drawable:function(Y){this.drawables.push(Y);Y.container=this;this.changed()},add_drawable_before:function(aa,Y){this.changed();var Z=this.drawables.indexOf(Y);if(Z!==-1){this.drawables.splice(Z,0,aa);return true}return false},replace_drawable:function(aa,Y,Z){var ab=this.drawables.indexOf(aa);if(ab!==-1){this.drawables[ab]=Y;if(Z){aa.container_div.replaceWith(Y.container_div)}this.changed()}return ab},remove_drawable:function(Z){var Y=this.drawables.indexOf(Z);if(Y!==-1){this.drawables.splice(Y,1);Z.container=null;this.changed();return true}return false},move_drawable:function(Z,aa){var Y=this.drawables.indexOf(Z);if(Y!==-1){this.drawables.splice(Y,1);this.drawables.splice(aa,0,Z);this.changed();return true}return false}});var L=function(Z,Y,ab){o(ab,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});v.call(this,Z,Y,ab);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);k(this.container_div,this);k(this.content_div,this);l(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new U(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in ab){this.unpack_drawables(ab.drawables)}if("filters" in ab){var aa=this.filters_manager;this.filters_manager=new U(this,ab.filters);aa.parent_div.replaceWith(this.filters_manager.parent_div);if(ab.filters.visible){this.setup_multitrack_filtering()}}};o(L.prototype,p.prototype,v.prototype,{action_icons_def:[p.prototype.action_icons_def[0],p.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(Y){$(".tipsy").remove();Y.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(Y){if(Y.filters_manager.visible()){Y.filters_manager.clear_filters();Y._restore_filter_managers()}else{Y.setup_multitrack_filtering();Y.request_draw(true)}Y.filters_manager.toggle()}},p.prototype.action_icons_def[2]],build_container_div:function(){var Y=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(Y)}return Y},build_header_div:function(){var Y=$("<div/>").addClass("track-header");Y.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(Y);return Y},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var aa=this.drawables.length;if(aa===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(aa===1){if(this.drawables[0] instanceof g){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var ah,ag,ae,ak=true,ac=this.drawables[0].get_type(),Y=0;for(ah=0;ah<aa;ah++){ae=this.drawables[ah];if(ae.get_type()!==ac){can_composite=false;break}if(ae instanceof c){Y++}}if(ak||Y===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".tipsy").remove()}if(Y>1&&Y===this.drawables.length){var al={},Z;ae=this.drawables[0];for(ag=0;ag<ae.filters_manager.filters.length;ag++){Z=ae.filters_manager.filters[ag];al[Z.name]=[Z]}for(ah=1;ah<this.drawables.length;ah++){ae=this.drawables[ah];for(ag=0;ag<ae.filters_manager.filters.length;ag++){Z=ae.filters_manager.filters[ag];if(Z.name in al){al[Z.name].push(Z)}}}this.filters_manager.remove_all();var ab,ad,af,ai;for(var aj in al){ab=al[aj];if(ab.length===Y){ad=new P({name:ab[0].name,index:ab[0].index});this.filters_manager.add_filter(ad)}}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 Y=0;Y<this.drawables.length;Y++){this.drawables[Y].filters_manager=this.saved_filters_managers[Y]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var Y=0;Y<this.drawables.length;Y++){drawable=this.drawables[Y];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var ac=[];for(var Z=0;Z<this.drawables.length;Z++){ac.push(this.drawables[Z].name)}var aa="Composite Track of "+this.drawables.length+" tracks ("+ac.join(", ")+")";var ab=new g(this.view,this.view,{name:aa,drawables:this.drawables});var Y=this.container.replace_drawable(this,ab,true);ab.request_draw()},add_drawable:function(Y){v.prototype.add_drawable.call(this,Y);this.update_icons()},remove_drawable:function(Y){v.prototype.remove_drawable.call(this,Y);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var Y=o(v.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return Y},request_draw:function(Y,aa){for(var Z=0;Z<this.drawables.length;Z++){this.drawables[Z].request_draw(Y,aa)}}});var W=function(Y){o(Y,{obj_type:"View"});v.call(this,"View",Y.container,Y);this.chrom=null;this.vis_id=Y.vis_id;this.dbkey=Y.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.init();this.canvas_manager=new CanvasManager(this.container.get(0).ownerDocument);this.reset()};_.extend(W.prototype,Backbone.Events);o(W.prototype,v.prototype,{init:function(){this.requested_redraw=false;var aa=this.container,Y=this;this.top_container=$("<div/>").addClass("top-container").appendTo(aa);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(aa);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(aa);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.browser_content_div);this.content_div=this.viewport_container;k(this.viewport_container,Y);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var ab=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_datasets(add_datasets_url,add_track_async_url,function(ac){_.each(ac,function(ad){Y.add_drawable(object_from_template(ad,Y))})})});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").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var Z=function(ac){if(ac.type==="focusout"||(ac.keyCode||ac.which)===13||(ac.keyCode||ac.which)===27){if((ac.keyCode||ac.which)!==27){Y.go_to($(this).val())}$(this).hide();$(this).val("");Y.location_span.show();Y.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",Z).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").attr("original-title","Click to change location").tipsy({gravity:"n"}).appendTo(this.nav_controls);this.location_span.click(function(){Y.location_span.hide();Y.chrom_select.hide();Y.nav_input.val(Y.chrom+":"+Y.low+"-"+Y.high);Y.nav_input.css("display","inline-block");Y.nav_input.select();Y.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a/>").attr("id","zoom-out").attr("title","Zoom out").tipsy({gravity:"n"}).click(function(){Y.zoom_out();Y.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tipsy({gravity:"n"}).click(function(){Y.zoom_in();Y.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){Y.change_chrom(Y.chrom_select.val())});this.browser_content_div.click(function(ac){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ac){Y.zoom_in(ac.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ac,ad){this.current_x=ad.offsetX}).bind("drag",function(ac,ae){var af=ae.offsetX-this.current_x;this.current_x=ae.offsetX;var ad=Math.round(af/Y.viewport_container.width()*(Y.max_high-Y.max_low));Y.move_delta(-ad)});this.overview_close.click(function(){Y.reset_overview()});this.viewport_container.bind("draginit",function(ac,ad){if(ac.clientX>Y.viewport_container.width()-16){return false}}).bind("dragstart",function(ac,ad){ad.original_low=Y.low;ad.current_height=ac.clientY;ad.current_x=ad.offsetX}).bind("drag",function(ae,ag){var ac=$(this);var ah=ag.offsetX-ag.current_x;var ad=ac.scrollTop()-(ae.clientY-ag.current_height);ac.scrollTop(ad);ag.current_height=ae.clientY;ag.current_x=ag.offsetX;var af=Math.round(ah/Y.viewport_container.width()*(Y.high-Y.low));Y.move_delta(af)}).bind("mousewheel",function(ae,ag,ad,ac){if(ad){ad*=50;var af=Math.round(-ad/Y.viewport_container.width()*(Y.high-Y.low));Y.move_delta(af)}});this.top_labeltrack.bind("dragstart",function(ac,ad){return $("<div />").css({height:Y.browser_content_div.height()+Y.top_labeltrack.height()+Y.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ag,ah){$(ah.proxy).css({left:Math.min(ag.pageX,ah.startX)-Y.container.offset().left,width:Math.abs(ag.pageX-ah.startX)});var ad=Math.min(ag.pageX,ah.startX)-Y.container.offset().left,ac=Math.max(ag.pageX,ah.startX)-Y.container.offset().left,af=(Y.high-Y.low),ae=Y.viewport_container.width();Y.update_location(Math.round(ad/ae*af)+Y.low,Math.round(ac/ae*af)+Y.low)}).bind("dragend",function(ah,ai){var ad=Math.min(ah.pageX,ai.startX),ac=Math.max(ah.pageX,ai.startX),af=(Y.high-Y.low),ae=Y.viewport_container.width(),ag=Y.low;Y.low=Math.round(ad/ae*af)+ag;Y.high=Math.round(ac/ae*af)+ag;$(ai.proxy).remove();Y.request_redraw()});this.add_label_track(new V(this,{content_div:this.top_labeltrack}));this.add_label_track(new V(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){Y.resize_window()},500)});$(document).bind("redraw",function(){Y.redraw()});this.reset();$(window).trigger("resize")},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(Z,ab,Y,ac){if(this.timer){clearTimeout(this.timer)}if(ac){var aa=this;this.timer=setTimeout(function(){aa.trigger("navigate",Z+":"+ab+"-"+Y)},500)}else{view.trigger("navigate",Z+":"+ab+"-"+Y)}},update_location:function(Y,aa){this.location_span.text(commatize(Y)+" - "+commatize(aa));this.nav_input.val(this.chrom+":"+commatize(Y)+"-"+commatize(aa));var Z=view.chrom_select.val();if(Z!==""){this.trigger_navigate(Z,view.low,view.high,true)}},load_chroms:function(aa){aa.num=t;aa.dbkey=this.dbkey;var Y=this,Z=$.Deferred();$.ajax({url:chrom_url,data:aa,dataType:"json",success:function(ac){if(ac.chrom_info.length===0){alert("Invalid chromosome: "+aa.chrom);return}if(ac.reference){Y.add_label_track(new x(Y))}Y.chrom_data=ac.chrom_info;var af='<option value="">Select Chrom/Contig</option>';for(var ae=0,ab=Y.chrom_data.length;ae<ab;ae++){var ad=Y.chrom_data[ae].chrom;af+='<option value="'+ad+'">'+ad+"</option>"}if(ac.prev_chroms){af+='<option value="previous">Previous '+t+"</option>"}if(ac.next_chroms){af+='<option value="next">Next '+t+"</option>"}Y.chrom_select.html(af);Y.chrom_start_index=ac.start_index;Z.resolve(ac)},error:function(){alert("Could not load chroms for this dbkey:",Y.dbkey)}});return Z},change_chrom:function(ad,Z,af){var aa=this;if(!aa.chrom_data){aa.load_chroms_deferred.then(function(){aa.change_chrom(ad,Z,af)});return}if(!ad||ad==="None"){return}if(ad==="previous"){aa.load_chroms({low:this.chrom_start_index-t});return}if(ad==="next"){aa.load_chroms({low:this.chrom_start_index+t});return}var ae=$.grep(aa.chrom_data,function(ag,ah){return ag.chrom===ad})[0];if(ae===undefined){aa.load_chroms({chrom:ad},function(){aa.change_chrom(ad,Z,af)});return}else{if(ad!==aa.chrom){aa.chrom=ad;aa.chrom_select.val(aa.chrom);aa.max_high=ae.len-1;aa.reset();aa.request_redraw(true);for(var ac=0,Y=aa.drawables.length;ac<Y;ac++){var ab=aa.drawables[ac];if(ab.init){ab.init()}}if(aa.reference_track){aa.reference_track.init()}}if(Z!==undefined&&af!==undefined){aa.low=Math.max(Z,0);aa.high=Math.min(af,aa.max_high)}else{aa.low=0;aa.high=aa.max_high}aa.reset_overview();aa.request_redraw()}},go_to:function(ac){ac=ac.replace(/ |,/g,"");var ag=this,Y,ab,Z=ac.split(":"),ae=Z[0],af=Z[1];if(af!==undefined){try{var ad=af.split("-");Y=parseInt(ad[0],10);ab=parseInt(ad[1],10)}catch(aa){return false}}ag.change_chrom(ae,Y,ab)},move_fraction:function(aa){var Y=this;var Z=Y.high-Y.low;this.move_delta(aa*Z)},move_delta:function(ab){var Y=this;var aa=Y.high-Y.low;if(Y.low-ab<Y.max_low){Y.low=Y.max_low;Y.high=Y.max_low+aa}else{if(Y.high-ab>Y.max_high){Y.high=Y.max_high;Y.low=Y.max_high-aa}else{Y.high-=ab;Y.low-=ab}}Y.request_redraw();var Z=Y.chrom_select.val();this.trigger_navigate(Z,Y.low,Y.high,true)},add_drawable:function(Y){v.prototype.add_drawable.call(this,Y);Y.init();this.changed();this.update_intro_div()},add_label_track:function(Y){Y.view=this;Y.init();this.label_tracks.push(Y)},remove_drawable:function(aa,Z){v.prototype.remove_drawable.call(this,aa);if(Z){var Y=this;aa.container_div.hide(0,function(){$(this).remove();Y.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ag,Y,af,ah){var ae=this,ad=(ah?[ah]:ae.drawables),aa;var Z;for(var ac=0;ac<ad.length;ac++){Z=ad[ac];aa=-1;for(var ab=0;ab<ae.tracks_to_be_redrawn.length;ab++){if(ae.tracks_to_be_redrawn[ab][0]===Z){aa=ab;break}}if(aa<0){ae.tracks_to_be_redrawn.push([Z,Y,af])}else{ae.tracks_to_be_redrawn[ac][1]=Y;ae.tracks_to_be_redrawn[ac][2]=af}}if(!this.requested_redraw){requestAnimationFrame(function(){ae._redraw(ag)});this.requested_redraw=true}},_redraw:function(ai){this.requested_redraw=false;var af=this.low,ab=this.high;if(af<this.max_low){af=this.max_low}if(ab>this.max_high){ab=this.max_high}var ah=this.high-this.low;if(this.high!==0&&ah<this.min_separation){ab=af+this.min_separation}this.low=Math.floor(af);this.high=Math.ceil(ab);this.update_location(this.low,this.high);this.resolution_b_px=(this.high-this.low)/this.viewport_container.width();this.resolution_px_b=this.viewport_container.width()/(this.high-this.low);var Y=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ae=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var aj=13;this.overview_box.css({left:Y,width:Math.max(aj,ae)}).show();if(ae<aj){this.overview_box.css("left",Y-(aj-ae)/2)}if(this.overview_highlight){this.overview_highlight.css({left:Y,width:ae})}if(!ai){var aa,Z,ag;for(var ac=0,ad=this.tracks_to_be_redrawn.length;ac<ad;ac++){aa=this.tracks_to_be_redrawn[ac][0];Z=this.tracks_to_be_redrawn[ac][1];ag=this.tracks_to_be_redrawn[ac][2];if(aa){aa._draw(Z,ag)}}this.tracks_to_be_redrawn=[];for(ac=0,ad=this.label_tracks.length;ac<ad;ac++){this.label_tracks[ac]._draw()}}},zoom_in:function(Z,aa){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var ab=this.high-this.low,ac=ab/2+this.low,Y=(ab/this.zoom_factor)/2;if(Z){ac=Z/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ac-Y);this.high=Math.round(ac+Y);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var Z=this.high-this.low,aa=Z/2+this.low,Y=(Z*this.zoom_factor)/2;this.low=Math.round(aa-Y);this.high=Math.round(aa+Y);this.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(aa){if(this.overview_drawable){if(this.overview_drawable.dataset_id===aa.dataset_id){return}this.overview_viewport.find(".track").remove()}var Z=aa.copy({content_div:this.overview_viewport}),Y=this;Z.header_div.hide();Z.is_overview=true;Y.overview_drawable=Z;this.overview_drawable.postdraw_actions=function(){Y.overview_highlight.show().height(Y.overview_drawable.content_div.height());Y.overview_viewport.height(Y.overview_drawable.content_div.height()+Y.overview_box.outerHeight());Y.overview_close.show();Y.resize_window()};Y.overview_drawable.request_draw();this.changed()},reset_overview:function(){$(".tipsy").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 q=function(aa,af,ab){this.track=aa;this.name=af.name;this.params=[];var am=af.params;for(var ac=0;ac<am.length;ac++){var ah=am[ac],Z=ah.name,al=ah.label,ad=unescape(ah.html),an=ah.value,aj=ah.type;if(aj==="number"){this.params.push(new e(Z,al,ad,(Z in ab?ab[Z]:an),ah.min,ah.max))}else{if(aj==="select"){this.params.push(new J(Z,al,ad,(Z in ab?ab[Z]:an)))}else{console.log("WARNING: unrecognized tool parameter type:",Z,aj)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(ap){ap.stopPropagation()}).click(function(ap){ap.stopPropagation()}).bind("dblclick",function(ap){ap.stopPropagation()});var ak=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var ai=this.params;var ag=this;$.each(this.params,function(aq,au){var at=$("<div>").addClass("param-row").appendTo(ag.parent_div);var ap=$("<div>").addClass("param-label").text(au.label).appendTo(at);var ar=$("<div/>").addClass("param-input").html(au.html).appendTo(at);ar.find(":input").val(au.value);$("<div style='clear: both;'/>").appendTo(at)});this.parent_div.find("input").click(function(){$(this).select()});var ao=$("<div>").addClass("param-row").appendTo(this.parent_div);var ae=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(ao);var Y=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(ao);Y.click(function(){ag.run_on_region()});ae.click(function(){ag.run_on_dataset()});if("visible" in ab&&ab.visible){this.parent_div.show()}};o(q.prototype,{update_params:function(){for(var Y=0;Y<this.params.length;Y++){this.params[Y].update_value()}},state_dict:function(){var Z={};for(var Y=0;Y<this.params.length;Y++){Z[this.params[Y].name]=this.params[Y].value}Z.visible=this.parent_div.is(":visible");return Z},get_param_values_dict:function(){var Y={};this.parent_div.find(":input").each(function(){var Z=$(this).attr("name"),aa=$(this).val();Y[Z]=aa});return Y},get_param_values:function(){var Y=[];this.parent_div.find(":input").each(function(){var Z=$(this).attr("name"),aa=$(this).val();if(Z){Y[Y.length]=aa}});return Y},run_on_dataset:function(){var Y=this;Y.run({target_dataset_id:this.track.original_dataset_id,tool_id:Y.name},null,function(Z){show_modal(Y.name+" is Running",Y.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var Z={target_dataset_id:this.track.original_dataset_id,action:"rerun",tool_id:this.name,regions:[{chrom:this.track.view.chrom,start:this.track.view.low,end:this.track.view.high}]},ad=this.track,aa=Z.tool_id+ad.tool_region_and_parameters_str(Z.chrom,Z.low,Z.high),Y;if(ad.container===view){var ac=new L(view,view,{name:this.name});var ab=ad.container.replace_drawable(ad,ac,false);ac.container_div.insertBefore(ad.view.content_div.children()[ab]);ac.add_drawable(ad);ad.container_div.appendTo(ac.content_div);Y=ac}else{Y=ad.container}var ae=new ad.constructor(view,Y,{name:aa,hda_ldda:"hda"});ae.init_for_tool_data();ae.change_mode(ad.mode);ae.set_filters_manager(ad.filters_manager.copy(ae));ae.update_icons();Y.add_drawable(ae);ae.tiles_div.text("Starting job.");this.update_params();this.run(Z,ae,function(af){ae.set_dataset(new Dataset(af));ae.tiles_div.text("Running job.");ae.init()})},run:function(Y,aa,ab){Y.inputs=this.get_param_values_dict();var Z=new ServerStateDeferred({ajax_settings:{url:galaxy_paths.get("tool_url"),data:JSON.stringify(Y),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ac){return ac!=="pending"}});$.when(Z.go()).then(function(ac){if(ac==="no converter"){aa.container_div.addClass("error");aa.content_div.text(F)}else{if(ac.error){aa.container_div.addClass("error");aa.content_div.text(u+ac.message)}else{ab(ac)}}})}});var J=function(Z,Y,aa,ab){this.name=Z;this.label=Y;this.html=$(aa);this.value=ab};o(J.prototype,{update_value:function(){this.value=$(this.html).val()}});var e=function(aa,Z,ac,ad,ab,Y){J.call(this,aa,Z,ac,ad);this.min=ab;this.max=Y};o(e.prototype,J.prototype,{update_value:function(){J.prototype.update_value.call(this);this.value=parseFloat(this.value)}});var f=function(Y){this.manager=null;this.name=Y.name;this.index=Y.index;this.tool_id=Y.tool_id;this.tool_exp_name=Y.tool_exp_name};o(f.prototype,{to_dict:function(){return{name:this.name,index:this.index,tool_id:this.tool_id,tool_exp_name:this.tool_exp_name}}});var P=function(ah){f.call(this,ah);this.low=("low" in ah?ah.low:-Number.MAX_VALUE);this.high=("high" in ah?ah.high:Number.MAX_VALUE);this.min=("min" in ah?ah.min:Number.MAX_VALUE);this.max=("max" in ah?ah.max:-Number.MAX_VALUE);this.container=null;this.slider=null;this.slider_label=null;var ad=function(ai,aj,ak){ai.click(function(){var ap=aj.text(),an=parseFloat(ak.slider("option","max")),am=(an<=1?4:an<=1000000?an.toString().length:6),ao=false,al=$(this).parents(".slider-row");al.addClass("input");if(ak.slider("option","values")){am=2*am+1;ao=true}aj.text("");$("<input type='text'/>").attr("size",am).attr("maxlength",am).attr("value",ap).appendTo(aj).focus().select().click(function(aq){aq.stopPropagation()}).blur(function(){$(this).remove();aj.text(ap);al.removeClass("input")}).keyup(function(av){if(av.keyCode===27){$(this).trigger("blur")}else{if(av.keyCode===13){var at=ak.slider("option","min"),aq=ak.slider("option","max"),au=function(aw){return(isNaN(aw)||aw>aq||aw<at)},ar=$(this).val();if(!ao){ar=parseFloat(ar);if(au(ar)){alert("Parameter value must be in the range ["+at+"-"+aq+"]");return $(this)}}else{ar=ar.split("-");ar=[parseFloat(ar[0]),parseFloat(ar[1])];if(au(ar[0])||au(ar[1])){alert("Parameter value must be in the range ["+at+"-"+aq+"]");return $(this)}}ak.slider((ao?"values":"value"),ar);al.removeClass("input")}}})})};var Z=this;Z.parent_div=$("<div/>").addClass("filter-row slider-row");var Y=$("<div/>").addClass("elt-label").appendTo(Z.parent_div),af=$("<span/>").addClass("slider-name").text(Z.name+" ").appendTo(Y),aa=$("<span/>").text(this.low+"-"+this.high),ab=$("<span/>").addClass("slider-value").appendTo(Y).append("[").append(aa).append("]");Z.values_span=aa;var ae=$("<div/>").addClass("slider").appendTo(Z.parent_div);Z.control_element=$("<div/>").attr("id",Z.name+"-filter-control").appendTo(ae);var ac=[0,0];Z.control_element.slider({range:true,min:this.min,max:this.max,step:this.get_slider_step(this.min,this.max),values:[this.low,this.high],slide:function(ai,aj){Z.slide(ai,aj)},change:function(ai,aj){Z.control_element.slider("option","slide").call(Z.control_element,ai,aj)}});Z.slider=Z.control_element;Z.slider_label=aa;ad(ab,aa,Z.control_element);var ag=$("<div/>").addClass("display-controls").appendTo(Z.parent_div);this.transparency_icon=create_action_icon("Use filter for data transparency","layer-transparent",function(){if(Z.manager.alpha_filter!==Z){Z.manager.alpha_filter=Z;Z.manager.parent_div.find(".layer-transparent").removeClass("active").hide();Z.transparency_icon.addClass("active").show()}else{Z.manager.alpha_filter=null;Z.transparency_icon.removeClass("active")}Z.manager.track.request_draw(true,true)}).appendTo(ag).hide();this.height_icon=create_action_icon("Use filter for data height","arrow-resize-090",function(){if(Z.manager.height_filter!==Z){Z.manager.height_filter=Z;Z.manager.parent_div.find(".arrow-resize-090").removeClass("active").hide();Z.height_icon.addClass("active").show()}else{Z.manager.height_filter=null;Z.height_icon.removeClass("active")}Z.manager.track.request_draw(true,true)}).appendTo(ag).hide();Z.parent_div.hover(function(){Z.transparency_icon.show();Z.height_icon.show()},function(){if(Z.manager.alpha_filter!==Z){Z.transparency_icon.hide()}if(Z.manager.height_filter!==Z){Z.height_icon.hide()}});$("<div style='clear: both;'/>").appendTo(Z.parent_div)};o(P.prototype,{to_dict:function(){var Y=f.prototype.to_dict.call(this);return o(Y,{type:"number",min:this.min,max:this.max,low:this.low,high:this.high})},copy:function(){return new P({name:this.name,index:this.index,tool_id:this.tool_id,tool_exp_name:this.tool_exp_name})},get_slider_step:function(aa,Y){var Z=Y-aa;return(Z<=2?0.01:1)},slide:function(Z,aa){var Y=aa.values;this.values_span.text(Y[0]+"-"+Y[1]);this.low=Y[0];this.high=Y[1];this.manager.track.request_draw(true,true)},applies_to:function(Y){if(Y.length>this.index){return true}return false},_keep_val:function(Y){return(isNaN(Y)||(Y>=this.low&&Y<=this.high))},keep:function(Z){if(!this.applies_to(Z)){return true}var ab=this;var ac=Z[this.index];if(ac instanceof Array){var aa=true;for(var Y=0;Y<ac.length;Y++){if(!this._keep_val(ac[Y])){aa=false;break}}return aa}else{return this._keep_val(Z[this.index])}},update_attrs:function(ab){var Y=false;if(!this.applies_to(ab)){return Y}var Z=ab[this.index];if(!(Z instanceof Array)){Z=[Z]}for(var aa=0;aa<Z.length;aa++){var ac=Z[aa];if(ac<this.min){this.min=Math.floor(ac);Y=true}if(ac>this.max){this.max=Math.ceil(ac);Y=true}}return Y},update_ui_elt:function(){if(this.min<this.max){this.parent_div.show()}else{this.parent_div.hide()}var Z=this.slider.slider("option","min"),Y=this.slider.slider("option","max");if(this.min<Z||this.max>Y){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",this.get_slider_step(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var U=function(aa,ag){this.track=aa;this.alpha_filter=null;this.height_filter=null;this.filters=[];this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(ai){ai.stopPropagation()}).click(function(ai){ai.stopPropagation()}).bind("dblclick",function(ai){ai.stopPropagation()}).bind("keydown",function(ai){ai.stopPropagation()});if(ag&&"filters" in ag){var Y=("alpha_filter" in ag?ag.alpha_filter:null),ab=("height_filter" in ag?ag.height_filter:null),ad=ag.filters,Z;for(var ae=0;ae<ad.length;ae++){if(ad[ae].type==="number"){Z=new P(ad[ae]);this.add_filter(Z);if(Z.name===Y){this.alpha_filter=Z;Z.transparency_icon.addClass("active").show()}if(Z.name===ab){this.height_filter=Z;Z.height_icon.addClass("active").show()}}else{console.log("ERROR: unsupported filter: ",name,type)}}if("visible" in ag&&ag.visible){this.parent_div.show()}}if(this.filters.length!==0){var ah=$("<div/>").addClass("param-row").appendTo(this.parent_div);var af=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(ah);var ac=this;af.click(function(){ac.run_on_dataset()})}};o(U.prototype,{show:function(){this.parent_div.show()},hide:function(){this.parent_div.hide()},toggle:function(){this.parent_div.toggle()},visible:function(){return this.parent_div.is(":visible")},to_dict:function(){var ab={},aa=[],Z;for(var Y=0;Y<this.filters.length;Y++){Z=this.filters[Y];aa.push(Z.to_dict())}ab.filters=aa;ab.alpha_filter=(this.alpha_filter?this.alpha_filter.name:null);ab.height_filter=(this.height_filter?this.height_filter.name:null);ab.visible=this.parent_div.is(":visible");return ab},copy:function(Z){var aa=new U(Z);for(var Y=0;Y<this.filters.length;Y++){aa.add_filter(this.filters[Y].copy())}return aa},add_filter:function(Y){Y.manager=this;this.parent_div.append(Y.parent_div);this.filters.push(Y)},remove_all:function(){this.filters=[];this.parent_div.children().remove()},init_filters:function(){for(var Y=0;Y<this.filters.length;Y++){var Z=this.filters[Y];Z.update_ui_elt()}},clear_filters:function(){for(var Y=0;Y<this.filters.length;Y++){var Z=this.filters[Y];Z.slider.slider("option","values",[Z.min,Z.max])}this.alpha_filter=null;this.height_filter=null;this.parent_div.find(".icon-button").hide()},run_on_dataset:function(){var ae=function(ai,ag,ah){if(!(ag in ai)){ai[ag]=ah}return ai[ag]};var ad={},af,Y;for(var ac=0;ac<this.filters.length;ac++){af=this.filters[ac];if(af.tool_id){if(af.min!==af.low){Y=ae(ad,af.tool_id,[]);Y[Y.length]=af.tool_exp_name+" >= "+af.low}if(af.max!==af.high){Y=ae(ad,af.tool_id,[]);Y[Y.length]=af.tool_exp_name+" <= "+af.high}}}var Z=[];for(var ab in ad){Z[Z.length]=[ab,ad[ab]]}(function aa(am,aj){var ah=aj[0],ai=ah[0],al=ah[1],ak="("+al.join(") and (")+")",ag={cond:ak,input:am,target_dataset_id:am,tool_id:ai},aj=aj.slice(1);$.getJSON(run_tool_url,ag,function(an){if(an.error){show_modal("Filter Dataset","Error running tool "+ai,{Close:hide_modal})}else{if(aj.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{aa(an.dataset_id,aj)}}})})(this.track.dataset_id,Z)}});var y=function(Y,Z){H.Scaler.call(this,Z);this.filter=Y};y.prototype.gen_val=function(Y){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(Y[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var B=function(Y){this.track=Y.track;this.params=Y.params;this.values={};this.restore_values((Y.saved_values?Y.saved_values:{}));this.onchange=Y.onchange};o(B.prototype,{restore_values:function(Y){var Z=this;$.each(this.params,function(aa,ab){if(Y[ab.key]!==undefined){Z.values[ab.key]=Y[ab.key]}else{Z.values[ab.key]=ab.default_value}})},build_form:function(){var ab=this;var Y=$("<div />");var aa;function Z(af,ac){for(var aj=0;aj<af.length;aj++){aa=af[aj];if(aa.hidden){continue}var ad="param_"+aj;var an=ab.values[aa.key];var aq=$("<div class='form-row' />").appendTo(ac);aq.append($("<label />").attr("for",ad).text(aa.label+":"));if(aa.type==="bool"){aq.append($('<input type="checkbox" />').attr("id",ad).attr("name",ad).attr("checked",an))}else{if(aa.type==="text"){aq.append($('<input type="text"/>').attr("id",ad).val(an).click(function(){$(this).select()}))}else{if(aa.type==="select"){var al=$("<select />").attr("id",ad);for(var ah=0;ah<aa.options.length;ah++){$("<option/>").text(aa.options[ah].label).attr("value",aa.options[ah].value).appendTo(al)}al.val(an);aq.append(al)}else{if(aa.type==="color"){var ap=$("<div/>").appendTo(aq),ak=$("<input />").attr("id",ad).attr("name",ad).val(an).css("float","left").appendTo(ap).click(function(at){$(".tipsy").hide();var ar=$(this).siblings(".tipsy");ar.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(ar).height()/2)+($(this).height()/2)}).show();ar.click(function(au){au.stopPropagation()});$(document).bind("click.color-picker",function(){ar.hide();$(document).unbind("click.color-picker")});at.stopPropagation()}),ai=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(ap).attr("title","Set new random color").tipsy({gravity:"s"}),am=$("<div class='tipsy tipsy-west' style='position: absolute;' />").appendTo(ap).hide(),ae=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(am),ao=$("<div/>").appendTo(ae),ag=$.farbtastic(ao,{width:100,height:100,callback:ak,color:an});ap.append($("<div/>").css("clear","both"));(function(ar){ai.click(function(){ar.setColor(get_random_color())})})(ag)}else{aq.append($("<input />").attr("id",ad).attr("name",ad).val(an))}}}}if(aa.help){aq.append($("<div class='help'/>").text(aa.help))}}}Z(this.params,Y);return Y},update_from_form:function(Y){var aa=this;var Z=false;$.each(this.params,function(ab,ad){if(!ad.hidden){var ae="param_"+ab;var ac=Y.find("#"+ae).val();if(ad.type==="float"){ac=parseFloat(ac)}else{if(ad.type==="int"){ac=parseInt(ac)}else{if(ad.type==="bool"){ac=Y.find("#"+ae).is(":checked")}}}if(ac!==aa.values[ad.key]){aa.values[ad.key]=ac;Z=true}}});if(Z){this.onchange();this.track.changed()}}});var b=function(Y,ac,aa,Z,ab){this.track=Y;this.region=ac;this.low=ac.get("start");this.high=ac.get("end");this.resolution=aa;this.html_elt=$("<div class='track-tile'/>").append(Z).height($(Z).attr("height"));this.data=ab;this.stale=false};b.prototype.predisplay_actions=function(){};var j=function(Y,ad,aa,Z,ab,ac){b.call(this,Y,ad,aa,Z,ab);this.max_val=ac};o(j.prototype,b.prototype);var K=function(ab,aj,ac,aa,ae,al,af,am,Z,ai){b.call(this,ab,aj,ac,aa,ae);this.mode=af;this.all_slotted=Z;this.feature_mapper=ai;this.has_icons=false;if(am){this.has_icons=true;var ag=this;aa=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:z-1,width:aa.width}).prependTo(this.html_elt);var ah=new GenomeRegion({chrom:ab.view.chrom,start:this.low,end:this.high}),ak=ae.length,ad=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ak+" features in this region were obtained from server. Click to get more data including depth").tipsy({gravity:"s"}).appendTo(message_div),Y=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ak+" features in this region were obtained from server. Click to get more data excluding depth").tipsy({gravity:"s"}).appendTo(message_div);ad.click(function(){ag.stale=true;ab.data_manager.get_more_data(ah,ab.mode,ag.resolution,{},ab.data_manager.DEEP_DATA_REQ);$(".tipsy").hide();ab.request_draw(true)}).dblclick(function(an){an.stopPropagation()});Y.click(function(){ag.stale=true;ab.data_manager.get_more_data(ah,ab.mode,ag.resolution,{},ab.data_manager.BROAD_DATA_REQ);$(".tipsy").hide();ab.request_draw(true)}).dblclick(function(an){an.stopPropagation()})}};o(K.prototype,b.prototype);K.prototype.predisplay_actions=function(){var Z=this,Y={};if(Z.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(ak){if(!this.hovered){return}var af=$(this).offset(),aj=ak.pageX-af.left,ai=ak.pageY-af.top,ao=Z.feature_mapper.get_feature_data(aj,ai),ag=(ao?ao[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!ag||$(this).attr("id")!==ag.toString()){$(this).remove()}});if(ao){var ab=Y[ag];if(!ab){var ag=ao[0],al={name:ao[3],start:ao[1],end:ao[2],strand:ao[4]},ae=Z.track.filters_manager.filters,ad;for(var ah=0;ah<ae.length;ah++){ad=ae[ah];al[ad.name]=ao[ad.index]}var ab=$("<div/>").attr("id",ag).addClass("feature-popup"),ap=$("<table/>"),an,am,aq;for(an in al){am=al[an];aq=$("<tr/>").appendTo(ap);$("<th/>").appendTo(aq).text(an);$("<td/>").attr("align","left").appendTo(aq).text(typeof(am)==="number"?T(am,2):am)}ab.append($("<div class='feature-popup-inner'>").append(ap));Y[ag]=ab}ab.appendTo($(this).parents(".track-content").children(".overlay"));var ac=aj+parseInt(Z.html_elt.css("left"))-ab.width()/2,aa=ai+parseInt(Z.html_elt.css("top"))+7;ab.css("left",ac+"px").css("top",aa+"px")}else{if(!ak.isPropagationStopped()){ak.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ak)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var h=function(aa,Z,ac){o(ac,{drag_handle_class:"draghandle"});p.call(this,aa,Z,ac);this.data_url=("data_url" in ac?ac.data_url:default_data_url);this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in ac?ac.data_query_wait:G);this.dataset_check_url=("converted_datasets_state_url" in ac?ac.converted_datasets_state_url:converted_datasets_state_url);var Y=this,ab=new Dataset({id:ac.dataset_id,hda_ldda:ac.hda_ldda});this.data_manager=("data_manager" in ac?ac.data_manager:new GenomeDataManager({dataset:ab,data_url:Y.data_url,dataset_state_url:Y.dataset_check_url,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 ac)||ac.resize){this.add_resize_handle()}}};o(h.prototype,p.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},p.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(Y){Y.view.set_overview(Y)}},p.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(Y){if(Y.filters_manager.visible()){Y.filters_manager.clear_filters()}else{Y.filters_manager.init_filters()}Y.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(Y){Y.dynamic_tool_div.toggle();if(Y.dynamic_tool_div.is(":visible")){Y.set_name(Y.name+Y.tool_region_and_parameters_str())}else{Y.revert_name()}$(".tipsy").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(Y){var ab='<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>',aa=_.template(ab,{track:Y});var ad=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},Z=function(){var af=$('select[name="regions"] option:selected').val(),ah,ae=new GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),ag=_.map($(".bookmark"),function(ai){return new GenomeRegion({from_str:$(ai).children(".position").text()})});if(af==="cur"){ah=[ae]}else{if(af==="bookmarks"){ah=ag}else{ah=[ae].concat(ag)}}hide_modal();window.location.href=galaxy_paths.get("paramamonster_url")+"?"+$.param({dataset_id:Y.dataset_id,hda_ldda:Y.hda_ldda,regions:JSON.stringify(new Backbone.Collection(ah).toJSON())})},ac=function(ae){if((ae.keyCode||ae.which)===27){ad()}else{if((ae.keyCode||ae.which)===13){Z()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",aa,{No:ad,Yes:Z})}},p.prototype.action_icons_def[2]],can_draw:function(){if(this.dataset_id&&p.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 Y=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(Y)}this.name_div=$("<div/>").addClass("track-name").appendTo(Y).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return Y},on_resize:function(){},add_resize_handle:function(){var Y=this;var ab=false;var aa=false;var Z=$("<div class='track-resize'>");$(Y.container_div).hover(function(){if(Y.content_visible){ab=true;Z.show()}},function(){ab=false;if(!aa){Z.hide()}});Z.hide().bind("dragstart",function(ac,ad){aa=true;ad.original_height=$(Y.content_div).height()}).bind("drag",function(ad,ae){var ac=Math.min(Math.max(ae.original_height+ae.deltaY,Y.min_height_px),Y.max_height_px);$(Y.tiles_div).css("height",ac);Y.visible_height_px=(Y.max_height_px===ac?0:ac);Y.on_resize()}).bind("dragend",function(ac,ad){Y.tile_cache.clear();aa=false;if(!ab){Z.hide()}Y.config.values.height=Y.visible_height_px;Y.changed()}).appendTo(Y.container_div)},set_display_modes:function(ab,ae){this.display_modes=ab;this.mode=(ae?ae:(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 Z=this,ac={};for(var aa=0,Y=Z.display_modes.length;aa<Y;aa++){var ad=Z.display_modes[aa];ac[ad]=function(af){return function(){Z.change_mode(af);Z.icons_div.show();Z.container_div.mouseleave(function(){Z.icons_div.hide()})}}(ad)}make_popupmenu(this.action_icons.mode_icon,ac)},build_action_icons:function(){p.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 V){return"LabelTrack"}else{if(this instanceof x){return"ReferenceTrack"}else{if(this instanceof i){return"LineTrack"}else{if(this instanceof Q){return"ReadTrack"}else{if(this instanceof N){return"VcfTrack"}else{if(this instanceof g){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(){var Z=this;Z.enabled=false;Z.tile_cache.clear();Z.data_manager.clear();Z.content_div.css("height","auto");Z.tiles_div.children().remove();Z.container_div.removeClass("nodata error pending");if(!Z.dataset_id){return}var Y=$.Deferred();$.getJSON(this.dataset_check_url,{hda_ldda:Z.hda_ldda,dataset_id:Z.dataset_id,chrom:Z.view.chrom},function(aa){if(!aa||aa==="error"||aa.kind==="error"){Z.container_div.addClass("error");Z.tiles_div.text(n);if(aa.message){var ab=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+aa.message+"</pre>",{Close:hide_modal})});Z.tiles_div.append(ab)}}else{if(aa==="no converter"){Z.container_div.addClass("error");Z.tiles_div.text(F)}else{if(aa==="no data"||(aa.data!==undefined&&(aa.data===null||aa.data.length===0))){Z.container_div.addClass("nodata");Z.tiles_div.text(A)}else{if(aa==="pending"){Z.container_div.addClass("pending");Z.tiles_div.html(s);setTimeout(function(){Z.init()},Z.data_query_wait)}else{if(aa==="data"||aa.status==="data"){if(aa.valid_chroms){Z.valid_chroms=aa.valid_chroms;Z.update_icons()}Z.tiles_div.text(S);if(Z.view.chrom){Z.tiles_div.text("");Z.tiles_div.css("height",Z.visible_height_px+"px");Z.enabled=true;$.when(Z.predraw_init()).done(function(){Y.resolve();Z.container_div.removeClass("nodata error pending");Z.request_draw()})}else{Y.resolve()}}}}}}});this.update_icons();return Y},predraw_init:function(){}});var I=function(aa,Z,ab){h.call(this,aa,Z,ab);var Y=this,aa=Y.view;l(Y.container_div,Y.drag_handle_class,".group",Y);this.filters_manager=new U(this,("filters" in ab?ab.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=("tool" in ab&&ab.tool?new q(this,ab.tool,ab.tool_state):null);this.tile_cache=new Cache(M);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(ab.mode){this.change_mode(ab.mode)}};o(I.prototype,p.prototype,h.prototype,{action_icons_def:h.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(Y){$(".tipsy").remove();Y.slotters[Y.view.resolution_px_b].max_rows*=2;Y.request_draw(true)},hide:true}]),copy:function(Y){var Z=this.to_dict();o(Z,{data_manager:this.data_manager});var aa=new this.constructor(this.view,Y,Z);aa.change_mode(this.mode);aa.enabled=this.enabled;return aa},set_filters_manager:function(Y){this.filters_manager=Y;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},change_mode:function(Z){var Y=this;Y.mode=Z;Y.config.values.mode=Z;Y.tile_cache.clear();Y.request_draw();this.action_icons.mode_icon.attr("title","Set display mode (now: "+Y.mode+")");return Y},update_icons:function(){var Y=this;if(Y.filters_available){Y.action_icons.filters_icon.show()}else{Y.action_icons.filters_icon.hide()}if(Y.tool){Y.action_icons.tools_icon.show();Y.action_icons.param_space_viz_icon.show()}else{Y.action_icons.tools_icon.hide();Y.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(Z,aa,Y){return Z+"_"+aa+"_"+Y},request_draw:function(Z,Y){this.view.request_redraw(false,Z,Y,this)},before_draw:function(){},_draw:function(Z,aj){if(!this.can_draw()){return}var ah=this.view.low,ad=this.view.high,af=ad-ah,aa=this.view.container.width(),al=this.view.resolution_px_b,ac=this.view.resolution_b_px;if(this.is_overview){ah=this.view.max_low;ad=this.view.max_high;ac=Math.pow(RESOLUTION,Math.ceil(Math.log((view.max_high-view.max_low)/O)/Math.log(RESOLUTION)));al=aa/(view.max_high-view.max_low)}this.before_draw();this.tiles_div.children().addClass("remove");var Y=Math.floor(ah/(ac*O)),ag=true,ak=[],ae=function(am){return(am&&"track" in am)};while((Y*O*ac)<ad){var ai=this.draw_helper(Z,aa,Y,ac,this.tiles_div,al);if(ae(ai)){ak.push(ai)}else{ag=false}Y+=1}if(!aj){this.tiles_div.children(".remove").removeClass("remove").remove()}var ab=this;if(ag){this.tiles_div.children(".remove").remove();ab.postdraw_actions(ak,aa,al,aj)}},postdraw_actions:function(ab,ac,ae,Y){var aa=this;var ad=false;for(var Z=0;Z<ab.length;Z++){if(ab[Z].has_icons){ad=true;break}}if(ad){for(var Z=0;Z<ab.length;Z++){tile=ab[Z];if(!tile.has_icons){tile.html_elt.css("padding-top",z)}}}},draw_helper:function(Y,ak,ap,an,ad,ae,al){var aj=this,at=this._gen_tile_cache_key(ak,ae,ap),ab=this._get_tile_bounds(ap,an);if(!al){al={}}var ar=(Y?undefined:aj.tile_cache.get_elt(at));if(ar){aj.show_tile(ar,ad,ae);return ar}var ah=true;var ao=aj.data_manager.get_data(ab,aj.mode,an,aj.data_url_extra_params);if(is_deferred(ao)){ah=false}var af;if(view.reference_track&&ae>view.canvas_manager.char_width_px){af=view.reference_track.data_manager.get_data(ab,aj.mode,an,view.reference_track.data_url_extra_params);if(is_deferred(af)){ah=false}}if(ah){o(ao,al.more_tile_data);var ag=aj.mode;if(ag==="Auto"){ag=aj.get_mode(ao);aj.update_auto_mode(ag)}var aa=aj.view.canvas_manager.new_canvas(),aq=ab.get("start"),Z=ab.get("end"),ak=Math.ceil((Z-aq)*ae)+aj.left_offset,ai=aj.get_canvas_height(ao,ag,ae,ak);aa.width=ak;aa.height=ai;var am=aa.getContext("2d");am.translate(this.left_offset,0);var ar=aj.draw_tile(ao,am,ag,an,ab,ae,af);if(ar!==undefined){aj.tile_cache.set_elt(at,ar);aj.show_tile(ar,ad,ae)}return ar}var ac=$.Deferred();$.when(ao,af).then(function(){view.request_redraw(false,false,false,aj);ac.resolve()});return ac},get_canvas_height:function(Y,aa,ab,Z){return this.visible_height_px},draw_tile:function(Y,Z,ad,ab,ac,ae,aa){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(aa,ac,ad){var Z=this,Y=aa.html_elt;aa.predisplay_actions();var ab=(aa.low-(this.is_overview?this.view.max_low:this.view.low))*ad;if(this.left_offset){ab-=this.left_offset}Y.css({position:"absolute",top:0,left:ab});if(Y.hasClass("remove")){Y.removeClass("remove")}else{ac.append(Y)}Z.after_show_tile(aa)},after_show_tile:function(Y){},_get_tile_bounds:function(Y,Z){var ab=Math.floor(Y*O*Z),ac=Math.ceil(O*Z),aa=(ab+ac<=this.view.max_high?ab+ac:this.view.max_high);return new GenomeRegion({chrom:this.view.chrom,start:ab,end:aa})},tool_region_and_parameters_str:function(aa,Y,ab){var Z=this,ac=(aa!==undefined&&Y!==undefined&&ab!==undefined?aa+":"+Y+"-"+ab:"all");return" - region=["+ac+"], parameters=["+Z.tool.get_param_values().join(", ")+"]"},data_and_mode_compatible:function(Y,Z){return true},can_subset:function(Y){return false},init_for_tool_data:function(){this.data_manager.set("data_url",raw_data_url);this.data_query_wait=1000;this.dataset_check_url=dataset_state_url;this.normal_postdraw_actions=this.postdraw_actions;this.postdraw_actions=function(aa,ab,ad,Y){var Z=this;Z.normal_postdraw_actions(aa,ab,ad,Y);Z.dataset_state_url=converted_datasets_state_url;Z.data_query_wait=G;var ac=new ServerStateDeferred({url:Z.dataset_state_url,url_params:{dataset_id:Z.dataset_id,hda_ldda:Z.hda_ldda},interval:Z.data_query_wait,success_fn:function(ae){return ae!=="pending"}});$.when(ac.go()).then(function(){Z.data_manager.set("data_url",default_data_url)});Z.postdraw_actions=Z.normal_postdraw_actions}}});var V=function(Z,Y){var aa={resize:false};h.call(this,Z,Y,aa);this.container_div.addClass("label-track")};o(V.prototype,h.prototype,{build_header_div:function(){},init:function(){this.enabled=true},_draw:function(){var aa=this.view,ab=aa.high-aa.low,ae=Math.floor(Math.pow(10,Math.floor(Math.log(ab)/Math.log(10)))),Y=Math.floor(aa.low/ae)*ae,ac=this.view.container.width(),Z=$("<div style='position: relative; height: 1.3em;'></div>");while(Y<aa.high){var ad=(Y-aa.low)/ab*ac;Z.append($("<div class='label'>"+commatize(Y)+"</div>").css({position:"absolute",left:ad-1}));Y+=ae}this.content_div.children(":first").remove();this.content_div.append(Z)}});var g=function(Z,Y,ac){I.call(this,Z,Y,ac);this.drawables=[];this.left_offset=0;if("drawables" in ac){var ab;for(var aa=0;aa<ac.drawables.length;aa++){ab=ac.drawables[aa];this.drawables[aa]=object_from_template(ab);if(ab.left_offset>this.left_offset){this.left_offset=ab.left_offset}}this.enabled=true}if(this.drawables.length!==0){this.set_display_modes(this.drawables[0].display_modes,this.drawables[0].mode)}this.update_icons();this.obj_type="CompositeTrack"};o(g.prototype,I.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(Y){$(".tipsy").remove();Y.show_group()}}].concat(I.prototype.action_icons_def),to_dict:v.prototype.to_dict,add_drawable:v.prototype.add_drawable,unpack_drawables:v.prototype.unpack_drawables,change_mode:function(Y){I.prototype.change_mode.call(this,Y);for(var Z=0;Z<this.drawables.length;Z++){this.drawables[Z].change_mode(Y)}},init:function(){var aa=[];for(var Z=0;Z<this.drawables.length;Z++){aa.push(this.drawables[Z].init())}var Y=this;$.when.apply($,aa).then(function(){Y.enabled=true;Y.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:p.prototype.can_draw,draw_helper:function(Z,an,au,aq,af,ah,ao){var am=this,ay=this._gen_tile_cache_key(an,ah,au),ad=this._get_tile_bounds(au,aq),av=ad.get("start"),aa=ad.get("end");if(!ao){ao={}}var ax=(Z?undefined:am.tile_cache.get_elt(ay));if(ax){am.show_tile(ax,af,ah);return ax}var ag=[],am,ak=true,ar,ai;for(var at=0;at<this.drawables.length;at++){am=this.drawables[at];ar=am.data_manager.get_data(av,aa,am.mode,aq,am.data_url_extra_params);if(is_deferred(ar)){ak=false}ag.push(ar);ai=null;if(view.reference_track&&ah>view.canvas_manager.char_width_px){ai=view.reference_track.data_manager.get_data(av,aa,am.mode,aq,view.reference_track.data_url_extra_params);if(is_deferred(ai)){ak=false}}ag.push(ai)}if(ak){o(ar,ao.more_tile_data);this.tile_predraw_init();var ac=am.view.canvas_manager.new_canvas(),ad=am._get_tile_bounds(au,aq),av=ad.get("start"),aa=ad.get("end"),aw=0,an=Math.ceil((aa-av)*ah)+this.left_offset,al=0,ab=[];var Y=0;for(var at=0;at<this.drawables.length;at++,aw+=2){am=this.drawables[at];ar=ag[aw];var aj=am.mode;if(aj==="Auto"){aj=am.get_mode(ar);am.update_auto_mode(aj)}ab.push(aj);Y=am.get_canvas_height(ar,aj,ah,an);if(Y>al){al=Y}}ac.width=an;ac.height=(ao.height?ao.height:al);aw=0;var ap=ac.getContext("2d");ap.translate(this.left_offset,0);ap.globalAlpha=0.5;ap.globalCompositeOperation="source-over";for(var at=0;at<this.drawables.length;at++,aw+=2){am=this.drawables[at];ar=ag[aw];ai=ag[aw+1];ax=am.draw_tile(ar,ap,ab[at],aq,ad,ah,ai)}this.tile_cache.set_elt(ay,ax);this.show_tile(ax,af,ah);return ax}var ae=$.Deferred(),am=this;$.when.apply($,ag).then(function(){view.request_redraw(false,false,false,am);ae.resolve()});return ae},show_group:function(){var ab=new L(this.view,this.container,{name:this.name}),Y;for(var aa=0;aa<this.drawables.length;aa++){Y=this.drawables[aa];ab.add_drawable(Y);Y.container=ab;ab.content_div.append(Y.container_div)}var Z=this.container.replace_drawable(this,ab,true);ab.request_draw()},tile_predraw_init:function(){var ab=Number.MAX_VALUE,Y=-ab,Z;for(var aa=0;aa<this.drawables.length;aa++){Z=this.drawables[aa];if(Z instanceof i){if(Z.prefs.min_value<ab){ab=Z.prefs.min_value}if(Z.prefs.max_value>Y){Y=Z.prefs.max_value}}}for(var aa=0;aa<this.drawables.length;aa++){Z=this.drawables[aa];Z.prefs.min_value=ab;Z.prefs.max_value=Y}},postdraw_actions:function(aa,ad,af,Z){I.prototype.postdraw_actions.call(this,aa,ad,af,Z);var ac=-1;for(var ab=0;ab<aa.length;ab++){var Y=aa[ab].html_elt.find("canvas").height();if(Y>ac){ac=Y}}for(var ab=0;ab<aa.length;ab++){var ae=aa[ab];if(ae.html_elt.find("canvas").height()!==ac){this.draw_helper(true,ad,ae.index,ae.resolution,ae.html_elt.parent(),af,{height:ac});ae.html_elt.remove()}}}});var x=function(Y){I.call(this,Y,{content_div:Y.top_labeltrack},{resize:false});Y.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=reference_url;this.data_url_extra_params={dbkey:Y.dbkey};this.data_manager=new ReferenceTrackDataManager({data_url:reference_url});this.hide_contents()};o(x.prototype,p.prototype,I.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},can_draw:p.prototype.can_draw,draw_tile:function(ag,ah,ac,ab,ae,ai){var aa=this;if(ai>this.view.canvas_manager.char_width_px){if(ag.data===null){this.hide_contents();return}var Z=ah.canvas;ah.font=ah.canvas.manager.default_font;ah.textAlign="center";ag=ag.data;for(var ad=0,af=ag.length;ad<af;ad++){var Y=Math.floor(ad*ai);ah.fillText(ag[ad],Y,10)}this.show_contents();return new b(aa,ae,ab,Z,ag)}this.hide_contents()}});var i=function(aa,Z,ab){var Y=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";I.call(this,aa,Z,ab);this.hda_ldda=ab.hda_ldda;this.dataset_id=ab.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;this.config=new B({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value: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:ab.prefs,onchange:function(){Y.set_name(Y.prefs.name);Y.vertical_range=Y.prefs.max_value-Y.prefs.min_value;Y.set_min_value(Y.prefs.min_value);Y.set_max_value(Y.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};o(i.prototype,p.prototype,I.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(Y){this.prefs.min_value=Y;$("#linetrack_"+this.dataset_id+"_minval").text(this.prefs.min_value);this.tile_cache.clear();this.request_draw()},set_max_value:function(Y){this.prefs.max_value=Y;$("#linetrack_"+this.dataset_id+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.request_draw()},predraw_init:function(){var Y=this;Y.vertical_range=undefined;return $.getJSON(Y.data_url,{stats:true,chrom:Y.view.chrom,low:null,high:null,hda_ldda:Y.hda_ldda,dataset_id:Y.dataset_id},function(Z){Y.container_div.addClass("line-track");var ac=Z.data;if(isNaN(parseFloat(Y.prefs.min_value))||isNaN(parseFloat(Y.prefs.max_value))){var aa=ac.min,ae=ac.max;aa=Math.floor(Math.min(0,Math.max(aa,ac.mean-2*ac.sd)));ae=Math.ceil(Math.max(0,Math.min(ae,ac.mean+2*ac.sd)));Y.prefs.min_value=aa;Y.prefs.max_value=ae;$("#track_"+Y.dataset_id+"_minval").val(Y.prefs.min_value);$("#track_"+Y.dataset_id+"_maxval").val(Y.prefs.max_value)}Y.vertical_range=Y.prefs.max_value-Y.prefs.min_value;Y.total_frequency=ac.total_frequency;Y.container_div.find(".yaxislabel").remove();var ad=$("<div/>").text(T(Y.prefs.min_value,3)).make_text_editable({num_cols:6,on_finish:function(af){$(".tipsy").remove();var af=parseFloat(af);if(!isNaN(af)){Y.set_min_value(af)}},help_text:"Set min value"}).addClass("yaxislabel bottom").attr("id","linetrack_"+Y.dataset_id+"_minval").prependTo(Y.container_div),ab=$("<div/>").text(T(Y.prefs.max_value,3)).make_text_editable({num_cols:6,on_finish:function(af){$(".tipsy").remove();var af=parseFloat(af);if(!isNaN(af)){Y.set_max_value(af)}},help_text:"Set max value"}).addClass("yaxislabel top").attr("id","linetrack_"+Y.dataset_id+"_maxval").prependTo(Y.container_div)})},draw_tile:function(ah,af,aa,Z,ac,ag){var Y=af.canvas,ab=ac.get("start"),ae=ac.get("end"),ad=new H.LinePainter(ah.data,ab,ae,this.prefs,aa);ad.draw(af,Y.width,Y.height,ag);return new b(this,ac,Z,Y,ah.data)},can_subset:function(Y){return false}});var c=function(ab,aa,ad){var Z=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];I.call(this,ab,aa,ad);var ac=get_random_color(),Y=get_random_color([ac,"#ffffff"]);this.config=new B({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:ac},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:Y},{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:"histogram_max",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:ad.prefs,onchange:function(){Z.set_name(Z.prefs.name);Z.tile_cache.clear();Z.set_painter_from_config();Z.request_draw()}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.hda_ldda=ad.hda_ldda;this.dataset_id=ad.dataset_id;this.original_dataset_id=ad.dataset_id;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()};o(c.prototype,p.prototype,I.prototype,{set_dataset:function(Y){this.dataset_id=Y.get("id");this.hda_ldda=Y.get("hda_ldda");this.data_manager.set("dataset",Y)},set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=H.ArcLinkedFeaturePainter}else{this.painter=H.LinkedFeaturePainter}},before_draw:function(){this.max_height_px=0},after_show_tile:function(Y){this.max_height_px=Math.max(this.max_height_px,Y.html_elt.height());Y.html_elt.parent().children().css("height",this.max_height_px+"px");var Z=this.max_height_px;if(this.visible_height_px!==0){Z=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",Z+"px")},postdraw_actions:function(an,ai,ad,ac){I.prototype.postdraw_actions.call(this,an,ac);var ah=this;if(ah.mode==="Histogram"){var ak,Z=-1;for(ak=0;ak<an.length;ak++){var aj=an[ak].max_val;if(aj>Z){Z=aj}}for(ak=0;ak<an.length;ak++){var ap=an[ak];if(ap.max_val!==Z){ap.html_elt.remove();ah.draw_helper(true,ai,ap.index,ap.resolution,ap.html_elt.parent(),ad,{more_tile_data:{max:Z}})}}}if(ah.filters_manager){var ae=ah.filters_manager.filters;for(var am=0;am<ae.length;am++){ae[am].update_ui_elt()}var ao=false,Y,af;for(var ak=0;ak<an.length;ak++){if(an[ak].data.length){Y=an[ak].data[0];for(var am=0;am<ae.length;am++){af=ae[am];if(af.applies_to(Y)&&af.min!==af.max){ao=true;break}}}}if(ah.filters_available!==ao){ah.filters_available=ao;if(!ah.filters_available){ah.filters_manager.hide()}ah.update_icons()}}this.container_div.find(".yaxislabel").remove();var ab=an[0];if(ab instanceof j){var ag=(this.prefs.histogram_max?this.prefs.histogram_max:ab.max_val),aa=$("<div/>").text(ag).make_text_editable({num_cols:12,on_finish:function(aq){$(".tipsy").remove();var aq=parseFloat(aq);ah.prefs.histogram_max=(!isNaN(aq)?aq:null);ah.tile_cache.clear();ah.request_draw()},help_text:"Set max value; leave blank to use default"}).addClass("yaxislabel top").css("color",this.prefs.label_color);this.container_div.prepend(aa)}if(ab instanceof K){var al=true;for(var ak=0;ak<an.length;ak++){if(!an[ak].all_slotted){al=false;break}}if(!al){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(Y){var Y;if(this.mode==="Auto"){if(Y==="no_detail"){Y="feature spans"}else{if(Y==="summary_tree"){Y="coverage histogram"}}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+Y+")")}},incremental_slots:function(ac,Y,ab){var Z=this.view.canvas_manager.dummy_context,aa=this.slotters[ac];if(!aa||(aa.mode!==ab)){aa=new (r.FeatureSlotter)(ac,ab,w,function(ad){return Z.measureText(ad)});this.slotters[ac]=aa}return aa.slot_features(Y)},get_summary_tree_data:function(ac,af,aa,an){if(an>aa-af){an=aa-af}var aj=Math.floor((aa-af)/an),am=[],ab=0;var ad=0,ae=0,ai,al=0,ag=[],ak,ah;var Z=function(aq,ap,ar,ao){aq[0]=ap+ar*ao;aq[1]=ap+(ar+1)*ao};while(al<an&&ad!==ac.length){var Y=false;for(;al<an&&!Y;al++){Z(ag,af,al,aj);for(ae=ad;ae<ac.length;ae++){ai=ac[ae].slice(1,3);if(is_overlap(ai,ag)){Y=true;break}}if(Y){break}}data_start_index=ae;am[am.length]=ak=[ag[0],0];for(;ae<ac.length;ae++){ai=ac[ae].slice(1,3);if(is_overlap(ai,ag)){ak[1]++}else{break}}if(ak[1]>ab){ab=ak[1]}al++}return{max:ab,delta:aj,data:am}},get_mode:function(Y){if(Y.dataset_type==="summary_tree"){mode="summary_tree"}else{if(Y.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>E){mode="Squish"}else{mode="Pack"}}}return mode},get_canvas_height:function(Y,ac,ad,Z){if(ac==="summary_tree"||ac==="Histogram"){return this.summary_draw_height}else{var ab=this.incremental_slots(ad,Y.data,ac);var aa=new (this.painter)(null,null,null,this.prefs,ac);return Math.max(X,aa.get_required_height(ab,Z))}},draw_tile:function(aj,an,al,ao,ab,af,aa){var am=this,Z=an.canvas,av=ab.get("start"),Y=ab.get("end"),aA=25,ac=this.left_offset;if(al==="summary_tree"||al==="Histogram"){if(aj.dataset_type!=="summary_tree"){var ag=this.get_summary_tree_data(aj.data,av,Y,200);if(aj.max){ag.max=aj.max}aj=ag}var ax=new H.SummaryTreePainter(aj,av,Y,this.prefs);ax.draw(an,Z.width,Z.height,af);return new j(am,ab,ao,Z,aj.data,aj.max)}var ae=[],ak=this.slotters[af].slots;all_slotted=true;if(aj.data){var ah=this.filters_manager.filters;for(var ap=0,ar=aj.data.length;ap<ar;ap++){var ad=aj.data[ap];var aq=false;var ai;for(var au=0,az=ah.length;au<az;au++){ai=ah[au];ai.update_attrs(ad);if(!ai.keep(ad)){aq=true;break}}if(!aq){ae.push(ad);if(!(ad[0] in ak)){all_slotted=false}}}}var ay=(this.filters_manager.alpha_filter?new y(this.filters_manager.alpha_filter):null);var aw=(this.filters_manager.height_filter?new y(this.filters_manager.height_filter):null);var ax=new (this.painter)(ae,av,Y,this.prefs,al,ay,aw,aa);var at=null;an.fillStyle=this.prefs.block_color;an.font=an.canvas.manager.default_font;an.textAlign="right";if(aj.data){at=ax.draw(an,Z.width,Z.height,af,ak);at.translation=-ac}return new K(am,ab,ao,Z,aj.data,af,al,aj.message,all_slotted,at)},data_and_mode_compatible:function(Y,Z){if(Z==="Auto"){return true}else{if(Y.extra_info==="no_detail"||Y.dataset_type==="summary_tree"){return false}else{return true}}},can_subset:function(Y){if(Y.dataset_type==="summary_tree"||Y.message||Y.extra_info==="no_detail"){return false}return true}});var N=function(Z,Y,aa){c.call(this,Z,Y,aa);this.config=new B({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:get_random_color()},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:aa.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=H.ReadPainter};o(N.prototype,p.prototype,I.prototype,c.prototype);var Q=function(aa,Z,ac){c.call(this,aa,Z,ac);var ab=get_random_color(),Y=get_random_color([ab,"#ffffff"]);this.config=new B({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:ab},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:Y},{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:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"Clear value to set automatically"},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ac.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=H.ReadPainter;this.update_icons()};o(Q.prototype,p.prototype,I.prototype,c.prototype);R.View=W;R.DrawableGroup=L;R.LineTrack=i;R.FeatureTrack=c;R.ReadTrack=Q;R.VcfTrack=N;R.CompositeTrack=g};var slotting_module=function(c,b){var e=c("class").extend;var d=2,a=5;b.FeatureSlotter=function(i,h,f,g){this.slots={};this.start_end_dct={};this.w_scale=i;this.mode=h;this.include_label=(h==="Pack");this.max_rows=f;this.measureText=g};e(b.FeatureSlotter.prototype,{slot_features:function(m){var p=this.w_scale,h=this.start_end_dct,x=[],z=[],n=0,y=this.max_rows;for(var v=0,w=m.length;v<w;v++){var k=m[v],o=k[0];if(this.slots[o]!==undefined){n=Math.max(n,this.slots[o]);z.push(this.slots[o])}else{x.push(v)}}var q=function(E,F){for(var D=0;D<=y;D++){var B=false,G=h[D];if(G!==undefined){for(var A=0,C=G.length;A<C;A++){var i=G[A];if(F>i[0]&&E<i[1]){B=true;break}}}if(!B){return D}}return -1};for(var v=0,w=x.length;v<w;v++){var k=m[x[v]],o=k[0],t=k[1],f=k[2],r=k[3],g=Math.floor(t*p),l=Math.ceil(f*p),u=this.measureText(r).width,j;if(r!==undefined&&this.include_label){u+=(d+a);if(g-u>=0){g-=u;j="left"}else{l+=u;j="right"}}var s=q(g,l);if(s>=0){if(h[s]===undefined){h[s]=[]}h[s].push([g,l]);this.slots[o]=s;n=Math.max(n,s)}}return n+1}})};var painters_module=function(i,x){var u=i("class").extend;var p=function(I,A,G,z,F,D){if(D===undefined){D=4}var C=z-A;var B=F-G;var E=Math.floor(Math.sqrt(C*C+B*B)/D);var J=C/E;var H=B/E;var y;for(y=0;y<E;y++,A+=J,G+=H){if(y%2!==0){continue}I.fillRect(A,G,D,1)}};var q=function(B,A,z,E){var D=A-E/2,C=A+E/2,F=z-Math.sqrt(E*3/2);B.beginPath();B.moveTo(D,F);B.lineTo(C,F);B.lineTo(A,z);B.lineTo(D,F);B.strokeStyle=this.fillStyle;B.fill();B.stroke();B.closePath()};var d=function(y){this.default_val=(y?y:1)};d.prototype.gen_val=function(y){return this.default_val};var l=function(A,C,y,z,B){this.data=A;this.view_start=C;this.view_end=y;this.prefs=u({},this.default_prefs,z);this.mode=B};l.prototype.default_prefs={};l.prototype.draw=function(z,A,y,B){};var v=function(A,C,y,z,B){l.call(this,A,C,y,z,B)};v.prototype.default_prefs={show_counts:false};v.prototype.draw=function(L,z,K,M){var E=this.view_start,N=this.view_end-this.view_start,I=this.data.data,G=(this.prefs.histogram_max?this.prefs.histogram_max:this.data.max),B=K;delta_x_px=Math.ceil(this.data.delta*M);L.save();for(var C=0,D=I.length;C<D;C++){var H=Math.floor((I[C][0]-E)*M);var F=I[C][1];if(!F){continue}var J=F/G*K;if(F!==0&&J<1){J=1}L.fillStyle=this.prefs.block_color;L.fillRect(H,B-J,delta_x_px,J);var A=4;if(this.prefs.show_counts&&(L.measureText(F).width+A)<delta_x_px){L.fillStyle=this.prefs.label_color;L.textAlign="center";L.fillText(F,H+(delta_x_px/2),10)}}L.restore()};var b=function(y,C,E,F,A){l.call(this,y,C,E,F,A);if(this.prefs.min_value===undefined){var G=Infinity;for(var z=0,B=this.data.length;z<B;z++){G=Math.min(G,this.data[z][1])}this.prefs.min_value=G}if(this.prefs.max_value===undefined){var D=-Infinity;for(var z=0,B=this.data.length;z<B;z++){D=Math.max(D,this.data[z][1])}this.prefs.max_value=D}};b.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};b.prototype.draw=function(S,Q,N,D){var I=false,K=this.prefs.min_value,F=this.prefs.max_value,M=F-K,B=N,C=this.view_start,P=this.view_end-this.view_start,L=this.mode,aa=this.data;S.save();var ac=Math.round(N+K/M*N);if(L!=="Intensity"){S.fillStyle="#aaa";S.fillRect(0,ac,Q,1)}S.beginPath();var Y,G,E;if(aa.length>1){E=Math.ceil((aa[1][0]-aa[0][0])*D)}else{E=10}var A=parseInt(this.prefs.color.slice(1),16),H=(A&16711680)>>16,R=(A&65280)>>8,V=A&255;for(var T=0,U=aa.length;T<U;T++){S.fillStyle=S.strokeStyle=this.prefs.color;Y=Math.round((aa[T][0]-C)*D);G=aa[T][1];var W=false,J=false;if(G===null){if(I&&L==="Filled"){S.lineTo(Y,B)}I=false;continue}if(G<K){J=true;G=K}else{if(G>F){W=true;G=F}}if(L==="Histogram"){G=Math.round(G/M*B);S.fillRect(Y,ac,E,-G)}else{if(L==="Intensity"){var z=(G-K)/M,O=Math.round(H+(255-H)*(1-z)),X=Math.round(R+(255-R)*(1-z)),ab=Math.round(V+(255-V)*(1-z));S.fillStyle="rgb("+O+","+X+","+ab+")";S.fillRect(Y,0,E,B)}else{G=Math.round(B-(G-K)/M*B);if(I){S.lineTo(Y,G)}else{I=true;if(L==="Filled"){S.moveTo(Y,B);S.lineTo(Y,G)}else{S.moveTo(Y,G)}}}}S.fillStyle=this.prefs.overflow_color;if(W||J){var Z;if(L==="Histogram"||L==="Intensity"){Z=E}else{Y-=2;Z=4}if(W){S.fillRect(Y,0,Z,3)}if(J){S.fillRect(Y,B-3,Z,3)}}S.fillStyle=this.prefs.color}if(L==="Filled"){if(I){S.lineTo(Y,ac);S.lineTo(0,ac)}S.fill()}else{S.stroke()}S.restore()};var m=function(y){this.feature_positions={};this.slot_height=y;this.translation=0;this.y_translation=0};m.prototype.map_feature_data=function(z,B,y,A){if(!this.feature_positions[B]){this.feature_positions[B]=[]}this.feature_positions[B].push({data:z,x_start:y,x_end:A})};m.prototype.get_feature_data=function(z,D){var C=Math.floor((D-this.y_translation)/this.slot_height),B;if(!this.feature_positions[C]){return null}z+=this.translation;for(var A=0;A<this.feature_positions[C].length;A++){B=this.feature_positions[C][A];if(z>=B.x_start&&z<=B.x_end){return B.data}}};var o=function(A,D,y,z,C,E,B){l.call(this,A,D,y,z,C);this.alpha_scaler=(E?E:new d());this.height_scaler=(B?B:new d())};o.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};u(o.prototype,{get_required_height:function(A,z){var y=y_scale=this.get_row_height(),B=this.mode;if(B==="no_detail"||B==="Squish"||B==="Pack"){y=A*y_scale}return y+this.get_top_padding(z)+this.get_bottom_padding(z)},get_top_padding:function(y){return 0},get_bottom_padding:function(y){return Math.max(Math.round(this.get_row_height()/2),5)},draw:function(K,I,G,E,F){var Q=this.data,D=this.view_start,M=this.view_end;K.save();K.fillStyle=this.prefs.block_color;K.textAlign="right";var H=this.view_end-this.view_start,L=this.get_row_height(),P=new m(L),B;for(var N=0,O=Q.length;N<O;N++){var A=Q[N],C=A[0],J=A[1],y=A[2],z=(F&&F[C]!==undefined?F[C]:null);if((J<M&&y>D)&&(this.mode==="Dense"||z!==null)){B=this.draw_element(K,this.mode,A,z,D,M,E,L,I);P.map_feature_data(A,z,B[0],B[1])}}K.restore();P.y_translation=this.get_top_padding(I);return P},draw_element:function(E,A,G,C,B,D,F,z,y){console.log("WARNING: Unimplemented function.");return[0,0]}});var c=10,h=3,k=5,w=10,f=1,s=9,e=3,a=9,j=2,g="#ccc";var r=function(A,D,y,z,C,E,B){o.call(this,A,D,y,z,C,E,B);this.draw_background_connector=true;this.draw_individual_connectors=false};u(r.prototype,o.prototype,{get_row_height:function(){var z=this.mode,y;if(z==="Dense"){y=c}else{if(z==="no_detail"){y=h}else{if(z==="Squish"){y=k}else{y=w}}}return y},draw_element:function(M,D,X,H,O,ai,am,ao,y){var T=X[0],ak=X[1],ad=X[2]-1,Q=X[3],K=X[4],ae=Math.floor(Math.max(0,(ak-O)*am)),N=Math.ceil(Math.min(y,Math.max(0,(ad-O)*am))),ac=ae,an=N,aa=(D==="Dense"?0:(0+H))*ao+this.get_top_padding(y),L,ag,R=null,aq=null,B=B=(!K||K==="+"||K==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;M.globalAlpha=this.alpha_scaler.gen_val(X);if(D==="Dense"){H=1}if(D==="no_detail"){M.fillStyle=B;M.fillRect(ae,aa+5,N-ae,f)}else{var Z=X[5],af=X[6],C=X[7],V=true;if(Z&&af){R=Math.floor(Math.max(0,(Z-O)*am));aq=Math.ceil(Math.min(y,Math.max(0,(af-O)*am)))}var al,U;if(D==="Squish"){al=1;U=e;V=false}else{if(D==="Dense"){al=5;U=s}else{al=5;U=a}}if(!C){M.fillStyle=B;M.fillRect(ae,aa+1,N-ae,U);if(K&&V){if(K==="+"){M.fillStyle=M.canvas.manager.get_pattern("right_strand_inv")}else{if(K==="-"){M.fillStyle=M.canvas.manager.get_pattern("left_strand_inv")}}M.fillRect(ae,aa+1,N-ae,U)}}else{var J,W;if(D==="Squish"||D==="Dense"){J=aa+Math.floor(e/2)+1;W=1}else{if(K){J=aa;W=U}else{J+=(e/2)+1;W=1}}if(this.draw_background_connector){if(D==="Squish"||D==="Dense"){M.fillStyle=g}else{if(K){if(K==="+"){M.fillStyle=M.canvas.manager.get_pattern("right_strand")}else{if(K==="-"){M.fillStyle=M.canvas.manager.get_pattern("left_strand")}}}else{M.fillStyle=g}}M.fillRect(ae,J,N-ae,W)}var E;for(var aj=0,A=C.length;aj<A;aj++){var F=C[aj],z=Math.floor(Math.max(0,(F[0]-O)*am)),Y=Math.ceil(Math.min(y,Math.max((F[1]-1-O)*am))),S,ab;if(z>Y){continue}M.fillStyle=B;M.fillRect(z,aa+(U-al)/2+1,Y-z,al);if(R!==undefined&&af>Z&&!(z>aq||Y<R)){var ah=Math.max(z,R),I=Math.min(Y,aq);M.fillRect(ah,aa+1,I-ah,U)}if(this.draw_individual_connectors&&S){this.draw_connector(M,S,ab,z,Y,aa)}S=z;ab=Y}if(D==="Pack"){M.globalAlpha=1;M.fillStyle="white";var G=this.height_scaler.gen_val(X),P=Math.ceil(U*G),ap=Math.round((U-P)/2);if(G!==1){M.fillRect(ae,J+1,N-ae,ap);M.fillRect(ae,J+U-ap+1,N-ae,ap)}}}M.globalAlpha=1;if(D==="Pack"&&ak>O){M.fillStyle=label_color;if(O===0&&ae-M.measureText(Q).width<0){M.textAlign="left";M.fillText(Q,N+j,aa+8);an+=M.measureText(Q).width+j}else{M.textAlign="right";M.fillText(Q,ae-j,aa+8);ac-=M.measureText(Q).width+j}}}M.globalAlpha=1;return[ac,an]}});var t=function(B,E,y,A,D,F,C,z){o.call(this,B,E,y,A,D,F,C);this.ref_seq=(z?z.data:null)};u(t.prototype,o.prototype,{get_row_height:function(){var y,z=this.mode;if(z==="Dense"){y=c}else{if(z==="Squish"){y=k}else{y=w;if(this.prefs.show_insertions){y*=2}}}return y},draw_read:function(K,A,ag,V,L,aa,ad,C,B,M){K.textAlign="center";var J=this,R=[L,aa],Z=0,W=0,D=0,F=K.canvas.manager.char_width_px,y=(B==="+"?this.prefs.block_color:this.prefs.reverse_strand_color);var O=[];if((A==="Pack"||this.mode==="Auto")&&M!==undefined&&ag>F){D=Math.round(ag/2)}if(!C){C=[[0,M.length]]}for(var G=0,I=C.length;G<I;G++){var z=C[G],E="MIDNSHP=X"[z[0]],S=z[1];if(E==="H"||E==="S"){Z-=S}var U=ad+Z,Y=Math.floor(Math.max(0,(U-L)*ag)),ab=Math.floor(Math.max(0,(U+S-L)*ag));if(Y===ab){ab+=1}switch(E){case"H":break;case"S":case"M":case"=":if(is_overlap([U,U+S],R)){var N=M.slice(W,W+S);if(D>0){K.fillStyle=y;K.fillRect(Y-D,V+1,ab-Y,9);K.fillStyle=g;for(var af=0,H=N.length;af<H;af++){if(this.prefs.show_differences){if(this.ref_seq){var P=this.ref_seq[U-L+af];if(!P||P.toLowerCase()===N[af].toLowerCase()){continue}}else{continue}}if(U+af>=L&&U+af<=aa){var X=Math.floor(Math.max(0,(U+af-L)*ag));K.fillText(N[af],X,V+9)}}}else{K.fillStyle=y;K.fillRect(Y,V+4,ab-Y,e)}}W+=S;Z+=S;break;case"N":K.fillStyle=g;K.fillRect(Y-D,V+5,ab-Y,1);Z+=S;break;case"D":K.fillStyle="red";K.fillRect(Y-D,V+4,ab-Y,3);Z+=S;break;case"P":break;case"I":var ah=Y-D;if(is_overlap([U,U+S],R)){var N=M.slice(W,W+S);if(this.prefs.show_insertions){var T=Y-(ab-Y)/2;if((A==="Pack"||this.mode==="Auto")&&M!==undefined&&ag>F){K.fillStyle="yellow";K.fillRect(T-D,V-9,ab-Y,9);O[O.length]={type:"triangle",data:[ah,V+4,5]};K.fillStyle=g;switch(compute_overlap([U,U+S],R)){case (OVERLAP_START):N=N.slice(L-U);break;case (OVERLAP_END):N=N.slice(0,U-aa);break;case (CONTAINED_BY):break;case (CONTAINS):N=N.slice(L-U,U-aa);break}for(var af=0,H=N.length;af<H;af++){var X=Math.floor(Math.max(0,(U+af-L)*ag));K.fillText(N[af],X-(ab-Y)/2,V)}}else{K.fillStyle="yellow";K.fillRect(T,V+(this.mode!=="Dense"?2:5),ab-Y,(A!=="Dense"?e:s))}}else{if((A==="Pack"||this.mode==="Auto")&&M!==undefined&&ag>F){O.push({type:"text",data:[N.length,ah,V+9]})}else{}}}W+=S;break;case"X":W+=S;break}}K.fillStyle="yellow";var Q,ai,ae;for(var ac=0;ac<O.length;ac++){Q=O[ac];ai=Q.type;ae=Q.data;if(ai==="text"){K.save();K.font="bold "+K.font;K.fillText(ae[0],ae[1],ae[2]);K.restore()}else{if(ai==="triangle"){q(K,ae[0],ae[1],ae[2])}}}},draw_element:function(R,M,E,B,U,z,I,S,P){var H=E[0],Q=E[1],A=E[2],J=E[3],D=Math.floor(Math.max(0,(Q-U)*I)),F=Math.ceil(Math.min(P,Math.max(0,(A-U)*I))),C=(M==="Dense"?0:(0+B))*S,G=this.prefs.label_color,O=0;if((M==="Pack"||this.mode==="Auto")&&I>R.canvas.manager.char_width_px){var O=Math.round(I/2)}if(E[5] instanceof Array){var N=Math.floor(Math.max(0,(E[4][0]-U)*I)),L=Math.ceil(Math.min(P,Math.max(0,(E[4][1]-U)*I))),K=Math.floor(Math.max(0,(E[5][0]-U)*I)),y=Math.ceil(Math.min(P,Math.max(0,(E[5][1]-U)*I)));if(E[4][1]>=U&&E[4][0]<=z&&E[4][2]){this.draw_read(R,M,I,C,U,z,E[4][0],E[4][2],E[4][3],E[4][4])}if(E[5][1]>=U&&E[5][0]<=z&&E[5][2]){this.draw_read(R,M,I,C,U,z,E[5][0],E[5][2],E[5][3],E[5][4])}if(K>L){R.fillStyle=g;p(R,L-O,C+5,K-O,C+5)}}else{this.draw_read(R,M,I,C,U,z,Q,E[4],E[5],E[6])}if(M==="Pack"&&Q>U&&J!=="."){R.fillStyle=this.prefs.label_color;var T=1;if(T===0&&D-R.measureText(J).width<0){R.textAlign="left";R.fillText(J,F+j-O,C+8)}else{R.textAlign="right";R.fillText(J,D-j-O,C+8)}}return[0,0]}});var n=function(A,D,y,z,C,E,B){r.call(this,A,D,y,z,C,E,B);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};u(n.prototype,o.prototype,r.prototype,{calculate_longest_feature_length:function(){var z=0;for(var C=0,y=this.data.length;C<y;C++){var B=this.data[C],A=B[1],D=B[2];z=Math.max(z,D-A)}return z},get_top_padding:function(z){var y=this.view_end-this.view_start,A=z/y;return Math.min(128,Math.ceil((this.longest_feature_length/2)*A))},draw_connector:function(G,B,F,H,E,D){var y=(F+H)/2,C=H-y;var A=Math.PI,z=0;if(C>0){G.beginPath();G.arc(y,D,H-y,Math.PI,0);G.stroke()}}});x.Scaler=d;x.SummaryTreePainter=v;x.LinePainter=b;x.LinkedFeaturePainter=r;x.ReadPainter=t;x.ArcLinkedFeaturePainter=n};(function(d){var c={};var b=function(e){return c[e]};var a=function(f,g){var e={};g(b,e);c[f]=e};a("class",class_module);a("slotting",slotting_module);a("painters",painters_module);a("trackster",trackster_module);for(key in c.trackster){d[key]=c.trackster[key]}})(window);
\ No newline at end of file
diff -r f7d0c01430f761a73db0f7dc18bd025ad6768575 -r 9b7cf76169b41729ee6253d9722145347e9f5213 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 @@
-var add_bookmark=function(d,b){var f=$("#bookmarks-container"),h=$("<div/>").addClass("bookmark").appendTo(f),g=$("<div/>").addClass("delete-icon-container").appendTo(h).click(function(){h.slideUp("fast");h.remove();view.has_changes=true;return false}),a=$("<a href=''/>").addClass("icon-button delete").appendTo(g),i=$("<div/>").addClass("position").appendTo(h),e=$("<a href=''/>").text(d).appendTo(i).click(function(){view.go_to(d);return false}),c=$("<div/>").text(b).make_text_editable({num_rows:3,use_textarea:true,help_text:"Set bookmark note"}).addClass("annotation").appendTo(h);view.has_changes=true;return h};var object_from_template=function(b,a){if("copy" in b){return b.copy(a)}else{var c=b.obj_type;if(!c){c=b.track_type}return new addable_objects[c](view,a,b)}};var addable_objects={LineTrack:LineTrack,FeatureTrack:FeatureTrack,VcfTrack:VcfTrack,ReadTrack:ReadTrack,CompositeTrack:CompositeTrack,DrawableGroup:DrawableGroup};var create_visualization=function(c,a,b,d){view=new View(c);view.editor=true;$.when(view.load_chroms_deferred).then(function(){if(a){var n=a.chrom,e=a.start,k=a.end,g=a.overview;if(n&&(e!==undefined)&&k){view.change_chrom(n,e,k)}}if(b){var h,f,j;for(var l=0;l<b.length;l++){view.add_drawable(object_from_template(b[l],view))}}view.update_intro_div();var o;for(var l=0;l<view.drawables.length;l++){if(view.drawables[l].name===g){view.set_overview(view.drawables[l]);break}}if(d){var m;for(var l=0;l<d.length;l++){m=d[l];add_bookmark(m.position,m.annotation)}}view.has_changes=false});return view};var init_keyboard_nav=function(a){$(document).keydown(function(b){if($(b.srcElement).is(":input")){return}switch(b.which){case 37:a.move_fraction(0.25);break;case 38:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTop(a.viewport_container.scrollTop()-20);break;case 39:a.move_fraction(-0.25);break;case 40:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTop(a.viewport_container.scrollTop()+20);break}})};
\ No newline at end of file
+var add_bookmark=function(d,b){var f=$("#bookmarks-container"),h=$("<div/>").addClass("bookmark").appendTo(f),g=$("<div/>").addClass("delete-icon-container").appendTo(h).click(function(){h.slideUp("fast");h.remove();view.has_changes=true;return false}),a=$("<a href=''/>").addClass("icon-button delete").appendTo(g),i=$("<div/>").addClass("position").appendTo(h),e=$("<a href=''/>").text(d).appendTo(i).click(function(){view.go_to(d);return false}),c=$("<div/>").text(b).make_text_editable({num_rows:3,use_textarea:true,help_text:"Set bookmark note"}).addClass("annotation").appendTo(h);view.has_changes=true;return h};var object_from_template=function(c,b,a){if("copy" in c){return c.copy(a)}else{var d=c.obj_type;if(!d){d=c.track_type}return new addable_objects[d](b,a,c)}};var addable_objects={LineTrack:LineTrack,FeatureTrack:FeatureTrack,VcfTrack:VcfTrack,ReadTrack:ReadTrack,CompositeTrack:CompositeTrack,DrawableGroup:DrawableGroup};var create_visualization=function(c,a,b,d){view=new View(c);view.editor=true;$.when(view.load_chroms_deferred).then(function(){if(a){var n=a.chrom,e=a.start,k=a.end,g=a.overview;if(n&&(e!==undefined)&&k){view.change_chrom(n,e,k)}}if(b){var h,f,j;for(var l=0;l<b.length;l++){view.add_drawable(object_from_template(b[l],view,view))}}view.update_intro_div();var o;for(var l=0;l<view.drawables.length;l++){if(view.drawables[l].name===g){view.set_overview(view.drawables[l]);break}}if(d){var m;for(var l=0;l<d.length;l++){m=d[l];add_bookmark(m.position,m.annotation)}}view.has_changes=false});return view};var init_keyboard_nav=function(a){$(document).keydown(function(b){if($(b.srcElement).is(":input")){return}switch(b.which){case 37:a.move_fraction(0.25);break;case 38:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTop(a.viewport_container.scrollTop()-20);break;case 39:a.move_fraction(-0.25);break;case 40:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTop(a.viewport_container.scrollTop()+20);break}})};
\ No newline at end of file
diff -r f7d0c01430f761a73db0f7dc18bd025ad6768575 -r 9b7cf76169b41729ee6253d9722145347e9f5213 static/scripts/packed/viz/visualization.js
--- a/static/scripts/packed/viz/visualization.js
+++ b/static/scripts/packed/viz/visualization.js
@@ -1,1 +1,1 @@
-var Cache=Backbone.Model.extend({defaults:{num_elements:20,obj_cache:{},key_ary:[]},get_elt:function(b){var c=this.attributes.obj_cache,d=this.attributes.key_ary,a=d.indexOf(b);if(a!==-1){if(c[b].stale){d.splice(a,1);delete c[b]}else{this.move_key_to_end(b,a)}}return c[b]},set_elt:function(b,d){var e=this.attributes.obj_cache,f=this.attributes.key_ary,c=this.attributes.num_elements;if(!e[b]){if(f.length>=c){var a=f.shift();delete e[a]}f.push(b)}e[b]=d;return d},move_key_to_end:function(b,a){this.attributes.key_ary.splice(a,1);this.attributes.key_ary.push(b)},clear:function(){this.attributes.obj_cache={};this.attributes.key_ary=[]},size:function(){return this.attributes.key_ary.length}});var GenomeDataManager=Cache.extend({defaults:_.extend({},Cache.prototype.defaults,{dataset:null,filters_manager:null,data_url:null,data_mode_compatible:function(a,b){return true},can_subset:function(a){return false}}),load_data:function(h,g,b,f){var d={chrom:h.get("chrom"),low:h.get("start"),high:h.get("end"),mode:g,resolution:b};dataset=this.get("dataset");if(dataset){d.dataset_id=dataset.id;d.hda_ldda=dataset.get("hda_ldda")}$.extend(d,f);var j=this.get("filters_manager");if(j){var k=[];var a=j.filters;for(var e=0;e<a.length;e++){k.push(a[e].name)}d.filter_cols=JSON.stringify(k)}var c=this;return $.getJSON(this.get("data_url"),d,function(i){c.set_data(h,i)})},get_data:function(g,f,c,e){var h=this.get_elt(g);if(h&&(is_deferred(h)||this.get("data_mode_compatible")(h,f))){return h}var j=this.get("key_ary"),b=this.get("obj_cache"),k,g,a,f,h;for(var d=0;d<j.length;d++){a=new GenomeRegion(j[d]);if(a.contains(g)){var h=b[k];if(is_deferred(h)||(this.get("data_mode_compatible")(h,f)&&this.get("can_subset")(h))){this.move_key_to_end(k,d);return h}}}h=this.load_data(g,f,c,e);this.set_data(g,h);return h},set_data:function(b,a){this.set_elt(b,a)},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(h,g,c,f,d){var j=this.get_elt(h);if(!(j&&this.get("data_mode_compatible")(j,g))){console.log("ERROR: no current data for: ",dataset,h.toString(),g,c,f);return}j.stale=true;var b=h.get("start");if(d===this.DEEP_DATA_REQ){$.extend(f,{start_val:j.data.length+1})}else{if(d===this.BROAD_DATA_REQ){b=(j.max_high?j.max_high:j.data[j.data.length-1][2])+1}}var i=h.copy().set("start",b);var a=this,e=this.load_data(i,g,c,f);new_data_available=$.Deferred();this.set_data(h,new_data_available);$.when(e).then(function(k){if(k.data){k.data=j.data.concat(k.data);if(k.max_low){k.max_low=j.max_low}if(k.message){k.message=k.message.replace(/[0-9]+/,k.data.length)}}a.set_data(h,k);new_data_available.resolve(k)});return new_data_available},get_elt:function(a){return Cache.prototype.get_elt.call(this,a.toString())},set_elt:function(b,a){return Cache.prototype.set_elt.call(this,b.toString(),a)}});var ReferenceTrackDataManager=GenomeDataManager.extend({load_data:function(a,d,e,b,c){if(b>1){return{data:null}}return GenomeDataManager.prototype.load_data.call(this,a,d,e,b,c)}});var Genome=Backbone.Model.extend({defaults:{name:null,key:null,chroms_info:null},get_chroms_info:function(){return this.attributes.chroms_info.chrom_info}});var GenomeRegion=Backbone.Model.extend({defaults:{chrom:null,start:0,end:0,DIF_CHROMS:1000,BEFORE:1001,CONTAINS:1002,OVERLAP_START:1003,OVERLAP_END:1004,CONTAINED_BY:1005,AFTER:1006},initialize:function(b){if(!this.get("chrom")&&!this.get("start")&&!this.get("end")&&"as_str" in b){var d=b.as_str.split(":"),c=d[0],d=d.split("-"),e=d[0],a=d[1];this.set("chrom",c);this.set("start",e);this.set("end",a)}},copy:function(){return new GenomeRegion({chrom:this.get("chrom"),start:this.get("start"),end:this.get("end")})},toString:function(){return this.get("chrom")+":"+this.get("start")+"-"+this.get("end")},compute_overlap:function(h){var b=this.get("chrom"),g=h.get("chrom"),f=this.get("start"),d=h.get("start"),e=this.get("end"),c=h.get("end"),a;if(b&&g&&b!==g){return this.get("DIF_CHROMS")}if(f<d){if(e<d){a=this.get("BEFORE")}else{if(e<=c){a=this.get("OVERLAP_START")}else{a=this.get("CONTAINS")}}}else{if(f>c){a=this.get("AFTER")}else{if(e<=c){a=this.get("CONTAINED_BY")}else{a=this.get("OVERLAP_END")}}}return a},contains:function(a){return this.compute_overlap(a)===this.get("CONTAINS")},overlaps:function(a){return _.intersection([this.compute_overlap(a)],[this.get("DIF_CHROMS"),this.get("BEFORE"),this.get("AFTER")]).length===0}});var BrowserBookmark=Backbone.Model.extend({defaults:{region:null,note:""}});var BrowserBookmarks=Backbone.Collection.extend({model:BrowserBookmark});var Visualization=Backbone.RelationalModel.extend({defaults:{id:"",title:"",type:"",dbkey:"",datasets:[]},url:function(){return galaxy_paths.get("visualization_url")},save:function(){return $.ajax({url:this.url(),type:"POST",dataType:"json",data:{vis_json:JSON.stringify(this)}})}});var TracksterVisualization=Visualization.extend({defaults:{bookmarks:[],viewport:{}}});var CircsterVisualization=Visualization.extend({});var Dataset=Backbone.Model.extend({defaults:{id:"",type:"",name:"",hda_ldda:""}});var HistogramDataset=Backbone.Model.extend({initialize:function(a){this.attributes.data=a;this.attributes.max=_.max(a,function(b){if(!b||typeof b==="string"){return 0}return b[1]})[1]}});var TrackConfig=Backbone.Model.extend({});var CircsterHistogramDatasetLayout=Backbone.Model.extend({chroms_layout:function(){var b=this.attributes.genome.get_chroms_info(),d=d3.layout.pie().value(function(f){return f.len}).sort(null),e=d(b),a=this.attributes.total_gap/b.length,c=_.map(e,function(h,g){var f=h.endAngle-a;h.endAngle=(f>h.startAngle?f:h.startAngle);return h});return c},chrom_data_layout:function(j,b,g,f,h){if(!b||typeof b==="string"){return null}var d=b[0],i=b[3],c=d3.scale.linear().domain([0,h]).range([g,f]),e=d3.layout.pie().value(function(k){return i}).startAngle(j.startAngle).endAngle(j.endAngle),a=e(d);_.each(d,function(k,l){a[l].outerRadius=c(k[1])});return a}});var CircsterView=Backbone.View.extend({className:"circster",initialize:function(a){this.width=a.width;this.height=a.height;this.total_gap=a.total_gap;this.genome=a.genome;this.dataset=a.dataset;this.radius_start=a.radius_start;this.dataset_arc_height=a.dataset_arc_height},render:function(){var d=this.radius_start,e=this.dataset_arc_height,j=new CircsterHistogramDatasetLayout({genome:this.genome,total_gap:this.total_gap}),i=j.chroms_layout(),g=_.zip(i,this.dataset.attributes.data),h=this.dataset.attributes.max,b=_.map(g,function(m){var n=m[0],l=m[1];return j.chrom_data_layout(n,l,d,d+e,h)});var c=d3.select(this.$el[0]).append("svg").attr("width",this.width).attr("height",this.height).append("g").attr("transform","translate("+this.width/2+","+this.height/2+")");var k=c.append("g").attr("id","inner-arc"),f=d3.svg.arc().innerRadius(d).outerRadius(d+e),a=k.selectAll("#inner-arc>path").data(i).enter().append("path").attr("d",f).style("stroke","#ccc").style("fill","#ccc").append("title").text(function(l){return l.data.chrom});_.each(b,function(l){if(!l){return}var o=c.append("g"),n=d3.svg.arc().innerRadius(d),m=o.selectAll("path").data(l).enter().append("path").attr("d",n).style("stroke","red").style("fill","red")})}});var TrackBrowserRouter=Backbone.Router.extend({initialize:function(b){this.view=b.view;this.route(/([\w]+)$/,"change_location");this.route(/([\w]+\:[\d,]+-[\d,]+)$/,"change_location");var a=this;a.view.on("navigate",function(c){a.navigate(c)})},change_location:function(a){this.view.go_to(a)}});var add_datasets=function(a,c,b){$.ajax({url:a,data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(d){show_modal("Select datasets for new tracks",d,{Cancel:function(){hide_modal()},Add:function(){var e=[];$("input[name=id]:checked,input[name=ldda_ids]:checked").each(function(){var f,g=$(this).val();if($(this).attr("name")==="id"){f={hda_id:g}}else{f={ldda_id:g}}e[e.length]=$.ajax({url:c,data:f,dataType:"json",})});$.when.apply($,e).then(function(){var f=(arguments[0] instanceof Array?$.map(arguments,function(g){return g[0]}):[arguments[0]]);b(f)});hide_modal()}})}})};
\ No newline at end of file
+var ServerStateDeferred=Backbone.Model.extend({defaults:{ajax_settings:{},interval:1000,success_fn:function(a){return true}},go:function(){var d=$.Deferred(),c=this,f=c.get("ajax_settings"),e=c.get("success_fn"),b=c.get("interval"),a=function(){$.ajax(f).success(function(g){if(e(g)){d.resolve(g)}else{setTimeout(a,b)}})};a();return d}});var CanvasManager=function(a){this.default_font=a!==undefined?a:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};_.extend(CanvasManager.prototype,{load_pattern:function(a,e){var b=this.patterns,c=this.dummy_context,d=new Image();d.src=galaxy_paths.attributes.image_path+e;d.onload=function(){b[a]=c.createPattern(d,"repeat")}},get_pattern:function(a){return this.patterns[a]},new_canvas:function(){var a=$("<canvas/>")[0];if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(a)}a.manager=this;return a}});var Cache=Backbone.Model.extend({defaults:{num_elements:20,obj_cache:null,key_ary:null},initialize:function(a){this.clear()},get_elt:function(b){var c=this.attributes.obj_cache,d=this.attributes.key_ary,a=d.indexOf(b);if(a!==-1){if(c[b].stale){d.splice(a,1);delete c[b]}else{this.move_key_to_end(b,a)}}return c[b]},set_elt:function(b,d){var e=this.attributes.obj_cache,f=this.attributes.key_ary,c=this.attributes.num_elements;if(!e[b]){if(f.length>=c){var a=f.shift();delete e[a]}f.push(b)}e[b]=d;return d},move_key_to_end:function(b,a){this.attributes.key_ary.splice(a,1);this.attributes.key_ary.push(b)},clear:function(){this.attributes.obj_cache={};this.attributes.key_ary=[]},size:function(){return this.attributes.key_ary.length}});var GenomeDataManager=Cache.extend({defaults:_.extend({},Cache.prototype.defaults,{dataset:null,filters_manager:null,data_url:null,dataset_state_url:null,data_mode_compatible:function(a,b){return true},can_subset:function(a){return false}}),data_is_ready:function(){var c=this.get("dataset"),b=$.Deferred(),a=new ServerStateDeferred({ajax_settings:{url:this.get("dataset_state_url"),data:{dataset_id:c.id,hda_ldda:c.get("hda_ldda")},dataType:"json"},interval:5000,success_fn:function(d){return d!=="pending"}});$.when(a.go()).then(function(d){b.resolve(d==="ok"||d==="data")});return b},load_data:function(h,g,b,f){var d={chrom:h.get("chrom"),low:h.get("start"),high:h.get("end"),mode:g,resolution:b};dataset=this.get("dataset");if(dataset){d.dataset_id=dataset.id;d.hda_ldda=dataset.get("hda_ldda")}$.extend(d,f);var j=this.get("filters_manager");if(j){var k=[];var a=j.filters;for(var e=0;e<a.length;e++){k.push(a[e].name)}d.filter_cols=JSON.stringify(k)}var c=this;return $.getJSON(this.get("data_url"),d,function(i){c.set_data(h,i)})},get_data:function(g,f,c,e){var h=this.get_elt(g);if(h&&(is_deferred(h)||this.get("data_mode_compatible")(h,f))){return h}var j=this.get("key_ary"),b=this.get("obj_cache"),k,a;for(var d=0;d<j.length;d++){a=new GenomeRegion({from_str:j[d]});if(a.contains(g)){h=b[k];if(is_deferred(h)||(this.get("data_mode_compatible")(h,f)&&this.get("can_subset")(h))){this.move_key_to_end(k,d);return h}}}h=this.load_data(g,f,c,e);this.set_data(g,h);return h},set_data:function(b,a){this.set_elt(b,a)},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(i,h,d,g,e){var k=this.get_elt(i);if(!(k&&this.get("data_mode_compatible")(k,h))){console.log("ERROR: no current data for: ",dataset,i.toString(),h,d,g);return}k.stale=true;var c=i.get("start");if(e===this.DEEP_DATA_REQ){$.extend(g,{start_val:k.data.length+1})}else{if(e===this.BROAD_DATA_REQ){c=(k.max_high?k.max_high:k.data[k.data.length-1][2])+1}}var j=i.copy().set("start",c);var b=this,f=this.load_data(j,h,d,g),a=$.Deferred();this.set_data(i,a);$.when(f).then(function(l){if(l.data){l.data=k.data.concat(l.data);if(l.max_low){l.max_low=k.max_low}if(l.message){l.message=l.message.replace(/[0-9]+/,l.data.length)}}b.set_data(i,l);a.resolve(l)});return a},get_elt:function(a){return Cache.prototype.get_elt.call(this,a.toString())},set_elt:function(b,a){return Cache.prototype.set_elt.call(this,b.toString(),a)}});var ReferenceTrackDataManager=GenomeDataManager.extend({load_data:function(a,d,e,b,c){if(b>1){return{data:null}}return GenomeDataManager.prototype.load_data.call(this,a,d,e,b,c)}});var Genome=Backbone.Model.extend({defaults:{name:null,key:null,chroms_info:null},get_chroms_info:function(){return this.attributes.chroms_info.chrom_info}});var GenomeRegion=Backbone.RelationalModel.extend({defaults:{chrom:null,start:0,end:0,DIF_CHROMS:1000,BEFORE:1001,CONTAINS:1002,OVERLAP_START:1003,OVERLAP_END:1004,CONTAINED_BY:1005,AFTER:1006},initialize:function(b){if(b.from_str){var d=b.from_str.split(":"),c=d[0],a=d[1].split("-");this.set({chrom:c,start:parseInt(a[0],10),end:parseInt(a[1],10)})}},copy:function(){return new GenomeRegion({chrom:this.get("chrom"),start:this.get("start"),end:this.get("end")})},length:function(){return this.get("end")-this.get("start")},toString:function(){return this.get("chrom")+":"+this.get("start")+"-"+this.get("end")},toJSON:function(){return{chrom:this.get("chrom"),start:this.get("start"),end:this.get("end")}},compute_overlap:function(h){var b=this.get("chrom"),g=h.get("chrom"),f=this.get("start"),d=h.get("start"),e=this.get("end"),c=h.get("end"),a;if(b&&g&&b!==g){return this.get("DIF_CHROMS")}if(f<d){if(e<d){a=this.get("BEFORE")}else{if(e<=c){a=this.get("OVERLAP_START")}else{a=this.get("CONTAINS")}}}else{if(f>c){a=this.get("AFTER")}else{if(e<=c){a=this.get("CONTAINED_BY")}else{a=this.get("OVERLAP_END")}}}return a},contains:function(a){return this.compute_overlap(a)===this.get("CONTAINS")},overlaps:function(a){return _.intersection([this.compute_overlap(a)],[this.get("DIF_CHROMS"),this.get("BEFORE"),this.get("AFTER")]).length===0}});var GenomeRegionCollection=Backbone.Collection.extend({model:GenomeRegion});var BrowserBookmark=Backbone.Model.extend({defaults:{region:null,note:""}});var BrowserBookmarks=Backbone.Collection.extend({model:BrowserBookmark});var Visualization=Backbone.RelationalModel.extend({defaults:{id:"",title:"",type:"",dbkey:"",datasets:[]},url:function(){return galaxy_paths.get("visualization_url")},save:function(){return $.ajax({url:this.url(),type:"POST",dataType:"json",data:{vis_json:JSON.stringify(this)}})}});var TracksterVisualization=Visualization.extend({defaults:{bookmarks:[],viewport:{}}});var CircsterVisualization=Visualization.extend({});var HistogramDataset=Backbone.Model.extend({initialize:function(a){this.attributes.data=a;this.attributes.max=_.max(a,function(b){if(!b||typeof b==="string"){return 0}return b[1]})[1]}});var TrackConfig=Backbone.Model.extend({});var CircsterHistogramDatasetLayout=Backbone.Model.extend({chroms_layout:function(){var b=this.attributes.genome.get_chroms_info(),d=d3.layout.pie().value(function(f){return f.len}).sort(null),e=d(b),a=this.attributes.total_gap/b.length,c=_.map(e,function(h,g){var f=h.endAngle-a;h.endAngle=(f>h.startAngle?f:h.startAngle);return h});return c},chrom_data_layout:function(j,b,g,f,h){if(!b||typeof b==="string"){return null}var d=b[0],i=b[3],c=d3.scale.linear().domain([0,h]).range([g,f]),e=d3.layout.pie().value(function(k){return i}).startAngle(j.startAngle).endAngle(j.endAngle),a=e(d);_.each(d,function(k,l){a[l].outerRadius=c(k[1])});return a}});var CircsterView=Backbone.View.extend({className:"circster",initialize:function(a){this.width=a.width;this.height=a.height;this.total_gap=a.total_gap;this.genome=a.genome;this.dataset=a.dataset;this.radius_start=a.radius_start;this.dataset_arc_height=a.dataset_arc_height},render:function(){var d=this.radius_start,e=this.dataset_arc_height,j=new CircsterHistogramDatasetLayout({genome:this.genome,total_gap:this.total_gap}),i=j.chroms_layout(),g=_.zip(i,this.dataset.attributes.data),h=this.dataset.attributes.max,b=_.map(g,function(m){var n=m[0],l=m[1];return j.chrom_data_layout(n,l,d,d+e,h)});var c=d3.select(this.$el[0]).append("svg").attr("width",this.width).attr("height",this.height).append("g").attr("transform","translate("+this.width/2+","+this.height/2+")");var k=c.append("g").attr("id","inner-arc"),f=d3.svg.arc().innerRadius(d).outerRadius(d+e),a=k.selectAll("#inner-arc>path").data(i).enter().append("path").attr("d",f).style("stroke","#ccc").style("fill","#ccc").append("title").text(function(l){return l.data.chrom});_.each(b,function(l){if(!l){return}var o=c.append("g"),n=d3.svg.arc().innerRadius(d),m=o.selectAll("path").data(l).enter().append("path").attr("d",n).style("stroke","red").style("fill","red")})}});var TrackBrowserRouter=Backbone.Router.extend({initialize:function(b){this.view=b.view;this.route(/([\w]+)$/,"change_location");this.route(/([\w]+\:[\d,]+-[\d,]+)$/,"change_location");var a=this;a.view.on("navigate",function(c){a.navigate(c)})},change_location:function(a){this.view.go_to(a)}});var add_datasets=function(a,c,b){$.ajax({url:a,data:{"f-dbkey":view.dbkey},error:function(){alert("Grid failed")},success:function(d){show_modal("Select datasets for new tracks",d,{Cancel:function(){hide_modal()},Add:function(){var e=[];$("input[name=id]:checked,input[name=ldda_ids]:checked").each(function(){var f,g=$(this).val();if($(this).attr("name")==="id"){f={hda_id:g}}else{f={ldda_id:g}}e[e.length]=$.ajax({url:c,data:f,dataType:"json"})});$.when.apply($,e).then(function(){var f=(arguments[0] instanceof Array?$.map(arguments,function(g){return g[0]}):[arguments[0]]);b(f)});hide_modal()}})}})};
\ No newline at end of file
diff -r f7d0c01430f761a73db0f7dc18bd025ad6768575 -r 9b7cf76169b41729ee6253d9722145347e9f5213 static/scripts/viz/trackster.js
--- a/static/scripts/viz/trackster.js
+++ b/static/scripts/viz/trackster.js
@@ -3054,8 +3054,6 @@
return new GenomeRegion({from_str: $(elt).children(".position").text()});
});
- console.log(regions_to_use);
-
// Get regions for visualization.
if (regions_to_use === 'cur') {
// Use only current region.
diff -r f7d0c01430f761a73db0f7dc18bd025ad6768575 -r 9b7cf76169b41729ee6253d9722145347e9f5213 templates/base_panels.mako
--- a/templates/base_panels.mako
+++ b/templates/base_panels.mako
@@ -54,11 +54,12 @@
root_path: '${h.url_for( "/" )}',
image_path: '${h.url_for( "/static/images" )}',
tool_url: '${h.url_for( controller="/api/tools" )}',
- data_url: '${h.url_for( controller="tracks", action="data" )}',
- raw_data_url: '${h.url_for( controller="tracks", action="raw_data" )}',
- converted_datasets_state_url: '${h.url_for( controller="tracks", action="converted_datasets_state" )}',
- dataset_state_url: '${h.url_for( controller="tracks", action="dataset_state" )}',
- visualization_url: '${h.url_for( controller="visualization", action="save" )}'
+ data_url: '${h.url_for( controller="/tracks", action="data" )}',
+ raw_data_url: '${h.url_for( controller="/tracks", action="raw_data" )}',
+ converted_datasets_state_url: '${h.url_for( controller="/tracks", action="converted_datasets_state" )}',
+ dataset_state_url: '${h.url_for( controller="/tracks", action="dataset_state" )}',
+ visualization_url: '${h.url_for( controller="/visualization", action="save" )}',
+ paramamonster_url: '${h.url_for( controller="/tracks", action="paramamonster" )}'
});
</script></%def>
diff -r f7d0c01430f761a73db0f7dc18bd025ad6768575 -r 9b7cf76169b41729ee6253d9722145347e9f5213 templates/display_base.mako
--- a/templates/display_base.mako
+++ b/templates/display_base.mako
@@ -32,9 +32,9 @@
<%def name="javascripts()">
${parent.javascripts()}
- ${h.js( "jquery", "jquery.tipsy", "galaxy.base", "json2", "jstorage", "jquery.autocomplete", "jquery.rating", "autocomplete_tagging",
- "viz/trackster", "viz/trackster_ui", "jquery.event.drag", "jquery.mousewheel", "jquery.autocomplete", "jquery.ui.sortable.slider",
- "farbtastic" )}
+ ${h.js( "jquery", "jquery.tipsy", "galaxy.base", "json2", "jstorage", "jquery.autocomplete", "jquery.rating",
+ "autocomplete_tagging", "viz/trackster", "viz/trackster_ui", "jquery.event.drag", "jquery.mousewheel",
+ "jquery.autocomplete", "jquery.ui.sortable.slider", "farbtastic", "mvc/data", "viz/visualization" )}
<script type="text/javascript">
diff -r f7d0c01430f761a73db0f7dc18bd025ad6768575 -r 9b7cf76169b41729ee6253d9722145347e9f5213 templates/tracks/browser.mako
--- a/templates/tracks/browser.mako
+++ b/templates/tracks/browser.mako
@@ -49,8 +49,7 @@
// Place URLs here so that url_for can be used to generate them.
//
galaxy_paths.set({
- visualization_url: "${h.url_for( action='save' )}",
- paramamonster_url: "${h.url_for( action='paramamonster' )}",
+ visualization_url: "${h.url_for( action='save' )}"
});
var
add_track_async_url = "${h.url_for( action='add_track_async' )}",
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: jgoecks: Prevent more than 10 jobs from being run at once in paramamonster. Additional paramamonster bug fixes as well.
by Bitbucket 01 Jul '12
by Bitbucket 01 Jul '12
01 Jul '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/f7d0c01430f7/
changeset: f7d0c01430f7
user: jgoecks
date: 2012-07-02 01:03:16
summary: Prevent more than 10 jobs from being run at once in paramamonster. Additional paramamonster bug fixes as well.
affected #: 4 files
diff -r 81d637b6fdad65d74fdccd02c7d71e0e6eaf37dd -r f7d0c01430f761a73db0f7dc18bd025ad6768575 lib/galaxy/web/api/tools.py
--- a/lib/galaxy/web/api/tools.py
+++ b/lib/galaxy/web/api/tools.py
@@ -142,31 +142,32 @@
# There is a list of regions.
regions = [ GenomeRegion.from_dict( r ) for r in regions ]
- # Sort by chrom name, start so that data is not fetched out of order.
- regions.sort( key=lambda r: r.chrom )
- regions.sort( key=lambda r: r.start )
+ if len( regions ) > 1:
+ # Sort by chrom name, start so that data is not fetched out of order.
+ regions.sort( key=lambda r: r.chrom )
+ regions.sort( key=lambda r: r.start )
- # Merge overlapping regions so that regions do not overlap
- # and hence data is not included multiple times.
- prev = regions[0]
- cur = regions[1]
- index = 1
- while True:
- if cur.start <= prev.end:
- # Found overlapping regions, so join them.
- prev.end = cur.end
- del regions[ index ]
- else:
- # No overlap, move to next region.
- prev = cur
- index += 1
+ # Merge overlapping regions so that regions do not overlap
+ # and hence data is not included multiple times.
+ prev = regions[0]
+ cur = regions[1]
+ index = 1
+ while True:
+ if cur.start <= prev.end:
+ # Found overlapping regions, so join them.
+ prev.end = cur.end
+ del regions[ index ]
+ else:
+ # No overlap, move to next region.
+ prev = cur
+ index += 1
- # Get next region or exit.
- if index == len( regions ):
- # Done.
- break
- else:
- cur = regions[ index ]
+ # Get next region or exit.
+ if index == len( regions ):
+ # Done.
+ break
+ else:
+ cur = regions[ index ]
run_on_regions = True
diff -r 81d637b6fdad65d74fdccd02c7d71e0e6eaf37dd -r f7d0c01430f761a73db0f7dc18bd025ad6768575 static/scripts/viz/paramamonster.js
--- a/static/scripts/viz/paramamonster.js
+++ b/static/scripts/viz/paramamonster.js
@@ -595,7 +595,7 @@
// Layout tree.
var cluster = d3.layout.cluster()
- .size([this.height - 10, this.width - 160]);
+ .size([this.height, this.width - 160]);
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x]; });
@@ -617,7 +617,7 @@
var vis = d3.select(this.$el[0])
.append("svg")
.attr("width", this.width)
- .attr("height", this.height)
+ .attr("height", this.height + 20)
.append("g")
.attr("transform", "translate(40, 10)");
@@ -754,39 +754,57 @@
regions = this.model.get('regions'),
node = d3.select(this.tool_param_tree_view.$el[0]).selectAll("g.node");
node.on("click", function(d, i) {
- // TODO: Show popup menu.
-
// Get all settings corresponding to node.
var tool = self.model.get('tool'),
dataset = self.model.get('dataset'),
- all_settings = param_tree.get_node_settings(d);
+ all_settings = param_tree.get_node_settings(d),
+ run_jobs_deferred = $.Deferred();
- // Create and add tracks for each settings group.
- var tracks = _.map(all_settings, function(settings) {
- var pm_track = new ParamaMonsterTrack({
- settings: settings,
- regions: regions
+ // Do not allow 10+ jobs to be run.
+ if (all_settings.length >= 10) {
+ show_modal("Whoa there cowboy!",
+ "You clicked on a node to try " + self.model.get('tool').get('name') +
+ " with " + all_settings.length +
+ " different combinations of settings. You can only run 10 jobs at a time.",
+ {
+ "Ok": function() { hide_modal(); run_jobs_deferred.resolve(false); }
+ });
+ }
+ else {
+ run_jobs_deferred.resolve(true);
+ }
+
+ // Take action when deferred resolves.
+ $.when(run_jobs_deferred).then(function(run_jobs) {
+ if (!run_jobs) { return; }
+
+ // Create and add tracks for each settings group.
+ var tracks = _.map(all_settings, function(settings) {
+ var pm_track = new ParamaMonsterTrack({
+ settings: settings,
+ regions: regions
+ });
+ self.add_track(pm_track);
+ return pm_track;
});
- self.add_track(pm_track);
- return pm_track;
- });
-
- // For each track, run tool using track's settings and update track.
- _.each(tracks, function(pm_track, index) {
- setTimeout(function() {
- // Set inputs and run tool.
- // console.log('running with settings', pm_track.get('settings'));
- tool.set_input_values(pm_track.get('settings'));
- $.when(tool.rerun(dataset, regions)).then(function(output) {
- // Create and add track for output dataset.
- var track_config = _.extend({
- data_url: galaxy_paths.get('raw_data_url'),
- converted_datasets_state_url: galaxy_paths.get('dataset_state_url')
- }, output.first().get('track_config')),
- track_obj = object_from_template(track_config, self, null);
- pm_track.set('track', track_obj);
- });
- }, index * 10000);
+
+ // For each track, run tool using track's settings and update track.
+ _.each(tracks, function(pm_track, index) {
+ setTimeout(function() {
+ // Set inputs and run tool.
+ // console.log('running with settings', pm_track.get('settings'));
+ tool.set_input_values(pm_track.get('settings'));
+ $.when(tool.rerun(dataset, regions)).then(function(output) {
+ // Create and add track for output dataset.
+ var track_config = _.extend({
+ data_url: galaxy_paths.get('raw_data_url'),
+ converted_datasets_state_url: galaxy_paths.get('dataset_state_url')
+ }, output.first().get('track_config')),
+ track_obj = object_from_template(track_config, self, null);
+ pm_track.set('track', track_obj);
+ });
+ }, index * 10000);
+ });
});
});
}
diff -r 81d637b6fdad65d74fdccd02c7d71e0e6eaf37dd -r f7d0c01430f761a73db0f7dc18bd025ad6768575 static/scripts/viz/trackster.js
--- a/static/scripts/viz/trackster.js
+++ b/static/scripts/viz/trackster.js
@@ -3063,11 +3063,11 @@
}
else if (regions_to_use === 'bookmarks') {
// Use only bookmarks.
- regions = new Backbone.Collection(bookmarked_regions);
+ regions = bookmarked_regions;
}
else {
// Use both current region and bookmarks.
- regions = new Backbone.Collection([ view_region ].concat(bookmarked_regions));
+ regions = [ view_region ].concat(bookmarked_regions);
}
hide_modal();
@@ -3078,7 +3078,7 @@
$.param({
dataset_id: track.dataset_id,
hda_ldda: track.hda_ldda,
- regions: JSON.stringify(regions.toJSON())
+ regions: JSON.stringify(new Backbone.Collection(regions).toJSON())
});
},
check_enter_esc = function(e) {
diff -r 81d637b6fdad65d74fdccd02c7d71e0e6eaf37dd -r f7d0c01430f761a73db0f7dc18bd025ad6768575 templates/visualization/paramamonster.mako
--- a/templates/visualization/paramamonster.mako
+++ b/templates/visualization/paramamonster.mako
@@ -91,7 +91,7 @@
.tiles {
overflow: auto;
position: absolute;
- top: 25px;
+ top: 30px;
bottom: 25px;
left: 0;
right: 0;
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: greg: Miscellaneous fixes for installing tool shed repositories.
by Bitbucket 30 Jun '12
by Bitbucket 30 Jun '12
30 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/81d637b6fdad/
changeset: 81d637b6fdad
user: greg
date: 2012-06-30 23:49:07
summary: Miscellaneous fixes for installing tool shed repositories.
affected #: 2 files
diff -r f3c8c73009c90025a068fc7eaf1641ebd1f3cc47 -r 81d637b6fdad65d74fdccd02c7d71e0e6eaf37dd lib/galaxy/web/controllers/admin_toolshed.py
--- a/lib/galaxy/web/controllers/admin_toolshed.py
+++ b/lib/galaxy/web/controllers/admin_toolshed.py
@@ -86,15 +86,18 @@
operations = [ grids.GridOperation( "Get updates",
allow_multiple=False,
condition=( lambda item: not item.deleted ),
- async_compatible=False ),
+ async_compatible=False,
+ url_args=dict( controller='admin_toolshed', action='browse_repositories', operation='get updates' ) ),
grids.GridOperation( "Deactivate or uninstall",
allow_multiple=False,
condition=( lambda item: not item.deleted ),
- async_compatible=False ),
+ async_compatible=False,
+ url_args=dict( controller='admin_toolshed', action='browse_repositories', operation='deactivate or uninstall' ) ),
grids.GridOperation( "Activate or reinstall",
allow_multiple=False,
condition=( lambda item: item.deleted ),
- async_compatible=False ) ]
+ async_compatible=False,
+ url_args=dict( controller='admin_toolshed', action='browse_repositories', operation='activate or reinstall' ) ) ]
standard_filters = []
default_filter = dict( deleted="False" )
num_rows_per_page = 50
@@ -589,43 +592,38 @@
if file_name == shed_tool_conf:
tool_path = shed_tool_conf_dict[ 'tool_path' ]
break
- if includes_tools and ( new_tool_panel_section or tool_panel_section ):
- if new_tool_panel_section:
- section_id = new_tool_panel_section.lower().replace( ' ', '_' )
- new_section_key = 'section_%s' % str( section_id )
- if new_section_key in trans.app.toolbox.tool_panel:
- # Appending a tool to an existing section in trans.app.toolbox.tool_panel
- log.debug( "Appending to tool panel section: %s" % new_tool_panel_section )
- tool_section = trans.app.toolbox.tool_panel[ new_section_key ]
- else:
- # Appending a new section to trans.app.toolbox.tool_panel
- log.debug( "Loading new tool panel section: %s" % new_tool_panel_section )
- elem = Element( 'section' )
- elem.attrib[ 'name' ] = new_tool_panel_section
- elem.attrib[ 'id' ] = section_id
- elem.attrib[ 'version' ] = ''
- tool_section = tools.ToolSection( elem )
- trans.app.toolbox.tool_panel[ new_section_key ] = tool_section
- else:
- section_key = 'section_%s' % tool_panel_section
- tool_section = trans.app.toolbox.tool_panel[ section_key ]
- else:
- tool_section = None
# Make sure all tool_shed_repository records exist.
- new_tool_shed_repositories = []
+ created_or_updated_tool_shed_repositories = []
for name, repo_info_tuple in repo_info_dict.items():
description, repository_clone_url, changeset_revision, ctx_rev = repo_info_tuple
clone_dir = os.path.join( tool_path, self.generate_tool_path( repository_clone_url, changeset_revision ) )
relative_install_dir = os.path.join( clone_dir, name )
owner = get_repository_owner( clean_repository_clone_url( repository_clone_url ) )
# Make sure the repository was not already installed.
- installed_changeset_revision = self.repository_was_previously_installed( trans, tool_shed_url, name, repo_info_tuple, clone_dir )
- if installed_changeset_revision:
- message = "Tool shed repository <b>%s</b> with owner <b>%s</b> and changeset revision <b>%s</b> " % ( name, owner, changeset_revision )
- message += "was previously installed using changeset revision <b>%s</b>. You can get " % installed_changeset_revision
- message += "the latest updates for the installed repository using the <b>Get updates</b> option from the repository's "
- message += "<b>Repository Actions</b> pop-up menu."
+ installed_tool_shed_repository, installed_changeset_revision = self.repository_was_previously_installed( trans,
+ tool_shed_url,
+ name,
+ repo_info_tuple,
+ clone_dir )
+ if installed_tool_shed_repository:
+ message = "The tool shed repository <b>%s</b> with owner <b>%s</b> and changeset revision <b>%s</b> " % ( name, owner, changeset_revision )
+ if installed_changeset_revision != changeset_revision:
+ message += "was previously installed using changeset revision <b>%s</b>. " % installed_changeset_revision
+ else:
+ message += "was previously installed. "
+ if installed_tool_shed_repository.uninstalled:
+ message += "The repository has been uninstalled, however, so reinstall the original repository instead of installing it again. "
+ elif installed_tool_shed_repository.deleted:
+ message += "The repository has been deactivated, however, so activate the original repository instead of installing it again. "
+ if installed_changeset_revision != changeset_revision:
+ message += "You can get the latest updates for the repository using the <b>Get updates</b> option from the repository's "
+ message += "<b>Repository Actions</b> pop-up menu. "
status = 'error'
+ if len( repo_info_dict ) == 1:
+ new_kwd = dict( message=message, status=status )
+ return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
+ action='browse_repositories',
+ **new_kwd ) )
else:
print "Adding new row (or updating an existing row) for repository '%s' in the tool_shed_repository table." % name
tool_shed_repository = create_or_update_tool_shed_repository( app=trans.app,
@@ -639,9 +637,31 @@
current_changeset_revision=changeset_revision,
owner=owner,
dist_to_shed=False )
- new_tool_shed_repositories.append( tool_shed_repository )
- if new_tool_shed_repositories:
- tsrids_list = [ trans.security.encode_id( tsr.id ) for tsr in new_tool_shed_repositories ]
+ created_or_updated_tool_shed_repositories.append( tool_shed_repository )
+ if created_or_updated_tool_shed_repositories:
+ if includes_tools and ( new_tool_panel_section or tool_panel_section ):
+ if new_tool_panel_section:
+ section_id = new_tool_panel_section.lower().replace( ' ', '_' )
+ tool_panel_section_key = 'section_%s' % str( section_id )
+ if tool_panel_section_key in trans.app.toolbox.tool_panel:
+ # Appending a tool to an existing section in trans.app.toolbox.tool_panel
+ log.debug( "Appending to tool panel section: %s" % new_tool_panel_section )
+ tool_section = trans.app.toolbox.tool_panel[ tool_panel_section_key ]
+ else:
+ # Appending a new section to trans.app.toolbox.tool_panel
+ log.debug( "Loading new tool panel section: %s" % new_tool_panel_section )
+ elem = Element( 'section' )
+ elem.attrib[ 'name' ] = new_tool_panel_section
+ elem.attrib[ 'id' ] = section_id
+ elem.attrib[ 'version' ] = ''
+ tool_section = tools.ToolSection( elem )
+ trans.app.toolbox.tool_panel[ tool_panel_section_key ] = tool_section
+ else:
+ tool_panel_section_key = 'section_%s' % tool_panel_section
+ tool_section = trans.app.toolbox.tool_panel[ tool_panel_section_key ]
+ else:
+ tool_section = None
+ tsrids_list = [ trans.security.encode_id( tsr.id ) for tsr in created_or_updated_tool_shed_repositories ]
new_kwd = dict( includes_tool_dependencies=kwd.get( 'includes_tool_dependencies', False ),
includes_tools=kwd.get( 'includes_tools', False ),
install_tool_dependencies=install_tool_dependencies,
@@ -652,7 +672,7 @@
status=status,
tool_panel_section=kwd.get( 'tool_panel_section', '' ),
tool_path=tool_path,
- tool_section=tool_section,
+ tool_panel_section_key=tool_panel_section_key,
tool_shed_repository_ids=tsrids_list,
tool_shed_url=kwd[ 'tool_shed_url' ] )
encoded_kwd = tool_shed_encode( new_kwd )
@@ -760,6 +780,11 @@
tool_path = kwd[ 'tool_path' ]
includes_tool_dependencies = util.string_as_bool( kwd[ 'includes_tool_dependencies' ] )
install_tool_dependencies = CheckboxField.is_checked( kwd.get( 'install_tool_dependencies', '' ) )
+ tool_panel_section_key = kwd.get( 'tool_panel_section_key', None )
+ if tool_panel_section_key:
+ tool_section = trans.app.toolbox.tool_panel[ tool_panel_section_key ]
+ else:
+ tool_section = None
for tool_shed_repository in tool_shed_repositories:
# Clone each repository to the configured location.
update_tool_shed_repository_status( trans.app, tool_shed_repository, trans.model.ToolShedRepository.installation_status.CLONING )
@@ -777,7 +802,7 @@
repository_clone_url=repository_clone_url,
relative_install_dir=relative_install_dir,
tool_shed=tool_shed_repository.tool_shed,
- tool_section=kwd.get( 'tool_section', '' ),
+ tool_section=tool_section,
shed_tool_conf=kwd.get( 'shed_tool_conf', '' ) )
trans.sa_session.refresh( tool_shed_repository )
metadata = tool_shed_repository.metadata
@@ -1262,25 +1287,29 @@
def repository_was_previously_installed( self, trans, tool_shed_url, repository_name, repo_info_tuple, clone_dir ):
# Handle case where the repository was previously installed using an older changeset_revsion, but later the repository was updated
# in the tool shed and now we're trying to install the latest changeset revision of the same repository instead of updating the one
- # that was previously installed.
+ # that was previously installed. We'll look in the database instead of on disk since the repository may be uninstalled.
description, repository_clone_url, changeset_revision, ctx_rev = repo_info_tuple
- if os.path.exists( clone_dir ):
- # The installed changeset revision already exists on disk.
- return changeset_revision
repository_owner = get_repository_owner( clean_repository_clone_url( repository_clone_url ) )
+ tool_shed = get_tool_shed_from_clone_url( repository_clone_url )
+ # Get all previous change set revisions from the tool shed for the repository back to, but excluding, the previous valid changeset
+ # revision to see if it was previously installed using one of them.
url = '%s/repository/previous_changeset_revisions?galaxy_url=%s&name=%s&owner=%s&changeset_revision=%s&webapp=galaxy&no_reset=true' % \
( tool_shed_url, url_for( '/', qualified=True ), repository_name, repository_owner, changeset_revision )
response = urllib2.urlopen( url )
text = response.read()
response.close()
if text:
- clone_path, clone_directory = os.path.split( clone_dir )
+ #clone_path, clone_directory = os.path.split( clone_dir )
changeset_revisions = util.listify( text )
for previous_changeset_revision in changeset_revisions:
- new_clone_dir = os.path.join( clone_path, previous_changeset_revision )
- if os.path.exists( new_clone_dir ):
- return previous_changeset_revision
- return None
+ tool_shed_repository = get_tool_shed_repository_by_shed_name_owner_installed_changeset_revision( trans.app,
+ tool_shed,
+ repository_name,
+ repository_owner,
+ previous_changeset_revision )
+ if tool_shed_repository and tool_shed_repository.status not in [ trans.model.ToolShedRepository.installation_status.NEW ]:
+ return tool_shed_repository, previous_changeset_revision
+ return None, None
@web.expose
@web.require_admin
def reselect_tool_panel_section( self, trans, **kwd ):
diff -r f3c8c73009c90025a068fc7eaf1641ebd1f3cc47 -r 81d637b6fdad65d74fdccd02c7d71e0e6eaf37dd templates/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako
--- a/templates/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako
+++ b/templates/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako
@@ -23,7 +23,7 @@
<div class="toolForm"><div class="toolFormTitle">${repository.name}</div><div class="toolFormBody">
- <form name="uninstall_repository" id="uninstall_repository" action="${h.url_for( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( repository.id ) )}" method="post" >
+ <form name="deactivate_or_uninstall_repository" id="deactivate_or_uninstall_repository" action="${h.url_for( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( repository.id ) )}" method="post" ><div class="form-row"><label>Description:</label>
${repository.description}
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: jgoecks: Enable scrolling for tiles area in parameter space visualization.
by Bitbucket 29 Jun '12
by Bitbucket 29 Jun '12
29 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/f3c8c73009c9/
changeset: f3c8c73009c9
user: jgoecks
date: 2012-06-30 00:15:02
summary: Enable scrolling for tiles area in parameter space visualization.
affected #: 2 files
diff -r c0afbd9f63713787b4fa4d3d42a00c91cb7fb3b1 -r f3c8c73009c90025a068fc7eaf1641ebd1f3cc47 static/scripts/viz/paramamonster.js
--- a/static/scripts/viz/paramamonster.js
+++ b/static/scripts/viz/paramamonster.js
@@ -695,7 +695,8 @@
});
tr.children().first().attr('colspan', 2);
- $('#right').append(this.track_collection_container);
+ var tracks_div = $('<div>').addClass('tiles');
+ $('#right').append( tracks_div.append(this.track_collection_container) );
self.model.get('tracks').each(function(track) {
self.add_track(track);
diff -r c0afbd9f63713787b4fa4d3d42a00c91cb7fb3b1 -r f3c8c73009c90025a068fc7eaf1641ebd1f3cc47 templates/visualization/paramamonster.mako
--- a/templates/visualization/paramamonster.mako
+++ b/templates/visualization/paramamonster.mako
@@ -88,6 +88,14 @@
#right {
width: 600px;
}
+ .tiles {
+ overflow: auto;
+ position: absolute;
+ top: 25px;
+ bottom: 25px;
+ left: 0;
+ right: 0;
+ }
</style></%def>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/c0afbd9f6371/
changeset: c0afbd9f6371
user: jgoecks
date: 2012-06-30 00:00:38
summary: Remove debugging code.
affected #: 1 file
diff -r 29abb6c4b296815594c93cd8d72944628160145c -r c0afbd9f63713787b4fa4d3d42a00c91cb7fb3b1 lib/galaxy/web/api/tools.py
--- a/lib/galaxy/web/api/tools.py
+++ b/lib/galaxy/web/api/tools.py
@@ -148,9 +148,6 @@
# Merge overlapping regions so that regions do not overlap
# and hence data is not included multiple times.
- print "REGIONS", regions
- for region in regions:
- print "\t", region.chrom, region.start, region.end
prev = regions[0]
cur = regions[1]
index = 1
@@ -170,10 +167,7 @@
break
else:
cur = regions[ index ]
-
- print "REGIONS", regions
- for region in regions:
- print "\t", region.chrom, region.start, region.end
+
run_on_regions = True
# Dataset check.
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

29 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/29abb6c4b296/
changeset: 29abb6c4b296
user: jgoecks
date: 2012-06-29 23:57:40
summary: Use Trackster as an entry point for parameter space visualization. Current viewing area, bookmarks, or both can be used as regions in parameter space visualization. Also handle multiple intervals well.
affected #: 10 files
diff -r cc5fea2e382ed8edadf0d694f559b46e86a66884 -r 29abb6c4b296815594c93cd8d72944628160145c lib/galaxy/web/api/tools.py
--- a/lib/galaxy/web/api/tools.py
+++ b/lib/galaxy/web/api/tools.py
@@ -141,6 +141,39 @@
elif isinstance( regions, list ):
# There is a list of regions.
regions = [ GenomeRegion.from_dict( r ) for r in regions ]
+
+ # Sort by chrom name, start so that data is not fetched out of order.
+ regions.sort( key=lambda r: r.chrom )
+ regions.sort( key=lambda r: r.start )
+
+ # Merge overlapping regions so that regions do not overlap
+ # and hence data is not included multiple times.
+ print "REGIONS", regions
+ for region in regions:
+ print "\t", region.chrom, region.start, region.end
+ prev = regions[0]
+ cur = regions[1]
+ index = 1
+ while True:
+ if cur.start <= prev.end:
+ # Found overlapping regions, so join them.
+ prev.end = cur.end
+ del regions[ index ]
+ else:
+ # No overlap, move to next region.
+ prev = cur
+ index += 1
+
+ # Get next region or exit.
+ if index == len( regions ):
+ # Done.
+ break
+ else:
+ cur = regions[ index ]
+
+ print "REGIONS", regions
+ for region in regions:
+ print "\t", region.chrom, region.start, region.end
run_on_regions = True
# Dataset check.
diff -r cc5fea2e382ed8edadf0d694f559b46e86a66884 -r 29abb6c4b296815594c93cd8d72944628160145c lib/galaxy/web/controllers/tracks.py
--- a/lib/galaxy/web/controllers/tracks.py
+++ b/lib/galaxy/web/controllers/tracks.py
@@ -484,22 +484,8 @@
viz_config = {
'dataset_id': dataset_id,
'tool_id': job.tool_id,
- 'regions': regions
+ 'regions': from_json_string( regions )
}
-
- viz_config[ 'regions' ] = [
- {
- 'chrom': 'chr19',
- 'start': '10000',
- 'end': '26000'
- },
- {
- 'chrom': 'chr19',
- 'start': '150000',
- 'end': '175000'
- }
-
- ]
# Add tool, dataset attributes to config based on id.
tool = trans.app.toolbox.get_tool( viz_config[ 'tool_id' ] )
diff -r cc5fea2e382ed8edadf0d694f559b46e86a66884 -r 29abb6c4b296815594c93cd8d72944628160145c static/images/fugue/arrow-split-bw.png
Binary file static/images/fugue/arrow-split-bw.png has changed
diff -r cc5fea2e382ed8edadf0d694f559b46e86a66884 -r 29abb6c4b296815594c93cd8d72944628160145c static/images/fugue/arrow-split.png
Binary file static/images/fugue/arrow-split.png has changed
diff -r cc5fea2e382ed8edadf0d694f559b46e86a66884 -r 29abb6c4b296815594c93cd8d72944628160145c static/june_2007_style/base_sprites.less.tmpl
--- a/static/june_2007_style/base_sprites.less.tmpl
+++ b/static/june_2007_style/base_sprites.less.tmpl
@@ -122,6 +122,14 @@
-sprite-group: fugue;
-sprite-image: fugue/cross-circle.png;
}
+.icon-button.arrow-split {
+ -sprite-group: fugue;
+ -sprite-image: fugue/arrow-split-bw.png;
+}
+.icon-button.arrow-split:hover {
+ -sprite-group: fugue;
+ -sprite-image: fugue/arrow-split.png;
+}
.text-and-autocomplete-select {
-sprite-group: fugue;
-sprite-image: fugue/control-270.png;
diff -r cc5fea2e382ed8edadf0d694f559b46e86a66884 -r 29abb6c4b296815594c93cd8d72944628160145c static/june_2007_style/blue/base.css
--- a/static/june_2007_style/blue/base.css
+++ b/static/june_2007_style/blue/base.css
@@ -759,7 +759,9 @@
.icon-button.disk--arrow:hover{background:url(fugue.png) no-repeat 0px -494px;}
.icon-button.cross-circle{background:url(fugue.png) no-repeat 0px -520px;}
.icon-button.cross-circle:hover{background:url(fugue.png) no-repeat 0px -546px;}
-.text-and-autocomplete-select{background:url(fugue.png) no-repeat right -572px;}
+.icon-button.arrow-split{background:url(fugue.png) no-repeat 0px -572px;}
+.icon-button.arrow-split:hover{background:url(fugue.png) no-repeat 0px -598px;}
+.text-and-autocomplete-select{background:url(fugue.png) no-repeat right -624px;}
div.historyItem-error .state-icon{background:url(history-states.png) no-repeat 0px 0px;}
div.historyItem-empty .state-icon{background:url(history-states.png) no-repeat 0px -25px;}
div.historyItem-queued .state-icon{background:url(history-states.png) no-repeat 0px -50px;}
diff -r cc5fea2e382ed8edadf0d694f559b46e86a66884 -r 29abb6c4b296815594c93cd8d72944628160145c static/june_2007_style/blue/fugue.png
Binary file static/june_2007_style/blue/fugue.png has changed
diff -r cc5fea2e382ed8edadf0d694f559b46e86a66884 -r 29abb6c4b296815594c93cd8d72944628160145c static/scripts/viz/trackster.js
--- a/static/scripts/viz/trackster.js
+++ b/static/scripts/viz/trackster.js
@@ -838,11 +838,11 @@
//
/// All tracks the same?
- var drawable,
+ var i, j, drawable,
same_type = true,
a_type = this.drawables[0].get_type(),
num_feature_tracks = 0;
- for (var i = 0; i < num_drawables; i++) {
+ for (i = 0; i < num_drawables; i++) {
drawable = this.drawables[i];
if (drawable.get_type() !== a_type) {
can_composite = false;
@@ -868,21 +868,20 @@
//
// Find shared filters.
//
- var
- shared_filters = {},
+ var shared_filters = {},
filter;
// Init shared filters with filters from first drawable.
drawable = this.drawables[0];
- for (var j = 0; j < drawable.filters_manager.filters.length; j++) {
+ for (j = 0; j < drawable.filters_manager.filters.length; j++) {
filter = drawable.filters_manager.filters[j];
shared_filters[filter.name] = [filter];
}
// Create lists of shared filters.
- for (var i = 1; i < this.drawables.length; i++) {
+ for (i = 1; i < this.drawables.length; i++) {
drawable = this.drawables[i];
- for (var j = 0; j < drawable.filters_manager.filters.length; j++) {
+ for (j = 0; j < drawable.filters_manager.filters.length; j++) {
filter = drawable.filters_manager.filters[j];
if (filter.name in shared_filters) {
shared_filters[filter.name].push(filter);
@@ -1278,8 +1277,8 @@
* Load chrom data for the view. Returns a jQuery Deferred.
*/
load_chroms: function(url_parms) {
- url_parms['num'] = MAX_CHROMS_SELECTABLE;
- url_parms['dbkey'] = this.dbkey;
+ url_parms.num = MAX_CHROMS_SELECTABLE;
+ url_parms.dbkey = this.dbkey;
var
view = this,
@@ -1729,7 +1728,6 @@
var run_tool_row = $("<div>").addClass("param-row").appendTo(this.parent_div);
var run_on_dataset_button = $("<input type='submit'>").attr("value", "Run on complete dataset").appendTo(run_tool_row);
var run_on_region_button = $("<input type='submit'>").attr("value", "Run on visible region").css("margin-left", "3em").appendTo(run_tool_row);
- var tool = this;
run_on_region_button.click( function() {
// Run tool to create new track.
tool.run_on_region();
@@ -2413,14 +2411,14 @@
filter = this.filters[i];
filter_dicts.push(filter.to_dict());
}
- obj_dict['filters'] = filter_dicts;
+ obj_dict.filters = filter_dicts;
// Include transparency, height filters.
- obj_dict['alpha_filter'] = (this.alpha_filter ? this.alpha_filter.name : null);
- obj_dict['height_filter'] = (this.height_filter ? this.height_filter.name : null);
+ obj_dict.alpha_filter = (this.alpha_filter ? this.alpha_filter.name : null);
+ obj_dict.height_filter = (this.height_filter ? this.height_filter.name : null);
// Include visibility.
- obj_dict['visible'] = this.parent_div.is(":visible");
+ obj_dict.visible = this.parent_div.is(":visible");
return obj_dict;
},
@@ -3028,6 +3026,76 @@
$(".tipsy").remove();
}
},
+ // Go to parameter exploration visualization.
+ {
+ name: "param_space_viz_icon",
+ title: "Tool parameter space visualization",
+ css_class: "arrow-split",
+ on_click_fn: function(track) {
+ var template =
+ '<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>',
+ html = _.template(template, { track: track });
+ var cancel_fn = function() { hide_modal(); $(window).unbind("keypress.check_enter_esc"); },
+ ok_fn = function() {
+ var regions_to_use = $('select[name="regions"] option:selected').val(),
+ regions,
+ view_region = new GenomeRegion({
+ chrom: view.chrom,
+ start: view.low,
+ end: view.high
+ }),
+ bookmarked_regions = _.map($(".bookmark"), function(elt) {
+ return new GenomeRegion({from_str: $(elt).children(".position").text()});
+ });
+
+ console.log(regions_to_use);
+
+ // Get regions for visualization.
+ if (regions_to_use === 'cur') {
+ // Use only current region.
+ regions = [ view_region ];
+ }
+ else if (regions_to_use === 'bookmarks') {
+ // Use only bookmarks.
+ regions = new Backbone.Collection(bookmarked_regions);
+ }
+ else {
+ // Use both current region and bookmarks.
+ regions = new Backbone.Collection([ view_region ].concat(bookmarked_regions));
+ }
+
+ hide_modal();
+
+ // Go to visualization.
+ window.location.href =
+ galaxy_paths.get('paramamonster_url') + "?" +
+ $.param({
+ dataset_id: track.dataset_id,
+ hda_ldda: track.hda_ldda,
+ regions: JSON.stringify(regions.toJSON())
+ });
+ },
+ check_enter_esc = function(e) {
+ if ((e.keyCode || e.which) === 27) { // Escape key
+ cancel_fn();
+ } else if ((e.keyCode || e.which) === 13) { // Enter key
+ ok_fn();
+ }
+ };
+
+ show_modal("Visualize tool parameter space and output from different parameter settings?", html, {
+ "No": cancel_fn,
+ "Yes": ok_fn
+ });
+
+ }
+ },
// Remove track.
Drawable.prototype.action_icons_def[2]
],
@@ -3379,13 +3447,15 @@
}
//
- // Show/hide tool icon.
+ // Show/hide tool icons.
//
if (track.tool) {
track.action_icons.tools_icon.show();
+ track.action_icons.param_space_viz_icon.show();
}
else {
track.action_icons.tools_icon.hide();
+ track.action_icons.param_space_viz_icon.hide();
}
//
@@ -3856,6 +3926,7 @@
// For now, hide filters and tool.
this.action_icons.filters_icon.hide();
this.action_icons.tools_icon.hide();
+ this.action_icons.param_space_viz_icon.hide();
},
can_draw: Drawable.prototype.can_draw,
draw_helper: function(force, width, tile_index, resolution, parent_element, w_scale, kwargs) {
@@ -4341,6 +4412,7 @@
}
this.tiles_div.css("height", track_height + "px");
},
+
/**
* Actions to be taken after draw has been completed. Draw is completed when all tiles have been
* drawn/fetched and shown.
@@ -4353,15 +4425,15 @@
// If mode is Histogram and tiles do not share max, redraw tiles as necessary using new max.
if (track.mode === "Histogram") {
// Get global max.
- var global_max = -1;
- for (var i = 0; i < tiles.length; i++) {
+ var i, global_max = -1;
+ for (i = 0; i < tiles.length; i++) {
var cur_max = tiles[i].max_val;
if (cur_max > global_max) {
global_max = cur_max;
}
}
- for (var i = 0; i < tiles.length; i++) {
+ for (i = 0; i < tiles.length; i++) {
var tile = tiles[i];
if (tile.max_val !== global_max) {
tile.html_elt.remove();
@@ -4477,7 +4549,7 @@
var dummy_context = this.view.canvas_manager.dummy_context,
slotter = this.slotters[level];
if (!slotter || (slotter.mode !== mode)) {
- slotter = new (slotting.FeatureSlotter)( level, mode, MAX_FEATURE_DEPTH, function ( x ) { return dummy_context.measureText( x ) } );
+ slotter = new (slotting.FeatureSlotter)( level, mode, MAX_FEATURE_DEPTH, function ( x ) { return dummy_context.measureText( x ); } );
this.slotters[level] = slotter;
}
@@ -4726,7 +4798,7 @@
}
return true;
- },
+ }
});
var VcfTrack = function(view, container, obj_dict) {
@@ -4740,7 +4812,7 @@
{ key: 'label_color', label: 'Label color', type: 'color', default_value: 'black' },
{ key: 'show_insertions', label: 'Show insertions', type: 'bool', default_value: false },
{ key: 'show_counts', label: 'Show summary counts', type: 'bool', default_value: true },
- { key: 'mode', type: 'string', default_value: this.mode, hidden: true },
+ { key: 'mode', type: 'string', default_value: this.mode, hidden: true }
],
saved_values: obj_dict.prefs,
onchange: function() {
@@ -4773,7 +4845,7 @@
{ 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: 'histogram_max', label: 'Histogram maximum', type: 'float', default_value: null, help: 'Clear value to set automatically' },
- { key: 'mode', type: 'string', default_value: this.mode, hidden: true },
+ { key: 'mode', type: 'string', default_value: this.mode, hidden: true }
],
saved_values: obj_dict.prefs,
onchange: function() {
diff -r cc5fea2e382ed8edadf0d694f559b46e86a66884 -r 29abb6c4b296815594c93cd8d72944628160145c static/scripts/viz/visualization.js
--- a/static/scripts/viz/visualization.js
+++ b/static/scripts/viz/visualization.js
@@ -269,7 +269,7 @@
obj_cache = this.get('obj_cache'),
key, entry_region;
for (var i = 0; i < key_ary.length; i++) {
- entry_region = new GenomeRegion(key_ary[i]);
+ entry_region = new GenomeRegion({from_str: key_ary[i]});
if (entry_region.contains(region)) {
// This entry has data in the requested range. Return if data
@@ -420,20 +420,19 @@
},
/**
- * If options is a string, parsing using the format
- * chrom:start-end is attempted to set object attributes.
+ * If from_str specified, use it to initialize attributes.
*/
initialize: function(options) {
- if (typeof(options) === 'string') {
- var pieces = options.split(':'),
+ if (options.from_str) {
+ var pieces = options.from_str.split(':'),
chrom = pieces[0],
start_end = pieces[1].split('-');
this.set({
chrom: chrom,
- start: parseInt(start_end[0]),
- end: parseInt(start_end[1])
+ start: parseInt(start_end[0], 10),
+ end: parseInt(start_end[1], 10)
});
- }
+ }
},
copy: function() {
@@ -552,7 +551,12 @@
datasets: []
},
- url: galaxy_paths.get("visualization_url"),
+ // Use function because visualization_url changes depending on viz.
+ // FIXME: all visualizations should save to the same URL (and hence
+ // this function won't be needed).
+ url: function() {
+ return galaxy_paths.get("visualization_url");
+ },
/**
* POSTs visualization's JSON to its URL using the parameter 'vis_json'
@@ -561,7 +565,7 @@
*/
save: function() {
return $.ajax({
- url: this.url,
+ url: this.url(),
type: "POST",
dataType: "json",
data: {
diff -r cc5fea2e382ed8edadf0d694f559b46e86a66884 -r 29abb6c4b296815594c93cd8d72944628160145c templates/tracks/browser.mako
--- a/templates/tracks/browser.mako
+++ b/templates/tracks/browser.mako
@@ -49,7 +49,8 @@
// Place URLs here so that url_for can be used to generate them.
//
galaxy_paths.set({
- visualization_url: "${h.url_for( action='save' )}"
+ visualization_url: "${h.url_for( action='save' )}",
+ paramamonster_url: "${h.url_for( action='paramamonster' )}",
});
var
add_track_async_url = "${h.url_for( action='add_track_async' )}",
@@ -141,10 +142,10 @@
// Save bookmarks.
var bookmarks = [];
$(".bookmark").each(function() {
- bookmarks[bookmarks.length] = {
+ bookmarks.push({
position: $(this).children(".position").text(),
annotation: $(this).children(".annotation").text()
- };
+ });
});
// FIXME: give unique IDs to Drawables and save overview as ID.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: greg: Refinements for installing tool shed repositories and tool dependencies.
by Bitbucket 29 Jun '12
by Bitbucket 29 Jun '12
29 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/cc5fea2e382e/
changeset: cc5fea2e382e
user: greg
date: 2012-06-29 21:44:49
summary: Refinements for installing tool shed repositories and tool dependencies.
affected #: 18 files
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -2647,15 +2647,23 @@
pass
class ToolShedRepository( object ):
- installation_status = Bunch( CLONED='cloned',
- SETTING_TOOL_VERSIONS='setting tool versions',
- INSTALLING_TOOL_DEPENDENCIES='installing tool dependencies',
- INSTALLED='installed',
- ERROR='error',
- UNINSTALLED='uninstalled' )
+ installation_status = Bunch( NEW='New',
+ CLONING='Cloning',
+ SETTING_TOOL_VERSIONS='Setting tool versions',
+ INSTALLING_TOOL_DEPENDENCIES='Installing tool dependencies',
+ LOADING_PROPRIETARY_DATATYPES='Loading proprietary datatypes',
+ INSTALLED='Installed',
+ DEACTIVATED='Deactivated',
+ ERROR='Error',
+ UNINSTALLED='Uninstalled' )
+ states = Bunch( INSTALLING = 'running',
+ OK = 'ok',
+ WARNING = 'queued',
+ ERROR = 'error',
+ UNINSTALLED = 'deleted_new' )
def __init__( self, id=None, create_time=None, tool_shed=None, name=None, description=None, owner=None, installed_changeset_revision=None,
changeset_revision=None, ctx_rev=None, metadata=None, includes_datatypes=False, update_available=False, deleted=False,
- uninstalled=False, dist_to_shed=False ):
+ uninstalled=False, dist_to_shed=False, status=None, error_message=None ):
self.id = id
self.create_time = create_time
self.tool_shed = tool_shed
@@ -2671,6 +2679,8 @@
self.deleted = deleted
self.uninstalled = uninstalled
self.dist_to_shed = dist_to_shed
+ self.status = status
+ self.error_message = error_message
def repo_files_directory( self, app ):
repo_path = self.repo_path( app )
if repo_path:
@@ -2723,6 +2733,16 @@
dependencies_being_installed.append( tool_dependency )
return dependencies_being_installed
@property
+ def tool_dependencies_missing_or_being_installed( self ):
+ dependencies_missing_or_being_installed = []
+ for tool_dependency in self.tool_dependencies:
+ if tool_dependency.status in [ ToolDependency.installation_status.ERROR,
+ ToolDependency.installation_status.INSTALLING,
+ ToolDependency.installation_status.NEVER_INSTALLED,
+ ToolDependency.installation_status.UNINSTALLED ]:
+ dependencies_missing_or_being_installed.append( tool_dependency )
+ return dependencies_missing_or_being_installed
+ @property
def tool_dependencies_with_installation_errors( self ):
dependencies_with_installation_errors = []
for tool_dependency in self.tool_dependencies:
@@ -2746,6 +2766,7 @@
UNINSTALLED='Uninstalled' )
states = Bunch( INSTALLING = 'running',
OK = 'ok',
+ WARNING = 'queued',
ERROR = 'error',
UNINSTALLED = 'deleted_new' )
def __init__( self, tool_shed_repository_id=None, name=None, version=None, type=None, status=None, error_message=None ):
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py
+++ b/lib/galaxy/model/mapping.py
@@ -388,7 +388,9 @@
Column( "update_available", Boolean, default=False ),
Column( "deleted", Boolean, index=True, default=False ),
Column( "uninstalled", Boolean, default=False ),
- Column( "dist_to_shed", Boolean, default=False ) )
+ Column( "dist_to_shed", Boolean, default=False ),
+ Column( "status", TrimmedString( 255 ) ),
+ Column( "error_message", TEXT ) )
ToolDependency.table = Table( "tool_dependency", metadata,
Column( "id", Integer, primary_key=True ),
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 lib/galaxy/model/migrate/versions/0103_add_tool_shed_repository_status_columns.py
--- /dev/null
+++ b/lib/galaxy/model/migrate/versions/0103_add_tool_shed_repository_status_columns.py
@@ -0,0 +1,68 @@
+"""Migration script to add status and error_message columns to the tool_shed_repository table."""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+metadata = MetaData( migrate_engine )
+db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
+
+def upgrade():
+ print __doc__
+ metadata.reflect()
+ ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
+ # Add the status column to the tool_shed_repository table.
+ col = Column( "status", TrimmedString( 255 ) )
+ try:
+ col.create( ToolShedRepository_table )
+ assert col is ToolShedRepository_table.c.status
+ except Exception, e:
+ print "Adding status column to the tool_shed_repository table failed: %s" % str( e )
+ # Add the error_message column to the tool_shed_repository table.
+ col = Column( "error_message", TEXT )
+ try:
+ col.create( ToolShedRepository_table )
+ assert col is ToolShedRepository_table.c.error_message
+ except Exception, e:
+ print "Adding error_message column to the tool_shed_repository table failed: %s" % str( e )
+ # Update the status column value for tool_shed_repositories to the default value 'Installed'.
+ cmd = "UPDATE tool_shed_repository SET status = 'Installed';"
+ try:
+ db_session.execute( cmd )
+ except Exception, e:
+ print "Exception executing sql command: "
+ print cmd
+ print str( e )
+ # Update the status column for tool_shed_repositories that have been uninstalled.
+ cmd = "UPDATE tool_shed_repository SET status = 'Uninstalled' WHERE uninstalled;"
+ try:
+ db_session.execute( cmd )
+ except Exception, e:
+ print "Exception executing sql command: "
+ print cmd
+ print str( e )
+ # Update the status column for tool_shed_repositories that have been deactivated.
+ cmd = "UPDATE tool_shed_repository SET status = 'Deactivated' where deleted and not uninstalled;"
+ try:
+ db_session.execute( cmd )
+ except Exception, e:
+ print "Exception executing sql command: "
+ print cmd
+ print str( e )
+def downgrade():
+ metadata.reflect()
+ ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
+ try:
+ ToolShedRepository_table.c.status.drop()
+ except Exception, e:
+ print "Dropping column status from the tool_shed_repository table failed: %s" % str( e )
+ try:
+ ToolShedRepository_table.c.error_message.drop()
+ except Exception, e:
+ print "Dropping column error_message from the tool_shed_repository table failed: %s" % str( e )
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 lib/galaxy/tool_shed/install_manager.py
--- a/lib/galaxy/tool_shed/install_manager.py
+++ b/lib/galaxy/tool_shed/install_manager.py
@@ -119,12 +119,8 @@
if not is_displayed:
is_displayed = True
return is_displayed, tool_sections
- def handle_repository_contents( self, repository_clone_url, relative_install_dir, repository_elem, repository_name, description,
- installed_changeset_revision, ctx_rev, install_dependencies ):
- # Generate the metadata for the installed tool shed repository, among other things. It is critical that the installed repository is
- # updated to the desired changeset_revision before metadata is set because the process for setting metadata uses the repository files on disk.
- # The values for the keys in each of the following dictionaries will be a list to allow for the same tool to be displayed in multiple places
- # in the tool panel.
+ def handle_repository_contents( self, tool_shed_repository, repository_clone_url, relative_install_dir, repository_elem, install_dependencies ):
+ """Generate the metadata for the installed tool shed repository, among other things."""
tool_panel_dict_for_display = odict()
for tool_elem in repository_elem:
# The tool_elem looks something like this: <tool id="EMBOSS: antigenic1" version="5.0.0" file="emboss_antigenic.xml" />
@@ -137,21 +133,12 @@
for k, v in tool_panel_dict_for_tool_config.items():
tool_panel_dict_for_display[ k ] = v
metadata_dict = generate_metadata_using_disk_files( self.toolbox, relative_install_dir, repository_clone_url )
- # Add a new record to the tool_shed_repository table if one doesn't already exist. If one exists but is marked
- # deleted, undelete it. It is critical that this happens before the call to add_to_tool_panel() below because
- # tools will not be properly loaded if the repository is marked deleted.
- print "Adding new row (or updating an existing row) for repository '%s' in the tool_shed_repository table." % repository_name
- tool_shed_repository = create_or_update_tool_shed_repository( self.app,
- repository_name,
- description,
- installed_changeset_revision,
- ctx_rev,
- repository_clone_url,
- metadata_dict,
- dist_to_shed=True )
+ tool_shed_repository.metadata = metadata_dict
+ self.app.sa_session.add( tool_shed_repository )
+ self.app.sa_session.flush()
if 'tool_dependencies' in metadata_dict:
- # All tool_dependency objects must be created before the tools are processed no matter whether tool dependencies are going to be installed.
- tool_dependencies = create_tool_dependency_objects( self.app, tool_shed_repository, installed_changeset_revision )
+ # All tool_dependency objects must be created before the tools are processed even if no tool dependencies will be installed.
+ tool_dependencies = create_tool_dependency_objects( self.app, tool_shed_repository, tool_shed_repository.installed_changeset_revision )
else:
tool_dependencies = None
if 'tools' in metadata_dict:
@@ -162,7 +149,7 @@
# Handle missing data table entries for tool parameters that are dynamically generated select lists.
repository_tools_tups = handle_missing_data_table_entry( self.app,
tool_shed_repository,
- installed_changeset_revision,
+ tool_shed_repository.installed_changeset_revision,
self.tool_path,
repository_tools_tups,
work_dir )
@@ -171,13 +158,16 @@
# Copy remaining sample files included in the repository to the ~/tool-data directory of the local Galaxy instance.
copy_sample_files( self.app, sample_files, sample_files_copied=sample_files_copied )
if install_dependencies and tool_dependencies and 'tool_dependencies' in metadata_dict:
+ # Install tool dependencies.
+ update_tool_shed_repository_status( self.app,
+ tool_shed_repository,
+ self.app.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES )
# Get the tool_dependencies.xml file from the repository.
tool_dependencies_config = get_config_from_repository( self.app,
'tool_dependencies.xml',
tool_shed_repository,
- installed_changeset_revision,
+ tool_shed_repository.installed_changeset_revision,
work_dir )
- # Install tool dependencies.
installed_tool_dependencies = handle_tool_dependencies( app=self.app,
tool_shed_repository=tool_shed_repository,
tool_dependencies_config=tool_dependencies_config,
@@ -187,9 +177,9 @@
print '\nThe following error occurred from the InstallManager while installing tool dependency ', installed_tool_dependency.name, ':'
print installed_tool_dependency.error_message, '\n\n'
add_to_tool_panel( self.app,
- repository_name,
+ tool_shed_repository.name,
repository_clone_url,
- installed_changeset_revision,
+ tool_shed_repository.installed_changeset_revision,
repository_tools_tups,
self.repository_owner,
self.migrated_tools_config,
@@ -200,11 +190,14 @@
except:
pass
if 'datatypes' in metadata_dict:
+ update_tool_shed_repository_status( self.app,
+ tool_shed_repository,
+ self.app.model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES )
work_dir = make_tmp_directory()
datatypes_config = get_config_from_repository( self.app,
'datatypes_conf.xml',
tool_shed_repository,
- installed_changeset_revision,
+ tool_shed_repository.installed_changeset_revision,
work_dir )
# Load proprietary data types required by tools. The value of override is not important here since the Galaxy server will be started
# after this installation completes.
@@ -212,9 +205,9 @@
if converter_path or display_path:
# Create a dictionary of tool shed repository related information.
repository_dict = create_repository_dict_for_proprietary_datatypes( tool_shed=self.tool_shed,
- name=repository_name,
+ name=tool_shed_repository.name,
owner=self.repository_owner,
- installed_changeset_revision=installed_changeset_revision,
+ installed_changeset_revision=tool_shed_repository.installed_changeset_revision,
tool_dicts=metadata_dict.get( 'tools', [] ),
converter_path=converter_path,
display_path=display_path )
@@ -228,7 +221,6 @@
shutil.rmtree( work_dir )
except:
pass
- return tool_shed_repository, metadata_dict
def install_repository( self, repository_elem, install_dependencies ):
# Install a single repository, loading contained tools into the tool panel.
name = repository_elem.get( 'name' )
@@ -243,16 +235,31 @@
repository_clone_url = os.path.join( tool_shed_url, 'repos', self.repository_owner, name )
relative_install_dir = os.path.join( clone_dir, name )
ctx_rev = get_ctx_rev( tool_shed_url, name, self.repository_owner, installed_changeset_revision )
+ print "Adding new row (or updating an existing row) for repository '%s' in the tool_shed_repository table." % name
+ tool_shed_repository = create_or_update_tool_shed_repository( app=self.app,
+ name=name,
+ description=description,
+ installed_changeset_revision=installed_changeset_revision,
+ ctx_rev=ctx_rev,
+ repository_clone_url=repository_clone_url,
+ metadata_dict={},
+ status=self.app.model.ToolShedRepository.installation_status.NEW,
+ current_changeset_revision=None,
+ owner=self.repository_owner,
+ dist_to_shed=True )
+ update_tool_shed_repository_status( self.app, tool_shed_repository, self.app.model.ToolShedRepository.installation_status.CLONING )
clone_repository( repository_clone_url, os.path.abspath( relative_install_dir ), ctx_rev )
- tool_shed_repository, metadata_dict = self.handle_repository_contents( repository_clone_url,
- relative_install_dir,
- repository_elem,
- name,
- description,
- installed_changeset_revision,
- ctx_rev,
- install_dependencies )
+ self.handle_repository_contents( tool_shed_repository=tool_shed_repository,
+ repository_clone_url=repository_clone_url,
+ relative_install_dir=relative_install_dir,
+ repository_elem=repository_elem,
+ install_dependencies=install_dependencies )
+ self.app.sa_session.refresh( tool_shed_repository )
+ metadata_dict = tool_shed_repository.metadata
if 'tools' in metadata_dict:
+ update_tool_shed_repository_status( self.app,
+ tool_shed_repository,
+ self.app.model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS )
# Get the tool_versions from the tool shed for each tool in the installed change set.
url = '%s/repository/get_tool_versions?name=%s&owner=%s&changeset_revision=%s&webapp=galaxy&no_reset=true' % \
( tool_shed_url, tool_shed_repository.name, self.repository_owner, installed_changeset_revision )
@@ -291,6 +298,7 @@
parent_id=tool_version_using_old_id.id )
self.app.sa_session.add( tool_version_association )
self.app.sa_session.flush()
+ update_tool_shed_repository_status( self.app, tool_shed_repository, self.app.model.ToolShedRepository.installation_status.INSTALLED )
@property
def non_shed_tool_panel_configs( self ):
# Get the non-shed related tool panel config file names from the Galaxy config - the default is tool_conf.xml.
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 lib/galaxy/util/shed_util.py
--- a/lib/galaxy/util/shed_util.py
+++ b/lib/galaxy/util/shed_util.py
@@ -279,11 +279,11 @@
def clone_repository( repository_clone_url, repository_file_dir, ctx_rev ):
"""Clone the repository up to the specified changeset_revision. No subsequent revisions will be present in the cloned repository."""
commands.clone( get_configured_ui(),
- repository_clone_url,
- dest=repository_file_dir,
+ str( repository_clone_url ),
+ dest=str( repository_file_dir ),
pull=True,
noupdate=False,
- rev=[ ctx_rev ] )
+ rev=util.listify( str( ctx_rev ) ) )
def copy_sample_file( app, filename, dest_path=None ):
"""Copy xxx.loc.sample to dest_path/xxx.loc.sample and dest_path/xxx.loc. The default value for dest_path is ~/tool-data."""
if dest_path is None:
@@ -313,7 +313,7 @@
converter_path=converter_path,
display_path=display_path )
def create_or_update_tool_shed_repository( app, name, description, installed_changeset_revision, ctx_rev, repository_clone_url, metadata_dict,
- current_changeset_revision=None, owner='', dist_to_shed=False ):
+ status, current_changeset_revision=None, owner='', dist_to_shed=False ):
# 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.
if current_changeset_revision is None:
@@ -337,8 +337,17 @@
tool_shed_repository.ctx_rev = ctx_rev
tool_shed_repository.metadata = metadata_dict
tool_shed_repository.includes_datatypes = includes_datatypes
- tool_shed_repository.deleted = False
- tool_shed_repository.uninstalled = False
+ tool_shed_repository.status = status
+ if status in [ app.model.ToolShedRepository.installation_status.NEW,
+ app.model.ToolShedRepository.installation_status.CLONING,
+ app.model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS,
+ app.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES,
+ app.model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES,
+ app.model.ToolShedRepository.installation_status.INSTALLED,
+ app.model.ToolShedRepository.installation_status.ERROR ]:
+ tool_shed_repository.deleted = False
+ if status not in [ app.model.ToolShedRepository.installation_status.UNINSTALLED ]:
+ tool_shed_repository.uninstalled = False
else:
tool_shed_repository = app.model.ToolShedRepository( tool_shed=tool_shed,
name=name,
@@ -349,7 +358,8 @@
ctx_rev=ctx_rev,
metadata=metadata_dict,
includes_datatypes=includes_datatypes,
- dist_to_shed=dist_to_shed )
+ dist_to_shed=dist_to_shed,
+ status=status )
sa_session.add( tool_shed_repository )
sa_session.flush()
return tool_shed_repository
@@ -1255,87 +1265,6 @@
def load_installed_display_applications( installed_repository_dict, deactivate=False ):
# Load or deactivate proprietary datatype display applications
app.datatypes_registry.load_display_applications( installed_repository_dict=installed_repository_dict, deactivate=deactivate )
-def load_repository_contents( trans, repository_name, description, owner, installed_changeset_revision, current_changeset_revision, ctx_rev,
- tool_path, repository_clone_url, relative_install_dir, tool_shed=None, tool_section=None, shed_tool_conf=None ):
- """
- Generate the metadata for the installed tool shed repository, among other things. This method is called from Galaxy (never the tool shed)
- when an admin is installing a new repository or reinstalling an uninstalled repository.
- """
- metadata_dict = generate_metadata_using_disk_files( trans.app.toolbox, relative_install_dir, repository_clone_url )
- # Add a new record to the tool_shed_repository table if one doesn't already exist. If one exists but is marked deleted, undelete it. This
- # must happen before the call to add_to_tool_panel() below because tools will not be properly loaded if the repository is marked deleted.
- log.debug( "Adding new row (or updating an existing row) for repository '%s' in the tool_shed_repository table." % repository_name )
- tool_shed_repository = create_or_update_tool_shed_repository( trans.app,
- repository_name,
- description,
- installed_changeset_revision,
- ctx_rev,
- repository_clone_url,
- metadata_dict,
- current_changeset_revision=current_changeset_revision,
- owner='',
- dist_to_shed=False )
- if 'tools' in metadata_dict:
- tool_panel_dict = generate_tool_panel_dict_for_new_install( metadata_dict[ 'tools' ], tool_section )
- repository_tools_tups = get_repository_tools_tups( trans.app, metadata_dict )
- if repository_tools_tups:
- # Handle missing data table entries for tool parameters that are dynamically generated select lists.
- work_dir = make_tmp_directory()
- repository_tools_tups = handle_missing_data_table_entry( trans.app,
- tool_shed_repository,
- current_changeset_revision,
- tool_path,
- repository_tools_tups,
- work_dir )
- # Handle missing index files for tool parameters that are dynamically generated select lists.
- sample_files = metadata_dict.get( 'sample_files', [] )
- repository_tools_tups, sample_files_copied = handle_missing_index_file( trans.app, tool_path, sample_files, repository_tools_tups )
- # Copy remaining sample files included in the repository to the ~/tool-data directory of the local Galaxy instance.
- copy_sample_files( trans.app, sample_files, sample_files_copied=sample_files_copied )
- add_to_tool_panel( app=trans.app,
- repository_name=repository_name,
- repository_clone_url=repository_clone_url,
- changeset_revision=current_changeset_revision,
- repository_tools_tups=repository_tools_tups,
- owner=owner,
- shed_tool_conf=shed_tool_conf,
- tool_panel_dict=tool_panel_dict,
- new_install=True )
- try:
- shutil.rmtree( work_dir )
- except:
- pass
- if 'datatypes' in metadata_dict:
- work_dir = make_tmp_directory()
- datatypes_config = get_config_from_repository( trans.app,
- 'datatypes_conf.xml',
- tool_shed_repository,
- current_changeset_revision,
- work_dir )
- # Load data types required by tools.
- converter_path, display_path = alter_config_and_load_prorietary_datatypes( trans.app, datatypes_config, relative_install_dir, override=False )
- if converter_path or display_path:
- # Create a dictionary of tool shed repository related information.
- repository_dict = create_repository_dict_for_proprietary_datatypes( tool_shed=tool_shed,
- name=repository_name,
- owner=owner,
- installed_changeset_revision=installed_changeset_revision,
- tool_dicts=metadata_dict.get( 'tools', [] ),
- converter_path=converter_path,
- display_path=display_path )
- if converter_path:
- # Load proprietary datatype converters
- trans.app.datatypes_registry.load_datatype_converters( trans.app.toolbox, installed_repository_dict=repository_dict )
- if display_path:
- # Load proprietary datatype display applications
- trans.app.datatypes_registry.load_display_applications( installed_repository_dict=repository_dict )
- try:
- shutil.rmtree( work_dir )
- except:
- pass
- if 'tool_dependencies' in metadata_dict:
- tool_dependencies = create_tool_dependency_objects( trans.app, tool_shed_repository, current_changeset_revision )
- return tool_shed_repository, metadata_dict
def make_tmp_directory():
tmp_dir = os.getenv( 'TMPDIR', '' )
if tmp_dir:
@@ -1582,3 +1511,8 @@
commands.update( get_configured_ui(),
repo,
rev=ctx_rev )
+def update_tool_shed_repository_status( app, tool_shed_repository, status ):
+ sa_session = app.model.context.current
+ tool_shed_repository.status = status
+ sa_session.add( tool_shed_repository )
+ sa_session.flush()
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 lib/galaxy/web/controllers/admin_toolshed.py
--- a/lib/galaxy/web/controllers/admin_toolshed.py
+++ b/lib/galaxy/web/controllers/admin_toolshed.py
@@ -7,17 +7,17 @@
from galaxy import eggs, tools
eggs.require( 'mercurial' )
-from mercurial import hg
+from mercurial import hg, ui, commands
log = logging.getLogger( __name__ )
MAX_CONTENT_SIZE = 32768
-class RepositoryListGrid( grids.Grid ):
+class InstalledRepositoryGrid( grids.Grid ):
class NameColumn( grids.TextColumn ):
def get_value( self, trans, grid, tool_shed_repository ):
if tool_shed_repository.update_available:
- return '<div class="count-box state-color-error">%s</div>' % tool_shed_repository.name
+ return '<div class="count-box state-color-running">%s</div>' % tool_shed_repository.name
return tool_shed_repository.name
class DescriptionColumn( grids.TextColumn ):
def get_value( self, trans, grid, tool_shed_repository ):
@@ -28,6 +28,30 @@
class RevisionColumn( grids.TextColumn ):
def get_value( self, trans, grid, tool_shed_repository ):
return tool_shed_repository.changeset_revision
+ class StatusColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, tool_shed_repository ):
+ if tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status.CLONING,
+ trans.model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS,
+ trans.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES,
+ trans.model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES ]:
+ bgcolor = trans.model.ToolShedRepository.states.INSTALLING
+ elif tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status.NEW,
+ trans.model.ToolShedRepository.installation_status.UNINSTALLED ]:
+ bgcolor = trans.model.ToolShedRepository.states.UNINSTALLED
+ elif tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status.ERROR ]:
+ bgcolor = trans.model.ToolShedRepository.states.ERROR
+ elif tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status.DEACTIVATED ]:
+ bgcolor = trans.model.ToolShedRepository.states.WARNING
+ elif tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status.INSTALLED ]:
+ if tool_shed_repository.missing_tool_dependencies:
+ bgcolor = trans.model.ToolShedRepository.states.WARNING
+ else:
+ bgcolor = trans.model.ToolShedRepository.states.OK
+ else:
+ bgcolor = trans.model.ToolShedRepository.states.ERROR
+ rval = '<div class="count-box state-color-%s">' % bgcolor
+ rval += '%s</div>' % tool_shed_repository.status
+ return rval
class ToolShedColumn( grids.TextColumn ):
def get_value( self, trans, grid, tool_shed_repository ):
return tool_shed_repository.tool_shed
@@ -44,6 +68,8 @@
DescriptionColumn( "Description" ),
OwnerColumn( "Owner" ),
RevisionColumn( "Revision" ),
+ StatusColumn( "Installation Status",
+ filterable="advanced" ),
ToolShedColumn( "Tool shed" ),
# Columns that are valid for filtering but are not visible.
grids.DeletedColumn( "Deleted",
@@ -77,6 +103,101 @@
def build_initial_query( self, trans, **kwd ):
return trans.sa_session.query( self.model_class )
+class RepositoryInstallationGrid( grids.Grid ):
+ class NameColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, tool_shed_repository ):
+ return tool_shed_repository.name
+ class DescriptionColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, tool_shed_repository ):
+ return tool_shed_repository.description
+ class OwnerColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, tool_shed_repository ):
+ return tool_shed_repository.owner
+ class RevisionColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, tool_shed_repository ):
+ return tool_shed_repository.changeset_revision
+ class StatusColumn( grids.TextColumn ):
+ def get_value( self, trans, grid, tool_shed_repository ):
+ if tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status.CLONING,
+ trans.model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS,
+ trans.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES,
+ trans.model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES ]:
+ bgcolor = trans.model.ToolShedRepository.states.INSTALLING
+ elif tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status.NEW,
+ trans.model.ToolShedRepository.installation_status.UNINSTALLED ]:
+ bgcolor = trans.model.ToolShedRepository.states.UNINSTALLED
+ elif tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status.ERROR ]:
+ bgcolor = trans.model.ToolShedRepository.states.ERROR
+ elif tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status.DEACTIVATED ]:
+ bgcolor = trans.model.ToolShedRepository.states.WARNING
+ elif tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status.INSTALLED ]:
+ if tool_shed_repository.missing_tool_dependencies:
+ bgcolor = trans.model.ToolShedRepository.states.WARNING
+ else:
+ bgcolor = trans.model.ToolShedRepository.states.OK
+ else:
+ bgcolor = trans.model.ToolShedRepository.states.ERROR
+ rval = '<div class="count-box state-color-%s" id="ToolShedRepositoryStatus-%s">' % ( bgcolor, trans.security.encode_id( tool_shed_repository.id ) )
+ rval += '%s</div>' % tool_shed_repository.status
+ return rval
+
+ webapp = "galaxy"
+ title = "Monitor installing tool shed repositories"
+ template = "admin/tool_shed_repository/repository_installation_grid.mako"
+ model_class = model.ToolShedRepository
+ default_sort_key = "-create_time"
+ num_rows_per_page = 50
+ preserve_state = True
+ use_paging = False
+ columns = [
+ NameColumn( "Name",
+ link=( lambda item: iff( item.status in \
+ [ model.ToolShedRepository.installation_status.NEW,
+ model.ToolShedRepository.installation_status.CLONING,
+ model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS,
+ model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES,
+ model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES,
+ model.ToolShedRepository.installation_status.UNINSTALLED ], \
+ None, dict( action="manage_repository", id=item.id ) ) ),
+ filterable="advanced" ),
+ DescriptionColumn( "Description",
+ filterable="advanced" ),
+ OwnerColumn( "Owner",
+ filterable="advanced" ),
+ RevisionColumn( "Revision",
+ filterable="advanced" ),
+ StatusColumn( "Installation Status",
+ filterable="advanced" ),
+ ]
+ operations = []
+ def build_initial_query( self, trans, **kwd ):
+ clause_list = []
+ tool_shed_repository_ids = util.listify( kwd.get( 'tool_shed_repository_ids', None ) )
+ if tool_shed_repository_ids:
+ for tool_shed_repository_id in tool_shed_repository_ids:
+ clause_list.append( self.model_class.table.c.id == trans.security.decode_id( tool_shed_repository_id ) )
+ if clause_list:
+ return trans.sa_session.query( self.model_class ) \
+ .filter( or_( *clause_list ) )
+ for tool_shed_repository in trans.sa_session.query( self.model_class ) \
+ .filter( self.model_class.table.c.deleted == False ):
+ if tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status.NEW,
+ trans.model.ToolShedRepository.installation_status.CLONING,
+ trans.model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS,
+ trans.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES,
+ trans.model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES ]:
+ clause_list.append( self.model_class.table.c.id == trans.security.decode_id( tool_shed_repository.id ) )
+ if clause_list:
+ return trans.sa_session.query( self.model_class ) \
+ .filter( or_( *clause_list ) )
+ return trans.sa_session.query( self.model_class ) \
+ .filter( self.model_class.table.c.status == trans.model.ToolShedRepository.installation_status.NEW )
+ def apply_query_filter( self, trans, query, **kwd ):
+ tool_shed_repository_id = kwd.get( 'tool_shed_repository_id', None )
+ if tool_shed_repository_id:
+ return query.filter_by( tool_shed_repository_id=trans.security.decode_id( tool_shed_repository_id ) )
+ return query
+
class ToolDependencyGrid( grids.Grid ):
class NameColumn( grids.TextColumn ):
def get_value( self, trans, grid, tool_dependency ):
@@ -90,18 +211,17 @@
class StatusColumn( grids.TextColumn ):
def get_value( self, trans, grid, tool_dependency ):
if tool_dependency.status in [ trans.model.ToolDependency.installation_status.INSTALLING ]:
- return tool_dependency.status
- else:
- if tool_dependency.status in [ trans.model.ToolDependency.installation_status.NEVER_INSTALLED,
- trans.model.ToolDependency.installation_status.UNINSTALLED ]:
- bgcolor = trans.model.ToolDependency.states.UNINSTALLED
- elif tool_dependency.status in [ trans.model.ToolDependency.installation_status.ERROR ]:
- bgcolor = trans.model.ToolDependency.states.ERROR
- elif tool_dependency.status in [ trans.model.ToolDependency.installation_status.INSTALLED ]:
- bgcolor = trans.model.ToolDependency.states.OK
- rval = '<div class="count-box state-color-%s" id="ToolDependencyStatus-%s">' % ( bgcolor, trans.security.encode_id( tool_dependency.id ) )
- rval += '%s</div>' % tool_dependency.status
- return rval
+ bgcolor = trans.model.ToolDependency.states.INSTALLING
+ elif tool_dependency.status in [ trans.model.ToolDependency.installation_status.NEVER_INSTALLED,
+ trans.model.ToolDependency.installation_status.UNINSTALLED ]:
+ bgcolor = trans.model.ToolDependency.states.UNINSTALLED
+ elif tool_dependency.status in [ trans.model.ToolDependency.installation_status.ERROR ]:
+ bgcolor = trans.model.ToolDependency.states.ERROR
+ elif tool_dependency.status in [ trans.model.ToolDependency.installation_status.INSTALLED ]:
+ bgcolor = trans.model.ToolDependency.states.OK
+ rval = '<div class="count-box state-color-%s" id="ToolDependencyStatus-%s">' % ( bgcolor, trans.security.encode_id( tool_dependency.id ) )
+ rval += '%s</div>' % tool_dependency.status
+ return rval
webapp = "galaxy"
title = "Tool Dependencies"
@@ -138,7 +258,7 @@
model.ToolDependency.installation_status.ERROR ] ) )
]
def build_initial_query( self, trans, **kwd ):
- tool_dependency_ids = kwd.get( 'tool_dependency_ids', None )
+ tool_dependency_ids = util.listify( kwd.get( 'tool_dependency_ids', None ) )
if tool_dependency_ids:
clause_list = []
for tool_dependency_id in tool_dependency_ids:
@@ -148,13 +268,14 @@
return trans.sa_session.query( self.model_class )
def apply_query_filter( self, trans, query, **kwd ):
tool_dependency_id = kwd.get( 'tool_dependency_id', None )
- if not tool_dependency_id:
- return query
- return query.filter_by( tool_dependency_id=trans.security.decode_id( tool_dependency_id ) )
+ if tool_dependency_id:
+ return query.filter_by( tool_dependency_id=trans.security.decode_id( tool_dependency_id ) )
+ return query
class AdminToolshed( AdminGalaxy ):
- repository_list_grid = RepositoryListGrid()
+ installed_repository_grid = InstalledRepositoryGrid()
+ repository_installation_grid = RepositoryInstallationGrid()
tool_dependency_grid = ToolDependencyGrid()
@web.expose
@@ -165,6 +286,7 @@
shed_tool_conf, tool_path, relative_install_dir = get_tool_panel_config_tool_path_install_dir( trans.app, repository )
repository_clone_url = self.__generate_clone_url( trans, repository )
repository.deleted = False
+ repository.status = trans.model.ToolShedRepository.installation_status.INSTALLED
trans.sa_session.add( repository )
trans.sa_session.flush()
if repository.includes_tools:
@@ -220,8 +342,8 @@
if operation == "deactivate or uninstall":
return self.deactivate_or_uninstall_repository( trans, **kwd )
if 'message' not in kwd or not kwd[ 'message' ]:
- kwd[ 'message' ] = 'Names of repositories for which updates are available are highlighted in red.'
- return self.repository_list_grid( trans, **kwd )
+ kwd[ 'message' ] = 'Names of repositories for which updates are available are highlighted in yellow.'
+ return self.installed_repository_grid( trans, **kwd )
@web.expose
@web.require_admin
def browse_tool_dependency( self, trans, **kwd ):
@@ -262,52 +384,23 @@
return trans.response.send_redirect( url )
@web.expose
@web.require_admin
- def confirm_tool_dependency_install( self, trans, **kwd ):
- """Display a page enabling the Galaxy administrator to choose to install tool dependencies for a tool shed repository they are installing."""
- # This method is called from the tool shed (never Galaxy) when a tool shed repository that includes a file named tool_dependencies.xml
- # is being installed into a local Galaxy instance.
- message = kwd.get( 'message', '' )
- status = kwd.get( 'status', 'done' )
- tool_shed_url = kwd[ 'tool_shed_url' ]
- repo_info_dict = kwd[ 'repo_info_dict' ]
- includes_tools = util.string_as_bool( kwd.get( 'includes_tools', False ) )
- # Decode the encoded repo_info_dict param value.
- dict_with_tool_dependencies = tool_shed_decode( repo_info_dict )
- # The repo_info_dict includes tool dependencies which we need to display so the user knows what will be installed.
- new_repo_info_dict = {}
- for name, repo_info_tuple in dict_with_tool_dependencies.items():
- description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, tool_dependencies = repo_info_tuple
- # Create a new repo_info_dict by eliminating tool-dependencies from the repo_info_tuple.
- new_repo_info_dict[ name ] = ( description, repository_clone_url, changeset_revision, ctx_rev )
- repo_info_dict = tool_shed_encode( new_repo_info_dict )
- install_tool_dependencies_check_box = CheckboxField( 'install_tool_dependencies', checked=True )
- return trans.fill_template( '/admin/tool_shed_repository/confirm_tool_dependency_install.mako',
- tool_shed_url=tool_shed_url,
- repo_info_dict=repo_info_dict,
- dict_with_tool_dependencies=dict_with_tool_dependencies,
- includes_tools=includes_tools,
- install_tool_dependencies_check_box=install_tool_dependencies_check_box,
- message=message,
- status=status )
- @web.expose
- @web.require_admin
def deactivate_or_uninstall_repository( self, trans, **kwd ):
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
remove_from_disk = params.get( 'remove_from_disk', '' )
remove_from_disk_checked = CheckboxField.is_checked( remove_from_disk )
- repository = get_repository( trans, kwd[ 'id' ] )
- shed_tool_conf, tool_path, relative_install_dir = get_tool_panel_config_tool_path_install_dir( trans.app, repository )
+ tool_shed_repository = get_repository( trans, kwd[ 'id' ] )
+ shed_tool_conf, tool_path, relative_install_dir = get_tool_panel_config_tool_path_install_dir( trans.app, tool_shed_repository )
repository_install_dir = os.path.abspath ( relative_install_dir )
errors = ''
if params.get( 'deactivate_or_uninstall_repository_button', False ):
- if repository.includes_tools:
+ if tool_shed_repository.includes_tools:
# Handle tool panel alterations.
- remove_from_tool_panel( trans, repository, shed_tool_conf, uninstall=remove_from_disk_checked )
- if repository.includes_datatypes:
+ remove_from_tool_panel( trans, tool_shed_repository, shed_tool_conf, uninstall=remove_from_disk_checked )
+ if tool_shed_repository.includes_datatypes:
# Deactivate proprietary datatypes.
- installed_repository_dict = load_installed_datatypes( trans.app, repository, repository_install_dir, deactivate=True )
+ installed_repository_dict = load_installed_datatypes( trans.app, tool_shed_repository, repository_install_dir, deactivate=True )
if installed_repository_dict[ 'converter_path' ]:
load_installed_datatype_converters( trans.app, installed_repository_dict, deactivate=True )
if installed_repository_dict[ 'display_path' ]:
@@ -322,24 +415,28 @@
log.debug( "Error removing repository installation directory %s: %s" % ( str( repository_install_dir ), str( e ) ) )
removed = False
if removed:
- repository.uninstalled = True
+ tool_shed_repository.uninstalled = True
# Remove all installed tool dependencies.
- for tool_dependency in repository.installed_tool_dependencies:
+ for tool_dependency in tool_shed_repository.installed_tool_dependencies:
uninstalled, error_message = remove_tool_dependency( trans, tool_dependency )
if error_message:
errors = '%s %s' % ( errors, error_message )
- repository.deleted = True
- trans.sa_session.add( repository )
+ tool_shed_repository.deleted = True
+ if remove_from_disk_checked:
+ tool_shed_repository.status = trans.model.ToolShedRepository.installation_status.UNINSTALLED
+ else:
+ tool_shed_repository.status = trans.model.ToolShedRepository.installation_status.DEACTIVATED
+ trans.sa_session.add( tool_shed_repository )
trans.sa_session.flush()
if remove_from_disk_checked:
- message = 'The repository named <b>%s</b> has been uninstalled. ' % repository.name
+ message = 'The repository named <b>%s</b> has been uninstalled. ' % tool_shed_repository.name
if errors:
message += 'Attempting to uninstall tool dependencies resulted in errors: %s' % errors
status = 'error'
else:
status = 'done'
else:
- message = 'The repository named <b>%s</b> has been deactivated. ' % repository.name
+ message = 'The repository named <b>%s</b> has been deactivated. ' % tool_shed_repository.name
status = 'done'
return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
action='browse_repositories',
@@ -347,7 +444,7 @@
status=status ) )
remove_from_disk_check_box = CheckboxField( 'remove_from_disk', checked=remove_from_disk_checked )
return trans.fill_template( '/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako',
- repository=repository,
+ repository=tool_shed_repository,
remove_from_disk_check_box=remove_from_disk_check_box,
message=message,
status=status )
@@ -365,6 +462,20 @@
galaxy_url = url_for( '/', qualified=True )
url = '%srepository/find_workflows?galaxy_url=%s&webapp=galaxy&no_reset=true' % ( tool_shed_url, galaxy_url )
return trans.response.send_redirect( url )
+ def generate_tool_path( self, repository_clone_url, changeset_revision ):
+ """
+ Generate a tool path that guarantees repositories with the same name will always be installed
+ in different directories. The tool path will be of the form:
+ <tool shed url>/repos/<repository owner>/<repository name>/<installed changeset revision>
+ http://test@bx.psu.edu:9009/repos/test/filter
+ """
+ tmp_url = clean_repository_clone_url( repository_clone_url )
+ # Now tmp_url is something like: bx.psu.edu:9009/repos/some_username/column
+ items = tmp_url.split( 'repos' )
+ tool_shed_url = items[ 0 ]
+ repo_path = items[ 1 ]
+ tool_shed_url = clean_tool_shed_url( tool_shed_url )
+ return '%s/repos%s/%s' % ( tool_shed_url, repo_path, changeset_revision )
@web.json
@web.require_admin
def get_file_contents( self, trans, file_path ):
@@ -374,6 +485,23 @@
return get_repository_file_contents( file_path )
@web.expose
@web.require_admin
+ def initiate_repository_installation( self, trans, shed_repository_ids, encoded_kwd ):
+ tsr_ids = util.listify( shed_repository_ids )
+ tool_shed_repositories = []
+ for tsr_id in tsr_ids:
+ tsr = trans.sa_session.query( trans.model.ToolShedRepository ).get( trans.security.decode_id( tsr_id ) )
+ tool_shed_repositories.append( tsr )
+ clause_list = []
+ for tsr_id in tsr_ids:
+ clause_list.append( trans.model.ToolShedRepository.table.c.id == trans.security.decode_id( tsr_id ) )
+ query = trans.sa_session.query( trans.model.ToolShedRepository ).filter( or_( *clause_list ) )
+ return trans.fill_template( 'admin/tool_shed_repository/initiate_repository_installation.mako',
+ encoded_kwd=encoded_kwd,
+ query=query,
+ tool_shed_repositories=tool_shed_repositories,
+ initiate_repository_installation_ids=shed_repository_ids )
+ @web.expose
+ @web.require_admin
def initiate_tool_dependency_installation( self, trans, tool_dependencies ):
"""Install specified dependencies for repository tools."""
# Get the tool_shed_repository from one of the tool_dependencies.
@@ -403,9 +531,10 @@
else:
message = "Installed tool dependencies: %s" % ','.join( td.name for td in installed_tool_dependencies )
status = 'done'
+ td_ids = [ trans.security.encode_id( td.id ) for td in tool_shed_repository.tool_dependencies ]
return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
action='manage_tool_dependencies',
- tool_dependency_ids=tool_dependency_ids,
+ tool_dependency_ids=td_ids,
message=message,
status=status ) )
@web.expose
@@ -423,22 +552,33 @@
message = kwd.get( 'message', '' )
status = kwd.get( 'status', 'done' )
tool_shed_url = kwd[ 'tool_shed_url' ]
- repo_info_dict = kwd[ 'repo_info_dict' ]
new_tool_panel_section = kwd.get( 'new_tool_panel_section', '' )
tool_panel_section = kwd.get( 'tool_panel_section', '' )
includes_tools = util.string_as_bool( kwd.get( 'includes_tools', False ) )
+ includes_tool_dependencies = util.string_as_bool( kwd.get( 'includes_tool_dependencies', False ) )
+ if includes_tool_dependencies:
+ dict_with_tool_dependencies = tool_shed_decode( kwd[ 'repo_info_dict' ] )
+ # The repo_info_dict includes tool dependencies which we need to display so the user knows what will be installed.
+ repo_info_dict = {}
+ for name, repo_info_tuple in dict_with_tool_dependencies.items():
+ description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, tool_dependencies = repo_info_tuple
+ # Create a new repo_info_dict by eliminating tool_dependencies from the repo_info_tuple.
+ repo_info_dict[ name ] = ( description, repository_clone_url, changeset_revision, ctx_rev )
+ else:
+ dict_with_tool_dependencies = {}
+ repo_info_dict = tool_shed_decode( kwd[ 'repo_info_dict' ] )
install_tool_dependencies = kwd.get( 'install_tool_dependencies', '' )
+ tool_section = None
if not includes_tools or ( includes_tools and kwd.get( 'select_tool_panel_section_button', False ) ):
if includes_tools:
install_tool_dependencies = CheckboxField.is_checked( install_tool_dependencies )
shed_tool_conf = kwd[ 'shed_tool_conf' ]
else:
install_tool_dependencies = False
- # If installing a repository that includes no tools, get the relative tool_path from the file
- # to which the migrated_tools_config setting points.
+ # If installing a repository that includes no tools, get the relative tool_path from the file to which the
+ # migrated_tools_config setting points.
shed_tool_conf = trans.app.config.migrated_tools_config
- # Get the tool path by searching the list of shed_tool_confs for the dictionary
- # that contains the information about shed_tool_conf.
+ # Get the tool path by searching the list of shed_tool_confs for the dictionary that contains the information about shed_tool_conf.
for shed_tool_conf_dict in trans.app.toolbox.shed_tool_confs:
config_filename = shed_tool_conf_dict[ 'config_filename' ]
if config_filename == shed_tool_conf:
@@ -471,79 +611,62 @@
tool_section = trans.app.toolbox.tool_panel[ section_key ]
else:
tool_section = None
- # Decode the encoded repo_info_dict param value.
- repo_info_dict = tool_shed_decode( repo_info_dict )
- # Clone the repository to the configured location.
- installed_repository_names = []
+ # Make sure all tool_shed_repository records exist.
+ new_tool_shed_repositories = []
for name, repo_info_tuple in repo_info_dict.items():
description, repository_clone_url, changeset_revision, ctx_rev = repo_info_tuple
- clone_dir = os.path.join( tool_path, self.__generate_tool_path( repository_clone_url, changeset_revision ) )
+ clone_dir = os.path.join( tool_path, self.generate_tool_path( repository_clone_url, changeset_revision ) )
relative_install_dir = os.path.join( clone_dir, name )
- if os.path.exists( clone_dir ):
- # Repository and revision has already been cloned.
- message += 'Revision <b>%s</b> of repository <b>%s</b> was previously installed.<br/>' % ( changeset_revision, name )
+ owner = get_repository_owner( clean_repository_clone_url( repository_clone_url ) )
+ # Make sure the repository was not already installed.
+ installed_changeset_revision = self.repository_was_previously_installed( trans, tool_shed_url, name, repo_info_tuple, clone_dir )
+ if installed_changeset_revision:
+ message = "Tool shed repository <b>%s</b> with owner <b>%s</b> and changeset revision <b>%s</b> " % ( name, owner, changeset_revision )
+ message += "was previously installed using changeset revision <b>%s</b>. You can get " % installed_changeset_revision
+ message += "the latest updates for the installed repository using the <b>Get updates</b> option from the repository's "
+ message += "<b>Repository Actions</b> pop-up menu."
+ status = 'error'
else:
- clone_repository( repository_clone_url, os.path.abspath( relative_install_dir ), ctx_rev )
- owner = get_repository_owner( clean_repository_clone_url( repository_clone_url ) )
- tool_shed = clean_tool_shed_url( tool_shed_url )
- tool_shed_repository, metadata_dict, = load_repository_contents( trans,
- repository_name=name,
- description=description,
- owner=owner,
- installed_changeset_revision=changeset_revision,
- current_changeset_revision=changeset_revision,
- ctx_rev=ctx_rev,
- tool_path=tool_path,
- repository_clone_url=repository_clone_url,
- relative_install_dir=relative_install_dir,
- tool_shed=tool_shed,
- tool_section=tool_section,
- shed_tool_conf=shed_tool_conf )
- if 'tools' in metadata_dict:
- # Get the tool_versions from the tool shed for each tool in the installed change set.
- url = '%srepository/get_tool_versions?name=%s&owner=%s&changeset_revision=%s&webapp=galaxy&no_reset=true' % \
- ( tool_shed_url, name, owner, changeset_revision )
- response = urllib2.urlopen( url )
- text = response.read()
- response.close()
- if text:
- tool_version_dicts = from_json_string( text )
- handle_tool_versions( trans.app, tool_version_dicts, tool_shed_repository )
- else:
- message += "Version information for the tools included in the <b>%s</b> repository is missing. " % name
- message += "Reset all of this repository's metadata in the tool shed, then set the installed tool versions "
- message += "from the installed repository's <b>Repository Actions</b> menu. "
- status = 'error'
- installed_repository_names.append( name )
- if installed_repository_names:
- installed_repository_names.sort()
- num_repositories_installed = len( installed_repository_names )
- if tool_section:
- message += 'Installed %d %s and all tools were loaded into tool panel section <b>%s</b>:<br/>Installed repositories: ' % \
- ( num_repositories_installed,
- inflector.cond_plural( num_repositories_installed, 'repository' ),
- tool_section.name )
- else:
- message += 'Installed %d %s and all tools were loaded into the tool panel outside of any sections.<br/>Installed repositories: ' % \
- ( num_repositories_installed,
- inflector.cond_plural( num_repositories_installed, 'repository' ) )
- for i, repo_name in enumerate( installed_repository_names ):
- if i == len( installed_repository_names ) -1:
- message += '%s.<br/>' % repo_name
- else:
- message += '%s, ' % repo_name
- if install_tool_dependencies:
- tool_dependency_ids = [ trans.security.encode_id( td.id ) for td in tool_shed_repository.missing_tool_dependencies ]
+ print "Adding new row (or updating an existing row) for repository '%s' in the tool_shed_repository table." % name
+ tool_shed_repository = create_or_update_tool_shed_repository( app=trans.app,
+ name=name,
+ description=description,
+ installed_changeset_revision=changeset_revision,
+ ctx_rev=ctx_rev,
+ repository_clone_url=repository_clone_url,
+ metadata_dict={},
+ status=trans.model.ToolShedRepository.installation_status.NEW,
+ current_changeset_revision=changeset_revision,
+ owner=owner,
+ dist_to_shed=False )
+ new_tool_shed_repositories.append( tool_shed_repository )
+ if new_tool_shed_repositories:
+ tsrids_list = [ trans.security.encode_id( tsr.id ) for tsr in new_tool_shed_repositories ]
+ new_kwd = dict( includes_tool_dependencies=kwd.get( 'includes_tool_dependencies', False ),
+ includes_tools=kwd.get( 'includes_tools', False ),
+ install_tool_dependencies=install_tool_dependencies,
+ repo_info_dict=kwd[ 'repo_info_dict' ],
+ message=message,
+ new_tool_panel_section=kwd.get( 'new_tool_panel_section', '' ),
+ shed_tool_conf = kwd[ 'shed_tool_conf' ],
+ status=status,
+ tool_panel_section=kwd.get( 'tool_panel_section', '' ),
+ tool_path=tool_path,
+ tool_section=tool_section,
+ tool_shed_repository_ids=tsrids_list,
+ tool_shed_url=kwd[ 'tool_shed_url' ] )
+ encoded_kwd = tool_shed_encode( new_kwd )
+ tsrids_str = ','.join( tsrids_list )
return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
- action='manage_tool_dependencies',
- operation='install',
- tool_dependency_ids=tool_dependency_ids,
- status=status,
- message=message ) )
- return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
- action='browse_repositories',
- message=message,
- status=status ) )
+ action='initiate_repository_installation',
+ shed_repository_ids=tsrids_str,
+ encoded_kwd=encoded_kwd ) )
+ else:
+ kwd[ 'message' ] = message
+ kwd[ 'status' ] = status
+ return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
+ action='manage_repositories',
+ **kwd ) )
if len( trans.app.toolbox.shed_tool_confs ) > 1:
shed_tool_conf_select_field = build_shed_tool_conf_select_field( trans )
shed_tool_conf = None
@@ -553,35 +676,35 @@
shed_tool_conf = shed_tool_conf.replace( './', '', 1 )
shed_tool_conf_select_field = None
tool_panel_section_select_field = build_tool_panel_section_select_field( trans )
- if includes_tools:
+ if includes_tools and len( repo_info_dict ) == 1:
# If we're installing a single repository that contains a readme file, get it's contents to display.
- decoded_repo_info_dict = tool_shed_decode( repo_info_dict )
- if len( decoded_repo_info_dict ) == 1:
- name = decoded_repo_info_dict.keys()[ 0 ]
- repo_info_tuple = decoded_repo_info_dict[ name ]
- description, repository_clone_url, changeset_revision, ctx_rev = repo_info_tuple
- owner = get_repository_owner( clean_repository_clone_url( repository_clone_url ) )
- url = '%srepository/get_readme?name=%s&owner=%s&changeset_revision=%s&webapp=galaxy&no_reset=true' % ( tool_shed_url, name, owner, changeset_revision )
- response = urllib2.urlopen( url )
- raw_text = response.read()
- response.close()
- readme_text = ''
- for i, line in enumerate( raw_text ):
- readme_text = '%s%s' % ( readme_text, to_html_str( line ) )
- if len( readme_text ) > MAX_CONTENT_SIZE:
- large_str = '\nFile contents truncated because file size is larger than maximum viewing size of %s\n' % util.nice_size( MAX_CONTENT_SIZE )
- readme_text = '%s%s' % ( readme_text, to_html_str( large_str ) )
- break
- else:
- readme_text = ''
+ name = repo_info_dict.keys()[ 0 ]
+ repo_info_tuple = repo_info_dict[ name ]
+ description, repository_clone_url, changeset_revision, ctx_rev = repo_info_tuple
+ repository_owner = get_repository_owner( clean_repository_clone_url( repository_clone_url ) )
+ url = '%srepository/get_readme?name=%s&owner=%s&changeset_revision=%s&webapp=galaxy&no_reset=true' % \
+ ( tool_shed_url, name, repository_owner, changeset_revision )
+ response = urllib2.urlopen( url )
+ raw_text = response.read()
+ response.close()
+ readme_text = ''
+ for i, line in enumerate( raw_text ):
+ readme_text = '%s%s' % ( readme_text, to_html_str( line ) )
+ if len( readme_text ) > MAX_CONTENT_SIZE:
+ large_str = '\nFile contents truncated because file size is larger than maximum viewing size of %s\n' % util.nice_size( MAX_CONTENT_SIZE )
+ readme_text = '%s%s' % ( readme_text, to_html_str( large_str ) )
+ break
else:
- readme_text = ''
+ readme_text = ''
+ install_tool_dependencies_check_box = CheckboxField( 'install_tool_dependencies', checked=True )
return trans.fill_template( '/admin/tool_shed_repository/select_tool_panel_section.mako',
tool_shed_url=tool_shed_url,
- repo_info_dict=repo_info_dict,
+ repo_info_dict=kwd[ 'repo_info_dict' ],
+ dict_with_tool_dependencies=dict_with_tool_dependencies,
shed_tool_conf=shed_tool_conf,
includes_tools=includes_tools,
- install_tool_dependencies=install_tool_dependencies,
+ includes_tool_dependencies=includes_tool_dependencies,
+ install_tool_dependencies_check_box=install_tool_dependencies_check_box,
shed_tool_conf_select_field=shed_tool_conf_select_field,
tool_panel_section_select_field=tool_panel_section_select_field,
new_tool_panel_section=new_tool_panel_section,
@@ -610,10 +733,10 @@
tool_dependencies_for_installation.append( tool_dependency )
if tool_dependencies_for_installation:
# Redirect back to the ToolDependencyGrid before initiating installation.
- tool_dependency_ids = [ trans.security.encode_id( td.id ) for td in tool_dependencies_for_installation ]
+ encoded_tool_dependency_for_installation_ids = [ trans.security.encode_id( td.id ) for td in tool_dependencies_for_installation ]
new_kwd = dict( action='manage_tool_dependencies',
operation='initiate_tool_dependency_installation',
- tool_dependency_ids=tool_dependency_ids,
+ tool_dependency_ids=encoded_tool_dependency_for_installation_ids,
message=message,
status=status )
return self.tool_dependency_grid( trans, **new_kwd )
@@ -631,12 +754,196 @@
status=status )
@web.expose
@web.require_admin
+ def install_tool_shed_repositories( self, trans, tool_shed_repositories, **kwd ):
+ """Install specified tool shed repositories."""
+ repo_info_dict = tool_shed_decode( kwd[ 'repo_info_dict' ] )
+ tool_path = kwd[ 'tool_path' ]
+ includes_tool_dependencies = util.string_as_bool( kwd[ 'includes_tool_dependencies' ] )
+ install_tool_dependencies = CheckboxField.is_checked( kwd.get( 'install_tool_dependencies', '' ) )
+ for tool_shed_repository in tool_shed_repositories:
+ # Clone each repository to the configured location.
+ update_tool_shed_repository_status( trans.app, tool_shed_repository, trans.model.ToolShedRepository.installation_status.CLONING )
+ repo_info_tuple = repo_info_dict[ tool_shed_repository.name ]
+ if includes_tool_dependencies:
+ description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, tool_dependencies = repo_info_tuple
+ else:
+ description, repository_clone_url, changeset_revision, ctx_rev = repo_info_tuple
+ clone_dir = os.path.join( tool_path, self.generate_tool_path( repository_clone_url, tool_shed_repository.installed_changeset_revision ) )
+ relative_install_dir = os.path.join( clone_dir, tool_shed_repository.name )
+ clone_repository( repository_clone_url, os.path.abspath( relative_install_dir ), ctx_rev )
+ self.handle_repository_contents( trans,
+ tool_shed_repository=tool_shed_repository,
+ tool_path=tool_path,
+ repository_clone_url=repository_clone_url,
+ relative_install_dir=relative_install_dir,
+ tool_shed=tool_shed_repository.tool_shed,
+ tool_section=kwd.get( 'tool_section', '' ),
+ shed_tool_conf=kwd.get( 'shed_tool_conf', '' ) )
+ trans.sa_session.refresh( tool_shed_repository )
+ metadata = tool_shed_repository.metadata
+ if 'tools' in metadata:
+ # Get the tool_versions from the tool shed for each tool in the installed change set.
+ update_tool_shed_repository_status( trans.app,
+ tool_shed_repository,
+ trans.model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS )
+ tool_shed_url = get_url_from_repository_tool_shed( trans.app, tool_shed_repository )
+ url = '%s/repository/get_tool_versions?name=%s&owner=%s&changeset_revision=%s&webapp=galaxy&no_reset=true' % \
+ ( tool_shed_url, tool_shed_repository.name, tool_shed_repository.owner, tool_shed_repository.changeset_revision )
+ response = urllib2.urlopen( url )
+ text = response.read()
+ response.close()
+ if text:
+ tool_version_dicts = from_json_string( text )
+ handle_tool_versions( trans.app, tool_version_dicts, tool_shed_repository )
+ else:
+ message += "Version information for the tools included in the <b>%s</b> repository is missing. " % name
+ message += "Reset all of this repository's metadata in the tool shed, then set the installed tool versions "
+ message += "from the installed repository's <b>Repository Actions</b> menu. "
+ status = 'error'
+ if install_tool_dependencies and tool_shed_repository.tool_dependencies and 'tool_dependencies' in metadata:
+ work_dir = make_tmp_directory()
+ # Install tool dependencies.
+ update_tool_shed_repository_status( trans.app,
+ tool_shed_repository,
+ trans.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES )
+ # Get the tool_dependencies.xml file from the repository.
+ tool_dependencies_config = get_config_from_repository( trans.app,
+ 'tool_dependencies.xml',
+ tool_shed_repository,
+ tool_shed_repository.installed_changeset_revision,
+ work_dir )
+ installed_tool_dependencies = handle_tool_dependencies( app=trans.app,
+ tool_shed_repository=tool_shed_repository,
+ tool_dependencies_config=tool_dependencies_config,
+ tool_dependencies=tool_shed_repository.tool_dependencies )
+ try:
+ shutil.rmtree( work_dir )
+ except:
+ pass
+ if 'datatypes' in metadata:
+ update_tool_shed_repository_status( trans.app,
+ tool_shed_repository,
+ trans.model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES )
+ work_dir = make_tmp_directory()
+ datatypes_config = get_config_from_repository( trans.app,
+ 'datatypes_conf.xml',
+ tool_shed_repository,
+ tool_shed_repository.installed_changeset_revision,
+ work_dir )
+ # Load proprietary data types required by tools.
+ converter_path, display_path = alter_config_and_load_prorietary_datatypes( trans.app, datatypes_config, relative_install_dir, override=False )
+ if converter_path or display_path:
+ # Create a dictionary of tool shed repository related information.
+ repository_dict = create_repository_dict_for_proprietary_datatypes( tool_shed=self.tool_shed,
+ name=tool_shed_repository.name,
+ owner=tool_shed_repository.owner,
+ installed_changeset_revision=tool_shed_repository.installed_changeset_revision,
+ tool_dicts=metadata.get( 'tools', [] ),
+ converter_path=converter_path,
+ display_path=display_path )
+ if converter_path:
+ # Load proprietary datatype converters
+ trans.app.datatypes_registry.load_datatype_converters( trans.app.toolbox, installed_repository_dict=repository_dict )
+ if display_path:
+ # Load proprietary datatype display applications
+ trans.app.datatypes_registry.load_display_applications( installed_repository_dict=repository_dict )
+ try:
+ shutil.rmtree( work_dir )
+ except:
+ pass
+ update_tool_shed_repository_status( trans.app, tool_shed_repository, trans.model.ToolShedRepository.installation_status.INSTALLED )
+ tsr_ids_for_monitoring = [ trans.security.encode_id( tsr.id ) for tsr in tool_shed_repositories ]
+ return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
+ action='monitor_repository_installation',
+ tool_shed_repository_ids=tsr_ids_for_monitoring ) )
+ def handle_repository_contents( self, trans, tool_shed_repository, tool_path, repository_clone_url, relative_install_dir, tool_shed=None,
+ tool_section=None, shed_tool_conf=None ):
+ """
+ Generate the metadata for the installed tool shed repository, among other things. This method is called from Galaxy (never the tool shed)
+ when an admin is installing a new repository or reinstalling an uninstalled repository.
+ """
+ metadata_dict = generate_metadata_using_disk_files( trans.app.toolbox, relative_install_dir, repository_clone_url )
+ tool_shed_repository.metadata = metadata_dict
+ trans.sa_session.add( tool_shed_repository )
+ trans.sa_session.flush()
+ if 'tool_dependencies' in metadata_dict:
+ tool_dependencies = create_tool_dependency_objects( trans.app, tool_shed_repository, tool_shed_repository.installed_changeset_revision )
+ if 'tools' in metadata_dict:
+ tool_panel_dict = generate_tool_panel_dict_for_new_install( metadata_dict[ 'tools' ], tool_section )
+ repository_tools_tups = get_repository_tools_tups( trans.app, metadata_dict )
+ if repository_tools_tups:
+ # Handle missing data table entries for tool parameters that are dynamically generated select lists.
+ work_dir = make_tmp_directory()
+ repository_tools_tups = handle_missing_data_table_entry( trans.app,
+ tool_shed_repository,
+ tool_shed_repository.changeset_revision,
+ tool_path,
+ repository_tools_tups,
+ work_dir )
+ # Handle missing index files for tool parameters that are dynamically generated select lists.
+ sample_files = metadata_dict.get( 'sample_files', [] )
+ repository_tools_tups, sample_files_copied = handle_missing_index_file( trans.app, tool_path, sample_files, repository_tools_tups )
+ # Copy remaining sample files included in the repository to the ~/tool-data directory of the local Galaxy instance.
+ copy_sample_files( trans.app, sample_files, sample_files_copied=sample_files_copied )
+ add_to_tool_panel( app=trans.app,
+ repository_name=tool_shed_repository.name,
+ repository_clone_url=repository_clone_url,
+ changeset_revision=tool_shed_repository.changeset_revision,
+ repository_tools_tups=repository_tools_tups,
+ owner=tool_shed_repository.owner,
+ shed_tool_conf=shed_tool_conf,
+ tool_panel_dict=tool_panel_dict,
+ new_install=True )
+ try:
+ shutil.rmtree( work_dir )
+ except:
+ pass
+ if 'datatypes' in metadata_dict:
+ update_tool_shed_repository_status( trans.app,
+ tool_shed_repository,
+ trans.model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES )
+ work_dir = make_tmp_directory()
+ datatypes_config = get_config_from_repository( trans.app,
+ 'datatypes_conf.xml',
+ tool_shed_repository,
+ tool_shed_repository.changeset_revision,
+ work_dir )
+ # Load data types required by tools.
+ converter_path, display_path = alter_config_and_load_prorietary_datatypes( trans.app, datatypes_config, relative_install_dir, override=False )
+ if converter_path or display_path:
+ # Create a dictionary of tool shed repository related information.
+ repository_dict = create_repository_dict_for_proprietary_datatypes( tool_shed=tool_shed,
+ name=tool_shed_repository.name,
+ owner=tool_shed_repository.owner,
+ installed_changeset_revision=tool_shed_repository.installed_changeset_revision,
+ tool_dicts=metadata_dict.get( 'tools', [] ),
+ converter_path=converter_path,
+ display_path=display_path )
+ if converter_path:
+ # Load proprietary datatype converters
+ trans.app.datatypes_registry.load_datatype_converters( trans.app.toolbox, installed_repository_dict=repository_dict )
+ if display_path:
+ # Load proprietary datatype display applications
+ trans.app.datatypes_registry.load_display_applications( installed_repository_dict=repository_dict )
+ try:
+ shutil.rmtree( work_dir )
+ except:
+ pass
+ @web.expose
+ @web.require_admin
def manage_repository( self, trans, **kwd ):
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
repository_id = kwd[ 'id' ]
repository = get_repository( trans, repository_id )
+ if repository.status in [ trans.model.ToolShedRepository.installation_status.NEW,
+ trans.model.ToolShedRepository.installation_status.CLONING ]:
+ message = "The repository '%s' is not yet cloned, please try again..."
+ status = 'warning'
+ return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
+ action='monitor_repository_installation',
+ **kwd ) )
description = util.restore_text( params.get( 'description', repository.description ) )
shed_tool_conf, tool_path, relative_install_dir = get_tool_panel_config_tool_path_install_dir( trans.app, repository )
repo_files_dir = os.path.abspath( os.path.join( relative_install_dir, repository.name ) )
@@ -662,6 +969,62 @@
status=status )
@web.expose
@web.require_admin
+ def manage_repositories( self, trans, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ tsrid = params.get( 'tool_shed_repository_id', None )
+ tsridslist = util.listify( params.get( 'tool_shed_repository_ids', None ) )
+ if not tsridslist:
+ tsridslist = util.listify( params.get( 'id', None ) )
+ if tsrid and tsrid not in tsridslist:
+ tsridslist.append( tsrid )
+ if 'operation' in kwd:
+ operation = kwd[ 'operation' ].lower()
+ if not tsridslist:
+ message = 'Select at least 1 tool shed repository to %s.' % operation
+ kwd[ 'message' ] = message
+ kwd[ 'status' ] = 'error'
+ del kwd[ 'operation' ]
+ return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
+ action='manage_repositories',
+ **kwd ) )
+ if operation == 'browse':
+ return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
+ action='browse_repository',
+ **kwd ) )
+ elif operation == 'uninstall':
+ repositories_for_uninstallation = []
+ for repository_id in tool_shed_repository_id:
+ repository = trans.sa_session.query( trans.model.ToolShedRepository ).get( trans.security.decode_id( repository_id ) )
+ if repository.status in [ trans.model.ToolShedRepository.installation_status.INSTALLED,
+ trans.model.ToolShedRepository.installation_status.ERROR ]:
+ repositories_for_uninstallation.append( repository )
+ if repositories_for_uninstallation:
+ return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
+ action='uninstall_repositories',
+ **kwd ) )
+ else:
+ kwd[ 'message' ] = 'All selected tool shed repositories are already uninstalled.'
+ kwd[ 'status' ] = 'error'
+ elif operation == "install":
+ encoded_kwd = kwd[ 'encoded_kwd' ]
+ decoded_kwd = tool_shed_decode( encoded_kwd )
+ tsr_ids = decoded_kwd[ 'tool_shed_repository_ids' ]
+ repositories_for_installation = []
+ for tsr_id in tsr_ids:
+ repository = trans.sa_session.query( trans.model.ToolShedRepository ).get( trans.security.decode_id( tsr_id ) )
+ if repository.status in [ trans.model.ToolShedRepository.installation_status.NEW,
+ trans.model.ToolShedRepository.installation_status.UNINSTALLED ]:
+ repositories_for_installation.append( repository )
+ if repositories_for_installation:
+ self.install_tool_shed_repositories( trans, repositories_for_installation, **decoded_kwd )
+ else:
+ kwd[ 'message' ] = 'All selected tool shed repositories are already installed.'
+ kwd[ 'status' ] = 'error'
+ return self.repository_installation_grid( trans, **kwd )
+ @web.expose
+ @web.require_admin
def manage_tool_dependencies( self, trans, **kwd ):
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
@@ -672,7 +1035,6 @@
tool_dependency_ids = util.listify( params.get( 'id', None ) )
if tool_dependency_id and tool_dependency_id not in tool_dependency_ids:
tool_dependency_ids.append( tool_dependency_id )
- tool_dependencies = []
# We need a tool_shed_repository, so get it from one of the tool_dependencies.
tool_dependency = get_tool_dependency( trans, tool_dependency_ids[ 0 ] )
tool_shed_repository = tool_dependency.tool_shed_repository
@@ -739,6 +1101,18 @@
kwd[ 'message' ] = 'All selected tool dependencies are already installed.'
kwd[ 'status' ] = 'error'
return self.tool_dependency_grid( trans, **kwd )
+ @web.expose
+ @web.require_admin
+ def monitor_repository_installation( self, trans, **kwd ):
+ params = util.Params( kwd )
+ tsrid = params.get( 'tool_shed_repository_id', None )
+ tsridslist = util.listify( params.get( 'tool_shed_repository_ids', None ) )
+ if not tsridslist:
+ tsridslist = util.listify( params.get( 'id', None ) )
+ if tsrid and tsrid not in tsridslist:
+ tsridslist.append( tsrid )
+ kwd[ 'tool_shed_repository_ids' ] = tsridslist
+ return self.repository_installation_grid( trans, **kwd )
@web.json
@web.require_admin
def open_folder( self, trans, folder_path ):
@@ -752,31 +1126,32 @@
message = kwd.get( 'message', '' )
status = kwd.get( 'status', 'done' )
repository_id = kwd[ 'id' ]
- repository = get_repository( trans, repository_id )
+ tool_shed_repository = get_repository( trans, repository_id )
no_changes = kwd.get( 'no_changes', '' )
no_changes_checked = CheckboxField.is_checked( no_changes )
install_tool_dependencies = CheckboxField.is_checked( kwd.get( 'install_tool_dependencies', '' ) )
- shed_tool_conf, tool_path, relative_install_dir = get_tool_panel_config_tool_path_install_dir( trans.app, repository )
- repository_clone_url = generate_clone_url( trans, repository )
- clone_dir = os.path.join( tool_path, self.__generate_tool_path( repository_clone_url, repository.installed_changeset_revision ) )
- relative_install_dir = os.path.join( clone_dir, repository.name )
- tool_shed_url = get_url_from_repository_tool_shed( trans.app, repository )
- if not repository.ctx_rev:
+ shed_tool_conf, tool_path, relative_install_dir = get_tool_panel_config_tool_path_install_dir( trans.app, tool_shed_repository )
+ repository_clone_url = generate_clone_url( trans, tool_shed_repository )
+ clone_dir = os.path.join( tool_path, self.generate_tool_path( repository_clone_url, tool_shed_repository.installed_changeset_revision ) )
+ relative_install_dir = os.path.join( clone_dir, tool_shed_repository.name )
+ tool_shed_url = get_url_from_repository_tool_shed( trans.app, tool_shed_repository )
+ if not tool_shed_repository.ctx_rev:
# The ctx_rev column was introduced late, so may be null for some installed ToolShedRepositories.
- ctx_rev = get_ctx_rev( tool_shed_url, repository.name, repository.owner, repository.installed_changeset_revision )
+ ctx_rev = get_ctx_rev( tool_shed_url, tool_shed_repository.name, tool_shed_repository.owner, tool_shed_repository.installed_changeset_revision )
else:
- ctx_rev = repository.ctx_rev
+ ctx_rev = tool_shed_repository.ctx_rev
+ update_tool_shed_repository_status( trans.app, tool_shed_repository, trans.model.ToolShedRepository.installation_status.CLONING )
clone_repository( repository_clone_url, os.path.abspath( relative_install_dir ), ctx_rev )
# Since we're reinstalling the repository we need to find the latest changeset revision to which is can be updated.
- current_changeset_revision, current_ctx_rev = get_update_to_changeset_revision_and_ctx_rev( trans, repository )
+ current_changeset_revision, current_ctx_rev = get_update_to_changeset_revision_and_ctx_rev( trans, tool_shed_repository )
if current_ctx_rev != ctx_rev:
repo = hg.repository( get_configured_ui(), path=os.path.abspath( relative_install_dir ) )
pull_repository( repo, repository_clone_url, current_changeset_revision )
update_repository( repo, ctx_rev=current_ctx_rev )
tool_section = None
- if repository.includes_tools:
+ metadata = tool_shed_repository.metadata
+ if tool_shed_repository.includes_tools:
# Get the location in the tool panel in which each tool was originally loaded.
- metadata = repository.metadata
if 'tool_panel_section' in metadata:
tool_panel_dict = metadata[ 'tool_panel_section' ]
if not tool_panel_dict:
@@ -829,52 +1204,83 @@
tool_section = trans.app.toolbox.tool_panel[ section_key ]
else:
tool_section = None
- tool_shed_repository, metadata_dict, load_repository_contents( trans,
- repository_name=repository.name,
- description=repository.description,
- owner=repository.owner,
- installed_changeset_revision=repository.installed_changeset_revision,
- current_changeset_revision=current_changeset_revision,
- ctx_rev=ctx_rev,
- tool_path=tool_path,
- repository_clone_url=repository_clone_url,
- relative_install_dir=relative_install_dir,
- tool_shed=repository.tool_shed,
- tool_section=tool_section,
- shed_tool_conf=shed_tool_conf )
- repository.uninstalled = False
- repository.deleted = False
- trans.sa_session.add( repository )
+ self.handle_repository_contents( trans,
+ tool_shed_repository=tool_shed_repository,
+ tool_path=tool_path,
+ repository_clone_url=repository_clone_url,
+ relative_install_dir=relative_install_dir,
+ tool_shed=tool_shed_repository.tool_shed,
+ tool_section=tool_section,
+ shed_tool_conf=shed_tool_conf )
+
+ if install_tool_dependencies and tool_shed_repository.tool_dependencies and 'tool_dependencies' in metadata:
+ # Install tool dependencies.
+ update_tool_shed_repository_status( trans.app,
+ tool_shed_repository,
+ trans.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES )
+ work_dir = make_tmp_directory()
+ # Get the tool_dependencies.xml file from the repository.
+ tool_dependencies_config = get_config_from_repository( trans.app,
+ 'tool_dependencies.xml',
+ tool_shed_repository,
+ tool_shed_repository.installed_changeset_revision,
+ work_dir )
+ installed_tool_dependencies = handle_tool_dependencies( app=trans.app,
+ tool_shed_repository=tool_shed_repository,
+ tool_dependencies_config=tool_dependencies_config,
+ tool_dependencies=tool_dependencies )
+ tool_shed_repository.uninstalled = False
+ tool_shed_repository.deleted = False
+ tool_shed_repository.status = trans.model.ToolShedRepository.installation_status.INSTALLED
+ trans.sa_session.add( tool_shed_repository )
trans.sa_session.flush()
- message += 'The <b>%s</b> repository has been reinstalled. ' % repository.name
- if install_tool_dependencies:
- message += 'The following tool dependencies are now being installed, please wait...'
- tool_dependency_ids = [ trans.security.encode_id( td.id ) for td in tool_shed_repository.missing_tool_dependencies ]
- return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
- action='manage_tool_dependencies',
- operation='install',
- tool_dependency_ids=tool_dependency_ids,
- status=status,
- message=message ) )
return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
action='browse_repositories',
message=message,
status=status ) )
@web.json
- def repository_installation_status_updates( self, trans, id=None, status=None ):
+ def repository_installation_status_updates( self, trans, ids=None, status_list=None ):
# Avoid caching
trans.response.headers[ 'Pragma' ] = 'no-cache'
trans.response.headers[ 'Expires' ] = '0'
- # Create new HTML for any that have changed
- rval = {}
- if id is not None and status is not None:
- repository = trans.sa_session.query( trans.model.ToolShedRepository ).get( trans.security.decode_id( id ) )
- if repository.status != status:
- repository.status = status
- rval[ id ] = { "status": repository.status,
- "html_status": unicode( trans.fill_template( "admin/tool_shed_repository/repository_installation_status.mako",
- repository=repository ),
- 'utf-8' ) }
+ # Create new HTML for any ToolShedRepository records whose status that has changed.
+ rval = []
+ if ids is not None and status_list is not None:
+ ids = util.listify( ids )
+ status_list = util.listify( status_list )
+ for id, status in zip( ids, status_list ):
+ repository = trans.sa_session.query( trans.model.ToolShedRepository ).get( trans.security.decode_id( id ) )
+ if repository.status != status:
+ rval.append( dict( id=id,
+ status=repository.status,
+ html_status=unicode( trans.fill_template( "admin/tool_shed_repository/repository_installation_status.mako",
+ repository=repository ),
+ 'utf-8' ) ) )
+ return rval
+ @web.expose
+ @web.require_admin
+ def repository_was_previously_installed( self, trans, tool_shed_url, repository_name, repo_info_tuple, clone_dir ):
+ # Handle case where the repository was previously installed using an older changeset_revsion, but later the repository was updated
+ # in the tool shed and now we're trying to install the latest changeset revision of the same repository instead of updating the one
+ # that was previously installed.
+ description, repository_clone_url, changeset_revision, ctx_rev = repo_info_tuple
+ if os.path.exists( clone_dir ):
+ # The installed changeset revision already exists on disk.
+ return changeset_revision
+ repository_owner = get_repository_owner( clean_repository_clone_url( repository_clone_url ) )
+ url = '%s/repository/previous_changeset_revisions?galaxy_url=%s&name=%s&owner=%s&changeset_revision=%s&webapp=galaxy&no_reset=true' % \
+ ( tool_shed_url, url_for( '/', qualified=True ), repository_name, repository_owner, changeset_revision )
+ response = urllib2.urlopen( url )
+ text = response.read()
+ response.close()
+ if text:
+ clone_path, clone_directory = os.path.split( clone_dir )
+ changeset_revisions = util.listify( text )
+ for previous_changeset_revision in changeset_revisions:
+ new_clone_dir = os.path.join( clone_path, previous_changeset_revision )
+ if os.path.exists( new_clone_dir ):
+ return previous_changeset_revision
+ return None
@web.expose
@web.require_admin
def reselect_tool_panel_section( self, trans, **kwd ):
@@ -948,18 +1354,19 @@
# Avoid caching
trans.response.headers[ 'Pragma' ] = 'no-cache'
trans.response.headers[ 'Expires' ] = '0'
- # Create new HTML for any that have changed
- rval = {}
+ # Create new HTML for any ToolDependency records whose status that has changed.
+ rval = []
if ids is not None and status_list is not None:
- ids = ids.split( "," )
- status_list = status_list.split( "," )
+ ids = util.listify( ids )
+ status_list = util.listify( status_list )
for id, status in zip( ids, status_list ):
tool_dependency = trans.sa_session.query( trans.model.ToolDependency ).get( trans.security.decode_id( id ) )
if tool_dependency.status != status:
- rval[ id ] = { "status": tool_dependency.status,
- "html_status": unicode( trans.fill_template( "admin/tool_shed_repository/tool_dependency_installation_status.mako",
- tool_dependency=tool_dependency ),
- 'utf-8' ) }
+ rval.append( dict( id=id,
+ status=tool_dependency.status,
+ html_status=unicode( trans.fill_template( "admin/tool_shed_repository/tool_dependency_installation_status.mako",
+ tool_dependency=tool_dependency ),
+ 'utf-8' ) ) )
return rval
@web.expose
@web.require_admin
@@ -992,9 +1399,11 @@
status = 'error'
else:
message = "These tool dependencies have been uninstalled: %s" % ','.join( td.name for td in tool_dependencies_for_uninstallation )
+ tool_shed_repository = tool_dependencies[ 0 ].tool_shed_repository
+ td_ids = [ trans.security.encode_id( td.id ) for td in tool_shed_repository.tool_dependencies ]
return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
action='manage_tool_dependencies',
- tool_dependency_ids=tool_dependency_ids,
+ tool_dependency_ids=td_ids,
status=status,
message=message ) )
return trans.fill_template( '/admin/tool_shed_repository/uninstall_tool_dependencies.mako',
@@ -1081,20 +1490,6 @@
"""Generate the URL for cloning a repository."""
tool_shed_url = get_url_from_repository_tool_shed( trans.app, repository )
return '%s/repos/%s/%s' % ( tool_shed_url, repository.owner, repository.name )
- def __generate_tool_path( self, repository_clone_url, changeset_revision ):
- """
- Generate a tool path that guarantees repositories with the same name will always be installed
- in different directories. The tool path will be of the form:
- <tool shed url>/repos/<repository owner>/<repository name>/<installed changeset revision>
- http://test@bx.psu.edu:9009/repos/test/filter
- """
- tmp_url = clean_repository_clone_url( repository_clone_url )
- # Now tmp_url is something like: bx.psu.edu:9009/repos/some_username/column
- items = tmp_url.split( 'repos' )
- tool_shed_url = items[ 0 ]
- repo_path = items[ 1 ]
- tool_shed_url = clean_tool_shed_url( tool_shed_url )
- return '%s/repos%s/%s' % ( tool_shed_url, repo_path, changeset_revision )
## ---- Utility methods -------------------------------------------------------
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 lib/galaxy/webapps/community/controllers/repository.py
--- a/lib/galaxy/webapps/community/controllers/repository.py
+++ b/lib/galaxy/webapps/community/controllers/repository.py
@@ -10,7 +10,7 @@
from galaxy.util.json import from_json_string, to_json_string
from galaxy.model.orm import *
from galaxy.util.shed_util import get_changectx_for_changeset, get_configured_ui, get_repository_file_contents, make_tmp_directory, NOT_TOOL_CONFIGS
-from galaxy.util.shed_util import open_repository_files_folder, strip_path
+from galaxy.util.shed_util import open_repository_files_folder, reversed_lower_upper_bounded_changelog, strip_path
from galaxy.tool_shed.encoding_util import *
from common import *
@@ -1096,8 +1096,9 @@
repo = hg.repository( get_configured_ui(), repo_dir )
# Default to the received changeset revision and ctx_rev.
update_to_ctx = get_changectx_for_changeset( repo, changeset_revision )
+ ctx_rev = str( update_to_ctx.rev() )
latest_changeset_revision = changeset_revision
- update_dict = dict( changeset_revision=update_to_ctx, ctx_rev=str( update_to_ctx.rev() ) )
+ update_dict = dict( changeset_revision=changeset_revision, ctx_rev=ctx_rev )
if changeset_revision == repository.tip:
# If changeset_revision is the repository tip, there are no additional updates.
return tool_shed_encode( update_dict )
@@ -1227,14 +1228,9 @@
changeset_revision,
str( ctx.rev() ) )
encoded_repo_info_dict = encode( repo_info_dict )
- if includes_tool_dependencies:
- # Redirect back to local Galaxy to present the option to install tool dependencies.
- url = '%sadmin_toolshed/confirm_tool_dependency_install?tool_shed_url=%s&repo_info_dict=%s&includes_tools=%s' % \
- ( galaxy_url, url_for( '/', qualified=True ), encoded_repo_info_dict, str( includes_tools ) )
- else:
- # Redirect back to local Galaxy to perform install.
- url = '%sadmin_toolshed/install_repository?tool_shed_url=%s&repo_info_dict=%s&includes_tools=%s' % \
- ( galaxy_url, url_for( '/', qualified=True ), encoded_repo_info_dict, str( includes_tools ) )
+ # Redirect back to local Galaxy to perform install.
+ url = '%sadmin_toolshed/install_repository?tool_shed_url=%s&repo_info_dict=%s&includes_tools=%s&includes_tool_dependencies=%s' % \
+ ( galaxy_url, url_for( '/', qualified=True ), encoded_repo_info_dict, str( includes_tools ), str( includes_tool_dependencies ) )
return trans.response.send_redirect( url )
@web.expose
def load_invalid_tool( self, trans, repository_id, tool_config, changeset_revision, **kwd ):
@@ -1563,6 +1559,34 @@
message=message,
status=status )
@web.expose
+ def previous_changeset_revisions( self, trans, **kwd ):
+ """
+ Handle a request from a local Galaxy instance. This method will handle the case where the repository was previously installed using an
+ older changeset_revsion, but later the repository was updated in the tool shed and the Galaxy admin is trying to install the latest
+ changeset revision of the same repository instead of updating the one that was previously installed.
+ """
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ # If the request originated with the UpdateManager, it will not include a galaxy_url.
+ galaxy_url = kwd.get( 'galaxy_url', '' )
+ name = params.get( 'name', None )
+ owner = params.get( 'owner', None )
+ changeset_revision = params.get( 'changeset_revision', None )
+ repository = get_repository_by_name_and_owner( trans, name, owner )
+ repo_dir = repository.repo_path
+ repo = hg.repository( get_configured_ui(), repo_dir )
+ # Get the lower bound changeset revision
+ lower_bound_changeset_revision = get_previous_valid_changset_revision( repository, repo, changeset_revision )
+ # Build the list of changeset revision hashes.
+ changeset_hashes = []
+ for changeset in reversed_lower_upper_bounded_changelog( repo, lower_bound_changeset_revision, changeset_revision ):
+ changeset_hashes.append( str( repo.changectx( changeset ) ) )
+ if changeset_hashes:
+ changeset_hashes_str = ','.join( changeset_hashes )
+ return changeset_hashes_str
+ return ''
+ @web.expose
@web.require_login( "rate repositories" )
def rate_repository( self, trans, **kwd ):
""" Rate a repository and return updated rating data. """
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 templates/admin/tool_shed_repository/common.mako
--- a/templates/admin/tool_shed_repository/common.mako
+++ b/templates/admin/tool_shed_repository/common.mako
@@ -54,7 +54,7 @@
url: "${h.url_for( controller='admin_toolshed', action='get_file_contents' )}",
dataType: "json",
data: { file_path: selected_value },
- success : function ( data ) {
+ success : function( data ) {
cell.html( '<label>'+data+'</label>' )
}
});
@@ -69,27 +69,31 @@
<%def name="dependency_status_updater()"><script type="text/javascript">
-
- // Tool dependency status updater - used to update the installation status on the Tool Dependencies grid.
+ // Tool dependency status updater - used to update the installation status on the Tool Dependencies Grid.
// Looks for changes in tool dependency installation status using an async request. Keeps calling itself
// (via setTimeout) until dependency installation status is neither 'Installing' nor 'Building'.
- var tool_dependency_status_updater = function ( dependency_status_list ) {
+ var tool_dependency_status_updater = function( dependency_status_list ) {
// See if there are any items left to track
var empty = true;
- for ( i in dependency_status_list ) {
- empty = false;
- break;
+ for ( var item in dependency_status_list ) {
+ //alert( "item" + item.toSource() );
+ //alert( "dependency_status_list[item] " + dependency_status_list[item].toSource() );
+ //alert( "dependency_status_list[item]['status']" + dependency_status_list[item]['status'] );
+ if ( dependency_status_list[item]['status'] != 'Installed' ) {
+ empty = false;
+ break;
+ }
}
if ( ! empty ) {
setTimeout( function() { tool_dependency_status_updater_callback( dependency_status_list ) }, 3000 );
}
};
- var tool_dependency_status_updater_callback = function ( dependency_status_list ) {
- var ids = []
- var status_list = []
- $.each( dependency_status_list, function ( id, dependency_status ) {
- ids.push( id );
- status_list.push( dependency_status );
+ var tool_dependency_status_updater_callback = function( dependency_status_list ) {
+ var ids = [];
+ var status_list = [];
+ $.each( dependency_status_list, function( index, dependency_status ) {
+ ids.push( dependency_status[ 'id' ] );
+ status_list.push( dependency_status[ 'status' ] );
});
// Make ajax call
$.ajax( {
@@ -97,17 +101,75 @@
url: "${h.url_for( controller='admin_toolshed', action='tool_dependency_status_updates' )}",
dataType: "json",
data: { ids: ids.join( "," ), status_list: status_list.join( "," ) },
- success : function ( data ) {
- $.each( data, function( id, val ) {
+ success : function( data ) {
+ $.each( data, function( index, val ) {
// Replace HTML
- var cell1 = $("#ToolDependencyStatus-" + id);
- cell1.html( val.html_status );
- dependency_status_list[ id ] = val.status;
+ var cell1 = $( "#ToolDependencyStatus-" + val[ 'id' ] );
+ cell1.html( val[ 'html_status' ] );
+ dependency_status_list[ index ] = val;
});
tool_dependency_status_updater( dependency_status_list );
},
error: function() {
- tool_dependency_status_updater( dependency_status_list );
+ alert( "tool_dependency_status_updater_callback failed..." );
+ }
+ });
+ };
+ </script>
+</%def>
+
+<%def name="repository_installation_status_updater()">
+ <script type="text/javascript">
+ // Tool shed repository status updater - used to update the installation status on the Repository Installation Grid.
+ // Looks for changes in repository installation status using an async request. Keeps calling itself (via setTimeout) until
+ // repository installation status is not one of: 'New', 'Cloning', 'Setting tool versions', 'Installing tool dependencies',
+ // 'Loading proprietary datatypes'.
+ var tool_shed_repository_status_updater = function( repository_status_list ) {
+ // See if there are any items left to track
+ //alert( "repository_status_list start " + repository_status_list.toSource() );
+ var empty = true;
+ for ( var item in repository_status_list ) {
+ //alert( "item" + item.toSource() );
+ //alert( "repository_status_list[item] " + repository_status_list[item].toSource() );
+ //alert( "repository_status_list[item]['status']" + repository_status_list[item]['status'] );
+ if (repository_status_list[item]['status'] != 'Installed'){
+ empty = false;
+ break;
+ }
+ }
+ if ( ! empty ) {
+ setTimeout( function() { tool_shed_repository_status_updater_callback( repository_status_list ) }, 3000 );
+ }
+ };
+ var tool_shed_repository_status_updater_callback = function( repository_status_list ) {
+ //alert( repository_status_list );
+ //alert( repository_status_list.toSource() );
+ var ids = [];
+ var status_list = [];
+ $.each( repository_status_list, function( index, repository_status ) {
+ //alert('repository_status '+ repository_status.toSource() );
+ //alert('id '+ repository_status['id'] );
+ //alert( 'status'+ repository_status['status'] );
+ ids.push( repository_status[ 'id' ] );
+ status_list.push( repository_status[ 'status' ] );
+ });
+ // Make ajax call
+ $.ajax( {
+ type: "POST",
+ url: "${h.url_for( controller='admin_toolshed', action='repository_installation_status_updates' )}",
+ dataType: "json",
+ data: { ids: ids.join( "," ), status_list: status_list.join( "," ) },
+ success : function( data ) {
+ $.each( data, function( index, val ) {
+ // Replace HTML
+ var cell1 = $( "#RepositoryStatus-" + val[ 'id' ] );
+ cell1.html( val[ 'html_status' ] );
+ repository_status_list[ index ] = val;
+ });
+ tool_shed_repository_status_updater( repository_status_list );
+ },
+ error: function() {
+ alert( "tool_shed_repository_status_updater_callback failed..." );
}
});
};
@@ -126,71 +188,27 @@
%if can_update:
<script type="text/javascript">
// Tool dependency installation status updater
- tool_dependency_status_updater( {${ ",".join( [ '"%s" : "%s"' % ( trans.security.encode_id( td.id ), td.status ) for td in query ] ) }});
+ tool_dependency_status_updater( [${ ",".join( [ '{"id" : "%s", "status" : "%s"}' % ( trans.security.encode_id( td.id ), td.status ) for td in query ] ) } ] );
</script>
%endif
</%def>
-<%def name="repository_installation_status_updater()">
- <script type="text/javascript">
-
- // Tool shed repository status updater - used to update the installation status on the repository_installation.mako template.
- // Looks for changes in repository installation status using an async request. Keeps calling itself (via setTimeout) until
- // repository installation status is neither 'cloning', 'cloned' nor 'installing tool dependencies'.
- var tool_shed_repository_status_updater = function ( repository_status_list ) {
- // See if there are any items left to track
- var empty = true;
- for ( i in repository_status_list ) {
- empty = false;
- break;
- }
- if ( ! empty ) {
- setTimeout( function() { tool_shed_repository_status_updater_callback( repository_status_list ) }, 3000 );
- }
- };
- var tool_shed_repository_status_updater_callback = function ( repository_status_list ) {
- var ids = []
- var status_list = []
- $.each( repository_status_list, function ( id, repository_status ) {
- ids.push( id );
- status_list.push( repository_status );
- });
- // Make ajax call
- $.ajax( {
- type: "POST",
- url: "${h.url_for( controller='admin_toolshed', action='repository_installation_status_updates' )}",
- dataType: "json",
- data: { id: ids[0], status_list: status_list.join( "," ) },
- success : function ( data ) {
- $.each( data, function( id, val ) {
- // Replace HTML
- var cell1 = $("#RepositoryStatus-" + id);
- cell1.html( val.html_status );
- repository_status_list[ id ] = val.status;
- });
- tool_shed_repository_status_updater( repository_status_list );
- },
- error: function() {
- tool_shed_repository_status_updater( repository_status_list );
- }
- });
- };
- </script>
-</%def>
-
<%def name="repository_installation_updater()"><%
- can_update = True
- if tool_shed_repository:
- can_update = tool_shed_repository.status not in [ trans.model.ToolShedRepository.installation_status.INSTALLED,
- trans.model.ToolShedRepository.installation_status.ERROR,
- trans.model.ToolShedRepository.installation_status.UNINSTALLED ]
+ can_update = False
+ if query.count():
+ for tool_shed_repository in query:
+ if tool_shed_repository.status not in [ trans.model.ToolShedRepository.installation_status.INSTALLED,
+ trans.model.ToolShedRepository.installation_status.ERROR,
+ trans.model.ToolShedRepository.installation_status.DEACTIVATED,
+ trans.model.ToolShedRepository.installation_status.UNINSTALLED ]:
+ can_update = True
+ break
%>
%if can_update:
<script type="text/javascript">
// Tool shed repository installation status updater
- repository_installation_status_updater( {${ ",".join( [ '"%s" : "%s"' % ( trans.security.encode_id( repository.id ), repository.status ) for repository in query ] ) }});
+ tool_shed_repository_status_updater( [${ ",".join( [ '{"id" : "%s", "status" : "%s"}' % ( trans.security.encode_id( tsr.id ), tsr.status ) for tsr in query ] ) } ] );
</script>
%endif
</%def>
-
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 templates/admin/tool_shed_repository/confirm_tool_dependency_install.mako
--- a/templates/admin/tool_shed_repository/confirm_tool_dependency_install.mako
+++ /dev/null
@@ -1,86 +0,0 @@
-<%inherit file="/base.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-
-<% import os %>
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-<div class="warningmessage">
- <p>
- The tool dependencies listed below can be automatically installed with the repository. Installing them provides significant
- benefits and Galaxy includes various features to manage them.
- </p>
- <p>
- Each of these dependencies may require their own build requirements (e.g., CMake, g++, etc). Galaxy will not attempt to install
- these build requirements, so if any are missing from your environment tool dependency installation may partially fail. The
- repository and all of it's contents will be installed in any case.
- </p>
- <p>
- If tool dependency installation fails in any way, you can install the missing build requirements and have Galaxy attempt to install
- the tool dependencies again using the <b>Install tool dependencies</b> pop-up menu option on the <b>Manage repository</b> page.
- </p>
-</div>
-
-<div class="toolForm">
- <div class="toolFormBody">
- <form name="confirm_tool_dependency_install" id="confirm_tool_dependency_install" action="${h.url_for( controller='admin_toolshed', action='install_repository', tool_shed_url=tool_shed_url, repo_info_dict=repo_info_dict, includes_tools=includes_tools )}" method="post" >
- <div style="clear: both"></div>
- <div class="form-row">
- <label>Install tool dependencies?</label>
- ${install_tool_dependencies_check_box.get_html()}
- <div class="toolParamHelp" style="clear: both;">
- Un-check to skip automatic installation of these tool dependencies.
- </div>
- </div>
- <div style="clear: both"></div>
- <div class="form-row">
- <table class="grid">
- <tr><td colspan="4" bgcolor="#D8D8D8"><b>Tool dependencies</b></td></tr>
- <tr>
- <th>Name</th>
- <th>Version</th>
- <th>Type</th>
- <th>Install directory</th>
- </tr>
- %for repository_name, repo_info_tuple in dict_with_tool_dependencies.items():
- <%
- description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, tool_dependencies = repo_info_tuple
- %>
- %for dependency_key, requirements_dict in tool_dependencies.items():
- <%
- name = requirements_dict[ 'name' ]
- version = requirements_dict[ 'version' ]
- type = requirements_dict[ 'type' ]
- install_dir = os.path.join( trans.app.config.tool_dependency_dir,
- name,
- version,
- repository_owner,
- repository_name,
- changeset_revision )
- readme_text = requirements_dict.get( 'readme', None )
- %>
- %if not os.path.exists( install_dir ):
- <tr>
- <td>${name}</td>
- <td>${version}</td>
- <td>${type}</td>
- <td>${install_dir}</td>
- </tr>
- %if readme_text:
- <tr><td colspan="4" bgcolor="#FFFFCC">${name} ${version} requirements and installation information</td></tr>
- <tr><td colspan="4"><pre>${readme_text}</pre></td></tr>
- %endif
- %endif
- %endfor
- %endfor
- </table>
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <input type="submit" name="confirm_tool_dependency_install_button" value="Continue"/>
- </div>
- </form>
- </div>
-</div>
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 templates/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako
--- a/templates/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako
+++ b/templates/admin/tool_shed_repository/deactivate_or_uninstall_repository.mako
@@ -10,7 +10,8 @@
<a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get updates</a>
%if repository.tool_dependencies:
- <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', id=trans.security.encode_id( repository.id ) )}">Manage tool dependencies</a>
+ <% tool_dependency_ids = [ trans.security.encode_id( td.id ) for td in repository.tool_dependencies ] %>
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', tool_dependency_ids=tool_dependency_ids )}">Manage tool dependencies</a>
%endif
</div></ul>
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 templates/admin/tool_shed_repository/initiate_repository_installation.mako
--- /dev/null
+++ b/templates/admin/tool_shed_repository/initiate_repository_installation.mako
@@ -0,0 +1,75 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/admin/tool_shed_repository/common.mako" import="*" />
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ ${repository_installation_status_updater()}
+ ${repository_installation_updater()}
+ ${self.repository_installation_javascripts()}
+</%def>
+
+<%def name="repository_installation_javascripts()">
+ <script type="text/javascript">
+ $(document).ready(function( ){
+ initiate_repository_installation( "${initiate_repository_installation_ids}", "${encoded_kwd}" );
+ });
+ var initiate_repository_installation = function ( iri_ids, encoded_kwd ) {
+ // Make ajax call
+ $.ajax( {
+ type: "POST",
+ url: "${h.url_for( controller='admin_toolshed', action='manage_repositories' )}",
+ dataType: "html",
+ data: { operation: "install", tool_shed_repository_ids: iri_ids, encoded_kwd: encoded_kwd },
+ success : function ( data ) {
+ //alert( "Initializing repository installation succeeded" );
+ },
+ error: function() {
+ alert( "Initializing repository installation failed" );
+ },
+ });
+ };
+ </script>
+</%def>
+
+%if tool_shed_repositories:
+ <div class="toolForm">
+ <div class="toolFormTitle">Monitor installing tool shed repositories</div>
+ <div class="toolFormBody">
+ <table class="grid">
+ <tr>
+ <td>Name</td>
+ <td>Description</td>
+ <td>Owner</td>
+ <td>Revision</td>
+ <td>Status</td>
+ </tr>
+ %for tool_shed_repository in tool_shed_repositories:
+ <%
+ encoded_repository_id = trans.security.encode_id( tool_shed_repository.id )
+ ids_of_tool_dependencies_missing_or_being_installed = [ trans.security.encode_id( td.id ) for td in tool_shed_repository.tool_dependencies_missing_or_being_installed ]
+ link_to_manage_tool_dependencies = tool_shed_repository.status in [ trans.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES ]
+ %>
+ <tr>
+ <td>
+ %if link_to_manage_tool_dependencies:
+ <a class="view-info" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', tool_dependency_ids=ids_of_tool_dependencies_missing_or_being_installed )}">
+ ${tool_shed_repository.name}
+ </a>
+ %else:
+ <a class="view-info" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=encoded_repository_id )}">
+ ${tool_shed_repository.name}
+ </a>
+ %endif
+ </td>
+ <td>${tool_shed_repository.description}</td>
+ <td>${tool_shed_repository.owner}</td>
+ <td>${tool_shed_repository.changeset_revision}</td>
+ <td><div id="RepositoryStatus-${encoded_repository_id}">${tool_shed_repository.status}</div></td>
+ </tr>
+ %endfor
+ </table>
+ <br clear="left"/>
+ </div>
+ </div>
+%endif
+
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 templates/admin/tool_shed_repository/repository_installation_grid.mako
--- /dev/null
+++ b/templates/admin/tool_shed_repository/repository_installation_grid.mako
@@ -0,0 +1,8 @@
+<%inherit file="/grid_base.mako"/>
+<%namespace file="/admin/tool_shed_repository/common.mako" import="*" />
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ ${repository_installation_status_updater()}
+ ${repository_installation_updater()}
+</%def>
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 templates/admin/tool_shed_repository/repository_installation_status.mako
--- /dev/null
+++ b/templates/admin/tool_shed_repository/repository_installation_status.mako
@@ -0,0 +1,29 @@
+<%def name="render_repository_status( repository )">
+ <%
+ if repository.status in [ trans.model.ToolShedRepository.installation_status.CLONING,
+ trans.model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS,
+ trans.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES,
+ trans.model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES ]:
+ bgcolor = trans.model.ToolShedRepository.states.INSTALLING
+ elif repository.status in [ trans.model.ToolShedRepository.installation_status.NEW,
+ trans.model.ToolShedRepository.installation_status.UNINSTALLED ]:
+ bgcolor = trans.model.ToolShedRepository.states.UNINSTALLED
+ elif repository.status in [ trans.model.ToolShedRepository.installation_status.ERROR ]:
+ bgcolor = trans.model.ToolShedRepository.states.ERROR
+ elif repository.status in [ trans.model.ToolShedRepository.installation_status.DEACTIVATED ]:
+ bgcolor = trans.model.ToolShedRepository.states.WARNING
+ elif repository.status in [ trans.model.ToolShedRepository.installation_status.INSTALLED ]:
+ if repository.missing_tool_dependencies:
+ bgcolor = trans.model.ToolShedRepository.states.WARNING
+ else:
+ bgcolor = trans.model.ToolShedRepository.states.OK
+ else:
+ bgcolor = trans.model.ToolShedRepository.states.ERROR
+ rval = '<div class="count-box state-color-%s" id="ToolShedRepositoryStatus-%s">' % ( bgcolor, trans.security.encode_id( repository.id ) )
+ rval += '%s</div>' % repository.status
+ return rval
+ %>
+ ${rval}
+</%def>
+
+${render_repository_status( repository )}
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 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
@@ -8,12 +8,7 @@
<div class="toolForm"><div class="toolFormTitle">Choose the tool panel section to contain the installed tools (optional)</div><div class="toolFormBody">
- %if repository.tool_dependencies:
- <% tool_dependency_ids = [ trans.security.encode_id( td.id ) for td in repository.tool_dependencies ] %>
- <form name="reselect_tool_panel_section" id="reselect_tool_panel_section" action="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', operation='install', tool_dependency_ids=tool_dependency_ids )}" method="post" >
- %else:
- <form name="reselect_tool_panel_section" id="reselect_tool_panel_section" action="${h.url_for( controller='admin_toolshed', action='reinstall_repository', id=trans.security.encode_id( repository.id ) )}" method="post" >
- %endif
+ <form name="reselect_tool_panel_section" id="reselect_tool_panel_section" action="${h.url_for( controller='admin_toolshed', action='reinstall_repository', id=trans.security.encode_id( repository.id ) )}" method="post" ><div class="form-row">
${no_changes_check_box.get_html()}
<label style="display: inline;">No changes</label>
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 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
@@ -1,6 +1,8 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
+<% import os %>
+
%if message:
${render_msg( message, status )}
%endif
@@ -20,24 +22,83 @@
</p></div><br/>
-<div class="warningmessage">
- <p>
- Installation may take a while with large repositories or if you elect to install tool dependencies. <b>Always wait until a message is
- displayed in your browser after clicking the <b>Install</b> button below.</b> If you get bored, watching your Galaxy server's paster log
- will help pass the time.
- </p>
- <p>
- If installing tool dependencies, information about installation process will be saved in various files named with a ".log"
- extension in the directory:
- ${trans.app.config.tool_dependency_dir}/<i>package name</i>/<i>package version</i>/<i>repository owner</i>/<i>repository name</i>/<i>repository changeset revision</i>
- </p>
-</div>
-<br/><div class="toolForm">
- <div class="toolFormTitle">Choose the tool panel section to contain the installed tools (optional)</div>
+ <div class="toolFormTitle">Confirm tool dependency installation</div><div class="toolFormBody">
- <form name="select_tool_panel_section" id="select_tool_panel_section" action="${h.url_for( controller='admin_toolshed', action='install_repository', tool_shed_url=tool_shed_url, repo_info_dict=repo_info_dict, includes_tools=includes_tools, install_tool_dependencies=install_tool_dependencies )}" method="post" >
+ <form name="select_tool_panel_section" id="select_tool_panel_section" action="${h.url_for( controller='admin_toolshed', action='install_repository', tool_shed_url=tool_shed_url, repo_info_dict=repo_info_dict, includes_tools=includes_tools, includes_tool_dependencies=includes_tool_dependencies )}" method="post" >
+ <div style="clear: both"></div>
+ %if includes_tool_dependencies:
+ <div class="form-row">
+ <div class="toolParamHelp" style="clear: both;">
+ <p>
+ These tool dependencies can be automatically installed with the repository. Installing them provides significant benefits and
+ Galaxy includes various features to manage them.
+ </p>
+ <p>
+ Each of these dependencies may require their own build requirements (e.g., CMake, g++, etc). Galaxy will not attempt to install
+ these build requirements, so tool dependency installation may partially fail if any are missing from your environment, but the
+ repository and all of it's contents will be installed. You can install the missing build requirements and have Galaxy attempt
+ to install the tool dependencies again if tool dependency installation fails in any way.
+ </p>
+ </div>
+ </div>
+ <div class="form-row">
+ <label>Install tool dependencies?</label>
+ ${install_tool_dependencies_check_box.get_html()}
+ <div class="toolParamHelp" style="clear: both;">
+ Un-check to skip automatic installation of these tool dependencies.
+ </div>
+ </div>
+ <div style="clear: both"></div>
+ <div class="form-row">
+ <table class="grid">
+ <tr><td colspan="4" bgcolor="#D8D8D8"><b>Tool dependencies</b></td></tr>
+ <tr>
+ <th>Name</th>
+ <th>Version</th>
+ <th>Type</th>
+ <th>Install directory</th>
+ </tr>
+ %for repository_name, repo_info_tuple in dict_with_tool_dependencies.items():
+ <% description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, tool_dependencies = repo_info_tuple %>
+ %for dependency_key, requirements_dict in tool_dependencies.items():
+ <%
+ name = requirements_dict[ 'name' ]
+ version = requirements_dict[ 'version' ]
+ type = requirements_dict[ 'type' ]
+ install_dir = os.path.join( trans.app.config.tool_dependency_dir,
+ name,
+ version,
+ repository_owner,
+ repository_name,
+ changeset_revision )
+ tool_dependency_readme_text = requirements_dict.get( 'readme', None )
+ %>
+ %if not os.path.exists( install_dir ):
+ <tr>
+ <td>${name}</td>
+ <td>${version}</td>
+ <td>${type}</td>
+ <td>${install_dir}</td>
+ </tr>
+ %if tool_dependency_readme_text:
+ <tr><td colspan="4" bgcolor="#FFFFCC">${name} ${version} requirements and installation information</td></tr>
+ <tr><td colspan="4"><pre>${tool_dependency_readme_text}</pre></td></tr>
+ %endif
+ %endif
+ %endfor
+ %endfor
+ </table>
+ <div style="clear: both"></div>
+ </div>
+ %endif
+ <div style="clear: both"></div>
+ <div class="form-row">
+ <table class="colored" width="100%">
+ <th bgcolor="#EBD9B2">Choose the tool panel section to contain the installed tools (optional)</th>
+ </table>
+ </div>
%if shed_tool_conf_select_field:
<div class="form-row"><label>Shed tool configuration file:</label>
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 templates/admin/tool_shed_repository/tool_dependency_installation_status.mako
--- a/templates/admin/tool_shed_repository/tool_dependency_installation_status.mako
+++ b/templates/admin/tool_shed_repository/tool_dependency_installation_status.mako
@@ -1,11 +1,17 @@
<%def name="render_tool_dependency_status( tool_dependency )"><%
- if tool_dependency.status == trans.model.ToolDependency.installation_status.INSTALLING:
+ if tool_dependency.status in [ trans.model.ToolDependency.installation_status.INSTALLING ]:
bgcolor = trans.model.ToolDependency.states.INSTALLING
- rval = '<div class="count-box state-color-%s" id="ToolDependencyStatus-%s">' % ( bgcolor, trans.security.encode_id( tool_dependency.id ) )
- rval += '%s</div>' % tool_dependency.status
- else:
- rval = tool_dependency.status
+ elif tool_dependency.status in [ trans.model.ToolDependency.installation_status.NEVER_INSTALLED,
+ trans.model.ToolDependency.installation_status.UNINSTALLED ]:
+ bgcolor = trans.model.ToolDependency.states.UNINSTALLED
+ elif tool_dependency.status in [ trans.model.ToolDependency.installation_status.ERROR ]:
+ bgcolor = trans.model.ToolDependency.states.ERROR
+ elif tool_dependency.status in [ trans.model.ToolDependency.installation_status.INSTALLED ]:
+ bgcolor = trans.model.ToolDependency.states.OK
+ rval = '<div class="count-box state-color-%s" id="ToolDependencyStatus-%s">' % ( bgcolor, trans.security.encode_id( tool_dependency.id ) )
+ rval += '%s</div>' % tool_dependency.status
+ return rval
%>
${rval}
</%def>
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 templates/admin/tool_shed_repository/view_tool_metadata.mako
--- a/templates/admin/tool_shed_repository/view_tool_metadata.mako
+++ b/templates/admin/tool_shed_repository/view_tool_metadata.mako
@@ -9,7 +9,8 @@
<a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( repository.id ) )}">Manage repository</a><a class="action-button" href="${h.url_for( controller='admin_toolshed', action='check_for_updates', id=trans.security.encode_id( repository.id ) )}">Get updates</a>
%if repository.tool_dependencies:
- <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', id=trans.security.encode_id( repository.id ) )}">Manage tool dependencies</a>
+ <% tool_dependency_ids = [ trans.security.encode_id( td.id ) for td in repository.tool_dependencies ] %>
+ <a class="action-button" href="${h.url_for( controller='admin_toolshed', action='manage_tool_dependencies', tool_dependency_ids=tool_dependency_ids )}">Manage tool dependencies</a>
%endif
<a class="action-button" href="${h.url_for( controller='admin_toolshed', action='deactivate_or_uninstall_repository', id=trans.security.encode_id( repository.id ) )}">Deactivate or uninstall repository</a></div>
diff -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 -r cc5fea2e382ed8edadf0d694f559b46e86a66884 templates/webapps/galaxy/admin/index.mako
--- a/templates/webapps/galaxy/admin/index.mako
+++ b/templates/webapps/galaxy/admin/index.mako
@@ -73,6 +73,7 @@
%if cloned_repositories:
<div class="toolTitle"><a href="${h.url_for( controller='admin_toolshed', action='browse_repositories' )}" target="galaxy_main">Manage installed tool shed repositories</a></div>
%endif
+ <div class="toolTitle"><a href="${h.url_for( controller='admin_toolshed', action='monitor_repository_installation' )}" target="galaxy_main">Monitor installing tool shed repositories</a></div></div></div>
%if trans.app.tool_shed_registry and trans.app.tool_shed_registry.tool_sheds:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: jgoecks: Trackster modifications to work with new tools API controller.
by Bitbucket 29 Jun '12
by Bitbucket 29 Jun '12
29 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/1a4d6f11f284/
changeset: 1a4d6f11f284
user: jgoecks
date: 2012-06-29 19:17:10
summary: Trackster modifications to work with new tools API controller.
affected #: 6 files
diff -r b2640a90e1b40a963be910329b243ae8c3fb9967 -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 lib/galaxy/web/api/tools.py
--- a/lib/galaxy/web/api/tools.py
+++ b/lib/galaxy/web/api/tools.py
@@ -135,7 +135,6 @@
run_on_regions = False
regions = payload.get( 'regions', None )
if regions:
- regions = from_json_string( regions )
if isinstance( regions, dict ):
# Regions is a single region.
regions = [ GenomeRegion.from_dict( regions ) ]
diff -r b2640a90e1b40a963be910329b243ae8c3fb9967 -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 static/scripts/mvc/data.js
--- a/static/scripts/mvc/data.js
+++ b/static/scripts/mvc/data.js
@@ -4,10 +4,10 @@
*/
var Dataset = Backbone.RelationalModel.extend({
defaults: {
- id: "",
- type: "",
- name: "",
- hda_ldda: ""
+ id: '',
+ type: '',
+ name: '',
+ hda_ldda: 'hda'
}
});
diff -r b2640a90e1b40a963be910329b243ae8c3fb9967 -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 static/scripts/mvc/tools.js
--- a/static/scripts/mvc/tools.js
+++ b/static/scripts/mvc/tools.js
@@ -112,7 +112,7 @@
return this._run({
action: 'rerun',
target_dataset_id: target_dataset.id,
- regions: JSON.stringify(regions)
+ regions: regions
});
},
diff -r b2640a90e1b40a963be910329b243ae8c3fb9967 -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 static/scripts/viz/trackster.js
--- a/static/scripts/viz/trackster.js
+++ b/static/scripts/viz/trackster.js
@@ -87,6 +87,9 @@
* Helper to determine if object is jQuery deferred.
*/
var is_deferred = function ( d ) {
+ if (d === 'pending') {
+ console.log('pending');
+ }
return ( 'isResolved' in d );
};
@@ -1770,7 +1773,7 @@
var param_dict = {};
this.parent_div.find(":input").each(function() {
var name = $(this).attr("name"), value = $(this).val();
- param_dict[name] = JSON.stringify(value);
+ param_dict[name] = value;
});
return param_dict;
},
@@ -1796,7 +1799,7 @@
tool.run(
// URL params.
{
- dataset_id: this.track.original_dataset_id,
+ target_dataset_id: this.track.original_dataset_id,
tool_id: tool.name
},
null,
@@ -1820,11 +1823,14 @@
var
url_params =
{
- dataset_id: this.track.original_dataset_id,
- chrom: this.track.view.chrom,
- low: this.track.view.low,
- high: this.track.view.high,
- tool_id: this.name
+ target_dataset_id: this.track.original_dataset_id,
+ action: 'rerun',
+ tool_id: this.name,
+ regions: [{
+ chrom: this.track.view.chrom,
+ start: this.track.view.low,
+ end: this.track.view.high
+ }]
},
current_track = this.track,
// Set name of track to include tool name, parameters, and region used.
@@ -1871,10 +1877,7 @@
this.run(url_params, new_track,
// Success callback.
function(track_data) {
- new_track.set_dataset(new Dataset({
- id: track_data.dataset_id,
- hda_ldda: track_data.hda_ldda
- }));
+ new_track.set_dataset(new Dataset(track_data));
new_track.tiles_div.text("Running job.");
new_track.init();
}
@@ -1885,9 +1888,15 @@
*/
run: function(url_params, new_track, success_callback) {
// Run tool.
+ url_params.inputs = this.get_param_values_dict();
var ss_deferred = new ServerStateDeferred({
- url: rerun_tool_url,
- url_params: $.extend(url_params, this.get_param_values_dict()),
+ ajax_settings: {
+ url: galaxy_paths.get('tool_url'),
+ data: JSON.stringify(url_params),
+ dataType: "json",
+ contentType: 'application/json',
+ type: "POST"
+ },
interval: 2000,
success_fn: function(response) {
return response !== "pending";
@@ -4636,7 +4645,7 @@
// Paint summary tree into canvas
var painter = new painters.SummaryTreePainter(result, tile_low, tile_high, this.prefs);
painter.draw(ctx, canvas.width, canvas.height, w_scale);
- return new SummaryTreeTile(track, tile_index, resolution, canvas, result.data, result.max);
+ return new SummaryTreeTile(track, region, resolution, canvas, result.data, result.max);
}
// Handle row-by-row tracks
diff -r b2640a90e1b40a963be910329b243ae8c3fb9967 -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 static/scripts/viz/visualization.js
--- a/static/scripts/viz/visualization.js
+++ b/static/scripts/viz/visualization.js
@@ -420,20 +420,19 @@
},
/**
- * as_str attribute using the format chrom:start-end can be
- * used to set object's attributes.
+ * If options is a string, parsing using the format
+ * chrom:start-end is attempted to set object attributes.
*/
initialize: function(options) {
- if (!this.get('chrom') && !this.get('start') &&
- !this.get('end') && 'as_str' in options) {
- var pieces = options.as_str.split(':'),
+ if (typeof(options) === 'string') {
+ var pieces = options.split(':'),
chrom = pieces[0],
- start_end = pieces.split('-'),
- start = start_end[0],
- end = start_end[1];
- this.set('chrom', chrom);
- this.set('start', start);
- this.set('end', end);
+ start_end = pieces[1].split('-');
+ this.set({
+ chrom: chrom,
+ start: parseInt(start_end[0]),
+ end: parseInt(start_end[1])
+ });
}
},
diff -r b2640a90e1b40a963be910329b243ae8c3fb9967 -r 1a4d6f11f28453aa98b32439a8df479a2830bc50 templates/tracks/browser.mako
--- a/templates/tracks/browser.mako
+++ b/templates/tracks/browser.mako
@@ -49,8 +49,7 @@
// Place URLs here so that url_for can be used to generate them.
//
galaxy_paths.set({
- visualization_url: "${h.url_for( action='save' )}",
- run_tool_url: "${h.url_for( controller='/api/tools' )}"
+ visualization_url: "${h.url_for( action='save' )}"
});
var
add_track_async_url = "${h.url_for( action='add_track_async' )}",
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/b2640a90e1b4/
changeset: b2640a90e1b4
user: jgoecks
date: 2012-06-29 01:11:25
summary: Code cleanup from JSHint.
affected #: 1 file
diff -r 1033af3c659443a981d7475e60171fb86a3e7e38 -r b2640a90e1b40a963be910329b243ae8c3fb9967 static/scripts/viz/trackster.js
--- a/static/scripts/viz/trackster.js
+++ b/static/scripts/viz/trackster.js
@@ -12,7 +12,7 @@
var target = arguments[0];
for ( var i = 1; i < arguments.length; i++ ) {
var other = arguments[i];
- for ( key in other ) {
+ for ( var key in other ) {
target[key] = other[key];
}
}
@@ -97,7 +97,7 @@
*/
var get_random_color = function(colors) {
// Default for colors is white.
- if (!colors) { colors = "#ffffff" };
+ if (!colors) { colors = "#ffffff"; }
// If needed, create list of colors.
if ( typeof(colors) === "string" ) {
@@ -138,7 +138,7 @@
nb = new_color & 0x0000ff;
n_brightness = brightness(nr, ng, nb);
ok = true;
- for (var i = 0; i < colors.length; i++) {
+ for (i = 0; i < colors.length; i++) {
other_color = colors[i];
or = ( other_color & 0xff0000 ) >> 16;
og = ( other_color & 0x00ff00 ) >> 8;
@@ -155,7 +155,7 @@
}
num_tries++
- } while (!ok && num_tries <= 10 );
+; } while (!ok && num_tries <= 10 );
// Add 0x1000000 to left pad number with 0s.
return '#' + ( 0x1000000 + new_color ).toString(16).substr(1,6);
@@ -211,8 +211,7 @@
// Need to provide selector for handle, not class.
element.bind( "drag", { handle: "." + handle_class, relative: true }, function ( e, d ) {
- var element = $(this);
- var
+ var element = $(this),
parent = $(this).parent(),
children = parent.children(),
this_obj = html_elt_js_obj_dict[$(this).attr("id")],
@@ -278,7 +277,6 @@
// Handle sibling movement, aka sorting.
// Determine new position
- var child;
for ( i = 0; i < children.length; i++ ) {
child = $(children.get(i));
if ( d.offsetY < child.position().top &&
@@ -343,8 +341,8 @@
DATA_ERROR = "There was an error in indexing this dataset. ",
DATA_NOCONVERTER = "A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",
DATA_NONE = "No data for this chrom/contig.",
- DATA_PENDING = "Preparing data. This can take a while for a large dataset. \
- If the visualization is saved and closed, preparation will continue in the background.",
+ DATA_PENDING = "Preparing data. This can take a while for a large dataset. " +
+ "If the visualization is saved and closed, preparation will continue in the background.",
DATA_CANNOT_RUN_TOOL = "Tool cannot be rerun: ",
DATA_LOADING = "Loading data...",
DATA_OK = "Ready for display",
@@ -512,7 +510,6 @@
* Use from_dict to recreate object.
*/
to_dict: function() {},
- update_icons: function() {},
/**
* Set drawable name.
*/
@@ -744,7 +741,7 @@
if ('filters' in obj_dict) {
// FIXME: Pass collection_dict to DrawableCollection/Drawable will make this easier.
var old_manager = this.filters_manager;
- this.filters_manager = new FiltersManager(this, obj_dict['filters']);
+ this.filters_manager = new FiltersManager(this, obj_dict.filters);
old_manager.parent_div.replaceWith(this.filters_manager.parent_div);
if (obj_dict.filters.visible) {
@@ -818,7 +815,7 @@
//
// Handle update when there are no tracks.
//
- var num_drawables = this.drawables.length
+ var num_drawables = this.drawables.length;
if (num_drawables === 0) {
this.action_icons.composite_icon.hide();
this.action_icons.filters_icon.hide();
@@ -843,7 +840,7 @@
a_type = this.drawables[0].get_type(),
num_feature_tracks = 0;
for (var i = 0; i < num_drawables; i++) {
- drawable = this.drawables[i]
+ drawable = this.drawables[i];
if (drawable.get_type() !== a_type) {
can_composite = false;
break;
@@ -1183,8 +1180,7 @@
// to zoom in
this.top_labeltrack.bind( "dragstart", function( e, d ) {
return $("<div />").css( {
- "height": view.browser_content_div.height() + view.top_labeltrack.height()
- + view.nav_labeltrack.height() + 1,
+ "height": view.browser_content_div.height() + view.top_labeltrack.height() + view.nav_labeltrack.height() + 1,
"top": "0px",
"position": "absolute",
"background-color": "#ccf",
@@ -1339,8 +1335,6 @@
return;
}
- var view = this;
-
//
// If user is navigating to previous/next set of chroms, load new chrom set and return.
//
@@ -1484,11 +1478,11 @@
*/
// FIXME: change method call so that track is first and additional parameters are optional.
// FIXME: is nodraw parameter needed?
- request_redraw: function(nodraw, force, clear_after, track) {
+ request_redraw: function(nodraw, force, clear_after, a_track) {
var
view = this,
// Either redrawing a single drawable or all view's drawables.
- track_list = (track ? [track] : view.drawables),
+ track_list = (a_track ? [a_track] : view.drawables),
track_index;
// Add/update tracks in track list to redraw list.
@@ -1519,7 +1513,7 @@
// Set up redraw if it has not been requested since last redraw.
if (!this.requested_redraw) {
- requestAnimationFrame(function() { view._redraw(nodraw) });
+ requestAnimationFrame(function() { view._redraw(nodraw); });
this.requested_redraw = true;
}
},
@@ -1726,7 +1720,7 @@
});
// Highlight value for inputs for easy replacement.
- this.parent_div.find("input").click(function() { $(this).select() });
+ this.parent_div.find("input").click(function() { $(this).select(); });
// Add buttons for running on dataset, region.
var run_tool_row = $("<div>").addClass("param-row").appendTo(this.parent_div);
@@ -1785,7 +1779,6 @@
*/
get_param_values: function() {
var param_values = [];
- var param_dict = {};
this.parent_div.find(":input").each(function() {
// Only include inputs with names; this excludes Run button.
var name = $(this).attr("name"), value = $(this).val();
@@ -1843,7 +1836,7 @@
// already in group, add track to group.
if (current_track.container === view) {
// Create new group.
- var group = new DrawableGroup(view, view, { name: this.name })
+ var group = new DrawableGroup(view, view, { name: this.name });
// Replace track with group.
var index = current_track.container.replace_drawable(current_track, group, false);
@@ -1942,7 +1935,7 @@
});
var NumberParameter = function(name, label, html, value, min, max) {
- ToolParameter.call(this, name, label, html, value)
+ ToolParameter.call(this, name, label, html, value);
this.min = min;
this.max = max;
};
@@ -1994,7 +1987,7 @@
this.high = ('high' in obj_dict ? obj_dict.high : Number.MAX_VALUE);
// Slide min/max. These values are used to set/update slider.
this.min = ('min' in obj_dict ? obj_dict.min : Number.MAX_VALUE);
- this.max = ('max' in obj_dict ? obj_dict.max : -Number.MAX_VALUE)
+ this.max = ('max' in obj_dict ? obj_dict.max : -Number.MAX_VALUE);
// UI elements associated with filter.
this.container = null;
this.slider = null;
@@ -2370,7 +2363,7 @@
}
}
else {
- console.log("ERROR: unsupported filter: ", name, type)
+ console.log("ERROR: unsupported filter: ", name, type);
}
}
@@ -2486,8 +2479,7 @@
//
var active_filters = {},
filter,
- tool_filter_conditions,
- operation;
+ tool_filter_conditions;
for (var i = 0; i < this.filters.length; i++) {
filter = this.filters[i];
if (filter.tool_id) {
@@ -2515,7 +2507,6 @@
// Invoke recursive function to run filters; this enables chaining of filters via
// iteratively application.
- var num_filters = active_filters_list.length;
(function run_filter(input_dataset_id, filters) {
var
// Set up filtering info and params.
@@ -2579,9 +2570,9 @@
var DrawableConfig = function( options ) {
this.track = options.track;
this.params = options.params;
- this.values = {}
+ this.values = {};
this.restore_values( (options.saved_values ? options.saved_values : {}) );
- this.onchange = options.onchange
+ this.onchange = options.onchange;
};
extend(DrawableConfig.prototype, {
@@ -2615,7 +2606,7 @@
row.append( $('<input type="checkbox" />').attr("id", id ).attr("name", id ).attr( 'checked', value ) );
// Draw parameter as textbox
} else if ( param.type === 'text' ) {
- row.append( $('<input type="text"/>').attr("id", id ).val(value).click( function() { $(this).select() }));
+ row.append( $('<input type="text"/>').attr("id", id ).val(value).click( function() { $(this).select(); }));
// Draw paramter as select area
} else if ( param.type === 'select' ) {
var select = $('<select />').attr("id", id);
@@ -2733,7 +2724,7 @@
this.resolution = resolution;
// Wrap element in div for background and explicitly set height. Use canvas
// height attribute because canvas may not have height if it is not in document yet.
- this.html_elt = $("<div class='track-tile'/>").append(canvas).height( $(canvas).attr("height") )
+ this.html_elt = $("<div class='track-tile'/>").append(canvas).height( $(canvas).attr("height") );
this.data = data;
this.stale = false;
};
@@ -2851,8 +2842,7 @@
var popup = popups[feature_uid];
if (!popup) {
// Create feature's popup element.
- var
- feature_uid = feature_data[0],
+ var feature_uid = feature_data[0],
feature_dict = {
name: feature_data[3],
start: feature_data[1],
@@ -2893,7 +2883,7 @@
var
popupX = offsetX + parseInt( tile.html_elt.css("left") ) - popup.width() / 2,
popupY = offsetY + parseInt( tile.html_elt.css("top") ) + 7;
- popup.css("left", popupX + "px").css("top", popupY + "px")
+ popup.css("left", popupX + "px").css("top", popupY + "px");
}
else if (!e.isPropagationStopped()) {
// Propogate event to other tiles because overlapping tiles prevent mousemove from being
@@ -2933,7 +2923,7 @@
// Attribute init.
//
this.data_url = ('data_url' in obj_dict ? obj_dict.data_url : default_data_url);
- this.data_url_extra_params = {}
+ this.data_url_extra_params = {};
this.data_query_wait = ('data_query_wait' in obj_dict ? obj_dict.data_query_wait : DEFAULT_DATA_QUERY_WAIT);
this.dataset_check_url = ('converted_datasets_state_url' in obj_dict ? obj_dict.converted_datasets_state_url : converted_datasets_state_url);
@@ -2950,7 +2940,7 @@
data_url: track.data_url,
dataset_state_url: track.dataset_check_url,
data_mode_compatible: this.data_and_mode_compatible,
- can_subset: this.can_subset,
+ can_subset: this.can_subset
}));
// Height attributes: min height, max height, and visible height.
@@ -3059,7 +3049,7 @@
var track = this;
var in_handle = false;
var in_drag = false;
- var drag_control = $( "<div class='track-resize'>" )
+ var drag_control = $( "<div class='track-resize'>" );
// Control shows on hover over track, stays while dragging
$(track.container_div).hover( function() {
if ( track.content_visible ) {
@@ -3135,12 +3125,12 @@
// Hide tiles.
this.tiles_div.hide();
// Hide any y axis labels (common to several track types)
- this.container_div.find(".yaxislabel, .track-resize").hide()
+ this.container_div.find(".yaxislabel, .track-resize").hide();
},
show_contents: function() {
// Show the contents div and labels (if present)
this.tiles_div.show();
- this.container_div.find(".yaxislabel, .track-resize").show()
+ this.container_div.find(".yaxislabel, .track-resize").show();
// Request a redraw of the content
this.request_draw();
},
@@ -3461,7 +3451,7 @@
// If any tile could not be drawn yet, this will be set to false.
all_tiles_drawn = true,
drawn_tiles = [],
- is_tile = function(o) { return (o && 'track' in o) };
+ is_tile = function(o) { return (o && 'track' in o); };
// Draw tiles.
while ( ( tile_index * TILE_SIZE * resolution ) < high ) {
var draw_result = this.draw_helper( force, width, tile_index, resolution, this.tiles_div, w_scale );
@@ -3531,7 +3521,7 @@
}
// Flag to track whether we can draw everything now
- var can_draw_now = true
+ var can_draw_now = true;
// Get the track data, maybe a deferred
var tile_data = track.data_manager.get_data( region, track.mode, resolution, track.data_url_extra_params );
@@ -3542,7 +3532,7 @@
// Get seq data if needed, maybe a deferred
var seq_data;
if ( view.reference_track && w_scale > view.canvas_manager.char_width_px ) {
- seq_data = view.reference_track.data_manager.get_data(region, track.mode, resolution, view.reference_track.data_url_extra_params)
+ seq_data = view.reference_track.data_manager.get_data(region, track.mode, resolution, view.reference_track.data_url_extra_params);
if ( is_deferred( seq_data ) ) {
can_draw_now = false;
}
@@ -3724,7 +3714,7 @@
url_params: {dataset_id : self.dataset_id, hda_ldda: self.hda_ldda},
interval: self.data_query_wait,
// Set up deferred to check dataset state until it is not pending.
- success_fn: function(result) { return result !== "pending" }
+ success_fn: function(result) { return result !== "pending"; }
});
$.when(ss_deferred.go()).then(function() {
// Dataset is indexed, so use default data URL.
@@ -3896,7 +3886,7 @@
// Get seq data if needed, maybe a deferred.
seq_data = null;
if ( view.reference_track && w_scale > view.canvas_manager.char_width_px ) {
- seq_data = view.reference_track.data_manager.get_data(tile_low, tile_high, track.mode, resolution, view.reference_track.data_url_extra_params)
+ seq_data = view.reference_track.data_manager.get_data(tile_low, tile_high, track.mode, resolution, view.reference_track.data_url_extra_params);
if ( is_deferred( seq_data ) ) {
can_draw_now = false;
}
@@ -3934,7 +3924,7 @@
mode = track.get_mode(tile_data);
track.update_auto_mode(mode);
}
- track_modes.push(mode)
+ track_modes.push(mode);
track_canvas_height = track.get_canvas_height(tile_data, mode, w_scale, width);
if (track_canvas_height > height) { height = track_canvas_height; }
@@ -3945,7 +3935,7 @@
//
canvas.width = width;
// Height is specified in kwargs or is the height found above.
- canvas.height = (kwargs['height'] ? kwargs['height'] : height);
+ canvas.height = (kwargs.height ? kwargs.height : height);
all_data_index = 0;
var ctx = canvas.getContext('2d');
ctx.translate(this.left_offset, 0);
@@ -3986,7 +3976,7 @@
}),
track;
for (var i = 0; i < this.drawables.length; i++) {
- track = this.drawables[i]
+ track = this.drawables[i];
group.add_drawable(track);
track.container = group;
group.content_div.append(track.container_div);
@@ -4013,10 +4003,10 @@
track = this.drawables[i];
if (track instanceof LineTrack) {
if (track.prefs.min_value < min) {
- min = track.prefs.min_value
+ min = track.prefs.min_value;
}
if (track.prefs.max_value > max) {
- max = track.prefs.max_value
+ max = track.prefs.max_value;
}
}
}
@@ -4175,12 +4165,12 @@
var data = result.data;
if ( isNaN(parseFloat(track.prefs.min_value)) || isNaN(parseFloat(track.prefs.max_value)) ) {
// Compute default minimum and maximum values
- var min_value = data.min
- var max_value = data.max
+ var min_value = data.min,
+ max_value = data.max;
// If mean and sd are present, use them to compute a ~95% window
// but only if it would shrink the range on one side
- min_value = Math.floor( Math.min( 0, Math.max( min_value, data.mean - 2 * data.sd ) ) )
- max_value = Math.ceil( Math.max( 0, Math.min( max_value, data.mean + 2 * data.sd ) ) )
+ min_value = Math.floor( Math.min( 0, Math.max( min_value, data.mean - 2 * data.sd ) ) );
+ max_value = Math.ceil( Math.max( 0, Math.min( max_value, data.mean + 2 * data.sd ) ) );
// Update the prefs
track.prefs.min_value = min_value;
track.prefs.max_value = max_value;
@@ -4244,7 +4234,7 @@
*/
can_subset: function(data) {
return false;
- },
+ }
});
var FeatureTrack = function(view, container, obj_dict) {
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: jgoecks: Fix bug when adding tracks due to recent refactoring.
by Bitbucket 28 Jun '12
by Bitbucket 28 Jun '12
28 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/1033af3c6594/
changeset: 1033af3c6594
user: jgoecks
date: 2012-06-29 00:34:44
summary: Fix bug when adding tracks due to recent refactoring.
affected #: 1 file
diff -r 447ed3a57217d5465758eeb720abad407cfe934c -r 1033af3c659443a981d7475e60171fb86a3e7e38 templates/tracks/browser.mako
--- a/templates/tracks/browser.mako
+++ b/templates/tracks/browser.mako
@@ -124,7 +124,7 @@
{ icon_class: 'plus-button', title: 'Add tracks', on_click: function() {
add_datasets(add_datasets_url, add_track_async_url, function(tracks) {
_.each(tracks, function(track) {
- view.add_drawable( object_from_template(track, view) );
+ view.add_drawable( object_from_template(track, view, view) );
});
});
} },
@@ -248,7 +248,7 @@
url: "${h.url_for( action='add_track_async' )}",
data: { hda_id: "${add_dataset}" },
dataType: "json",
- success: function(track_data) { view.add_drawable( object_from_template(track_data, view) ) }
+ success: function(track_data) { view.add_drawable( object_from_template(track_data, view, view) ) }
});
%endif
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: jgoecks: Paramamonster polish: (1) size panels appropriately; (2) initialize tool form from saved data; (3) use constant for tile size; (4) bug fixes.
by Bitbucket 28 Jun '12
by Bitbucket 28 Jun '12
28 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/447ed3a57217/
changeset: 447ed3a57217
user: jgoecks
date: 2012-06-29 00:00:30
summary: Paramamonster polish: (1) size panels appropriately; (2) initialize tool form from saved data; (3) use constant for tile size; (4) bug fixes.
affected #: 2 files
diff -r 603e4ed98fa7cb3b3c47f71b3b77bedd67f50fea -r 447ed3a57217d5465758eeb720abad407cfe934c static/scripts/viz/paramamonster.js
--- a/static/scripts/viz/paramamonster.js
+++ b/static/scripts/viz/paramamonster.js
@@ -112,6 +112,7 @@
this.set('tree_data', {
name: 'Root',
+ id: node_id++,
children: (params_samples.length !== 0 ? create_tree_data(params_samples, 0) : null)
});
},
@@ -149,8 +150,11 @@
// Walk subtree starting at clicked node to get full list of settings.
var get_settings = function(node, settings) {
- // Add setting for this node.
- settings[node.param.get('name')] = node.value;
+ // Add setting for this node. Root node does not have a param,
+ // however.
+ if (node.param) {
+ settings[node.param.get('name')] = node.value;
+ }
if (!node.children) {
// At leaf node: add param setting and return.
@@ -244,14 +248,16 @@
],
initialize: function(options) {
- // FIXME: find a better way to deal with needed URLs:
- var track_config = _.extend({
- data_url: galaxy_paths.get('raw_data_url'),
- converted_datasets_state_url: galaxy_paths.get('dataset_state_url')
- }, options.track);
- // HACK: remove prefs b/c they cause a redraw, which is not supported now.
- delete track_config.mode;
- this.set('track', object_from_template(track_config, {}, null));
+ if (options.track) {
+ // FIXME: find a better way to deal with needed URLs:
+ var track_config = _.extend({
+ data_url: galaxy_paths.get('raw_data_url'),
+ converted_datasets_state_url: galaxy_paths.get('dataset_state_url')
+ }, options.track);
+ // HACK: remove prefs b/c they cause a redraw, which is not supported now.
+ delete track_config.mode;
+ this.set('track', object_from_template(track_config, {}, null));
+ }
},
same_settings: function(a_track) {
@@ -358,6 +364,8 @@
var ParamaMonsterTrackView = Backbone.View.extend({
tagName: 'tr',
+ TILE_LEN: 250,
+
initialize: function(options) {
this.canvas_manager = options.canvas_manager;
this.render();
@@ -382,10 +390,19 @@
{
title: 'Settings',
icon_class: 'gear track-settings',
- on_click: function () {
+ on_click: function() {
settings_div.toggle();
},
tipsy_config: { gravity: 's' }
+ },
+ {
+ title: 'Remove',
+ icon_class: 'cross-circle',
+ on_click: function() {
+ self.$el.remove();
+ $('.tipsy').remove();
+ // TODO: remove track from viz collection.
+ }
}
]);
settings_td.prepend(icon_menu.$el);
@@ -413,12 +430,12 @@
$.when(track.data_manager.data_is_ready()).then(function(data_ok) {
// Draw tile for each region.
regions.each(function(region, index) {
- var resolution = region.length() / 300,
+ var resolution = region.length() / self.TILE_LEN,
w_scale = 1/resolution,
mode = 'Pack';
$.when(track.data_manager.get_data(region, mode, resolution, {})).then(function(tile_data) {
var canvas = self.canvas_manager.new_canvas();
- canvas.width = 300;
+ canvas.width = self.TILE_LEN;
canvas.height = track.get_canvas_height(tile_data, mode, w_scale, canvas.width);
track.draw_tile(tile_data, canvas.getContext('2d'), mode, resolution, region, w_scale);
$(tile_containers[index]).empty().append(canvas);
@@ -473,9 +490,17 @@
}));
}
+ sweep_inputs_row.insertAfter(single_input_row);
+
+ if (input.get('in_ptree')) {
+ single_input_row.hide();
+ }
+ else {
+ sweep_inputs_row.hide();
+ }
+
// Fow now, assume parameter is included in tree to start.
- sweep_inputs_row.insertAfter(single_input_row);
- single_input_row.hide();
+
// Add buttons for adding/removing parameter.
var self = this,
@@ -554,10 +579,14 @@
},
render: function() {
- var tree_params = this.model.get_tree_params();
// Start fresh.
this.$el.children().remove();
+ var tree_params = this.model.get_tree_params();
+ if (!tree_params.length) {
+ return;
+ }
+
// Set width, height based on params and samples.
this.width = 100 * (2 + tree_params.length);
this.height = 15 * this.model.get_num_leaves();
@@ -692,7 +721,8 @@
* Add track to model and view.
*/
add_track: function(pm_track) {
- var self = this;
+ var self = this,
+ param_tree = this.model.get('parameter_tree');
self.model.add_track(pm_track);
var track_view = new ParamaMonsterTrackView({
model: pm_track,
@@ -701,7 +731,7 @@
track_view.on('run_on_dataset', self.run_tool_on_dataset, self);
self.track_collection_container.append(track_view.$el);
track_view.$el.hover(function() {
- var settings_leaf = param_tree.get_leaf(settings);
+ var settings_leaf = param_tree.get_leaf(pm_track.get('settings'));
var connected_node_ids = _.pluck(param_tree.get_connected_nodes(settings_leaf), 'id');
// TODO: can do faster with enter?
@@ -736,26 +766,7 @@
settings: settings,
regions: regions
});
- self.model.add_track(pm_track);
- var track_view = new ParamaMonsterTrackView({
- model: pm_track,
- canvas_manager: self.canvas_manager
- });
- track_view.on('run_on_dataset', self.run_tool_on_dataset, self);
- self.track_collection_container.append(track_view.$el);
- track_view.$el.hover(function() {
- var settings_leaf = param_tree.get_leaf(settings);
- var connected_node_ids = _.pluck(param_tree.get_connected_nodes(settings_leaf), 'id');
-
- // TODO: can do faster with enter?
- d3.select(self.tool_param_tree_view.$el[0]).selectAll("g.node")
- .filter(function(d) {
- return _.find(connected_node_ids, function(id) { return id === d.id; }) !== undefined;
- }).style('fill', '#f00');
- },
- function() {
- d3.select(self.tool_param_tree_view.$el[0]).selectAll("g.node").style('fill', '#000');
- });
+ self.add_track(pm_track);
return pm_track;
});
@@ -763,7 +774,7 @@
_.each(tracks, function(pm_track, index) {
setTimeout(function() {
// Set inputs and run tool.
- //console.log('running with settings', pm_track.get('settings'));
+ // console.log('running with settings', pm_track.get('settings'));
tool.set_input_values(pm_track.get('settings'));
$.when(tool.rerun(dataset, regions)).then(function(output) {
// Create and add track for output dataset.
diff -r 603e4ed98fa7cb3b3c47f71b3b77bedd67f50fea -r 447ed3a57217d5465758eeb720abad407cfe934c templates/visualization/paramamonster.mako
--- a/templates/visualization/paramamonster.mako
+++ b/templates/visualization/paramamonster.mako
@@ -78,6 +78,16 @@
background-image: none;
border-radius: 12px;
}
+ #left {
+ width: 300px;
+ }
+ #center {
+ left: 300px;
+ right: 600px;
+ }
+ #right {
+ width: 600px;
+ }
</style></%def>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: jgoecks: Make it simpler to save/restore visualizations and enable saving/restoring of paramamonster visualizations.
by Bitbucket 28 Jun '12
by Bitbucket 28 Jun '12
28 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/603e4ed98fa7/
changeset: 603e4ed98fa7
user: jgoecks
date: 2012-06-28 21:48:50
summary: Make it simpler to save/restore visualizations and enable saving/restoring of paramamonster visualizations.
affected #: 9 files
diff -r 063a1d690724b3485f41c620f664f11c7390ceef -r 603e4ed98fa7cb3b3c47f71b3b77bedd67f50fea lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -353,8 +353,6 @@
viz_types = [ "trackster", "circster" ]
- len_files = None
-
def create_visualization( self, trans, title, slug, type, dbkey, annotation=None, config={} ):
""" Create visualiation and first revision. """
visualization = self._create_visualization( trans, title, type, dbkey, slug, annotation )
@@ -434,9 +432,9 @@
end = config['viewport']['end']
overview = config['viewport']['overview']
vis_rev.config[ "viewport" ] = { 'chrom': chrom, 'start': start, 'end': end, 'overview': overview }
- elif type == 'circster':
- # TODO.
- pass
+ else:
+ # Default action is to save the config as is with no validation.
+ vis_rev.config = config
vis.latest_revision = vis_rev
session.add( vis_rev )
@@ -543,6 +541,10 @@
if 'viewport' in latest_revision.config:
config['viewport'] = latest_revision.config['viewport']
+ else:
+ # Default action is to return config unaltered.
+ latest_revision = visualization.latest_revision
+ config = latest_revision.config
return config
diff -r 063a1d690724b3485f41c620f664f11c7390ceef -r 603e4ed98fa7cb3b3c47f71b3b77bedd67f50fea lib/galaxy/web/controllers/tracks.py
--- a/lib/galaxy/web/controllers/tracks.py
+++ b/lib/galaxy/web/controllers/tracks.py
@@ -16,7 +16,7 @@
from galaxy.model import NoConverterException, ConverterDependencyException
from galaxy.visualization.tracks.data_providers import *
from galaxy.visualization.genomes import decode_dbkey, Genomes
-from galaxy.visualization.tracks.visual_analytics import get_tool_def, get_dataset_job
+from galaxy.visualization.tracks.visual_analytics import get_dataset_job
class NameColumn( grids.TextColumn ):
@@ -471,12 +471,42 @@
@web.expose
@web.require_login( "use Galaxy visualizations", use_panels=True )
- def paramamonster( self, trans, hda_ldda, dataset_id ):
- # Get dataset.
- dataset = self.get_hda_or_ldda( trans, hda_ldda, dataset_id )
+ def paramamonster( self, trans, id=None, hda_ldda=None, dataset_id=None, regions=None ):
+ if id:
+ # Loading a shared visualization.
+ viz = self.get_visualization( trans, id )
+ viz_config = self.get_visualization_config( trans, viz )
+ dataset = self.get_dataset( trans, viz_config[ 'dataset_id' ] )
+ else:
+ # Loading new visualization.
+ dataset = self.get_hda_or_ldda( trans, hda_ldda, dataset_id )
+ job = get_dataset_job( dataset )
+ viz_config = {
+ 'dataset_id': dataset_id,
+ 'tool_id': job.tool_id,
+ 'regions': regions
+ }
+
+ viz_config[ 'regions' ] = [
+ {
+ 'chrom': 'chr19',
+ 'start': '10000',
+ 'end': '26000'
+ },
+ {
+ 'chrom': 'chr19',
+ 'start': '150000',
+ 'end': '175000'
+ }
+
+ ]
- return trans.fill_template_mako( "visualization/paramamonster.mako", dataset=dataset,
- tool=self.app.toolbox.tools_by_id[ 'cufflinks' ].to_dict( trans, for_display=True ) )
+ # Add tool, dataset attributes to config based on id.
+ tool = trans.app.toolbox.get_tool( viz_config[ 'tool_id' ] )
+ viz_config[ 'tool' ] = tool.to_dict( trans, for_display=True )
+ viz_config[ 'dataset' ] = dataset.get_api_value()
+
+ return trans.fill_template_mako( "visualization/paramamonster.mako", config=viz_config )
@web.expose
@web.require_login( "use Galaxy visualizations", use_panels=True )
diff -r 063a1d690724b3485f41c620f664f11c7390ceef -r 603e4ed98fa7cb3b3c47f71b3b77bedd67f50fea lib/galaxy/web/controllers/visualization.py
--- a/lib/galaxy/web/controllers/visualization.py
+++ b/lib/galaxy/web/controllers/visualization.py
@@ -5,14 +5,26 @@
from galaxy.util.sanitize_html import sanitize_html
class VisualizationListGrid( grids.Grid ):
+ def get_link( item ):
+ """
+ Returns dictionary used to create item link.
+ """
+ controller = "tracks"
+ if item.type == "trackster":
+ action = "browser"
+ elif item.type == "paramamonster":
+ action = "paramamonster"
+ elif item.type == "circster":
+ action = "circster"
+ return dict( controller=controller, action=action, id=item.id )
+
# Grid definition
title = "Saved Visualizations"
model_class = model.Visualization
default_sort_key = "-update_time"
default_filter = dict( title="All", deleted="False", tags="All", sharing="All" )
columns = [
- grids.TextColumn( "Title", key="title", attach_popup=True,
- link=( lambda item: dict( controller="tracks", action="browser", id=item.id ) ) ),
+ grids.TextColumn( "Title", key="title", attach_popup=True, link=get_link ),
grids.TextColumn( "Type", key="type" ),
grids.TextColumn( "Dbkey", key="dbkey" ),
grids.IndividualTagsColumn( "Tags", key="tags", model_tag_association_class=model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationListGrid" ),
@@ -383,12 +395,20 @@
template="visualization/create.mako" )
@web.json
- def save( self, trans, config, type, id=None, title=None, dbkey=None, annotation=None ):
+ def save( self, trans, vis_json=None, type=None, id=None, title=None, dbkey=None, annotation=None ):
"""
Save a visualization; if visualization does not have an ID, a new
visualization is created. Returns JSON of visualization.
"""
- return self.save_visualization( trans, from_json_string( config ), type, id, title, dbkey, annotation )
+
+ # Get visualization attributes from kwargs or from config.
+ vis_config = from_json_string( vis_json )
+ vis_type = type or vis_config[ 'type' ]
+ vis_id = id or vis_config.get( 'id', None )
+ vis_title = title or vis_config.get( 'title', None )
+ vis_dbkey = dbkey or vis_config.get( 'dbkey', None )
+ vis_annotation = annotation or vis_config.get( 'annotation', None )
+ return self.save_visualization( trans, vis_config, vis_type, vis_id, vis_title, vis_dbkey, vis_annotation )
@web.expose
@web.require_login( "edit visualizations" )
diff -r 063a1d690724b3485f41c620f664f11c7390ceef -r 603e4ed98fa7cb3b3c47f71b3b77bedd67f50fea static/scripts/mvc/data.js
--- a/static/scripts/mvc/data.js
+++ b/static/scripts/mvc/data.js
@@ -2,7 +2,7 @@
* A dataset. In Galaxy, datasets are associated with a history, so
* this object is also known as a HistoryDatasetAssociation.
*/
-var Dataset = Backbone.Model.extend({
+var Dataset = Backbone.RelationalModel.extend({
defaults: {
id: "",
type: "",
diff -r 063a1d690724b3485f41c620f664f11c7390ceef -r 603e4ed98fa7cb3b3c47f71b3b77bedd67f50fea static/scripts/mvc/tools.js
--- a/static/scripts/mvc/tools.js
+++ b/static/scripts/mvc/tools.js
@@ -46,7 +46,8 @@
key: 'inputs',
relatedModel: 'ToolInput',
reverseRelation: {
- key: 'tool'
+ key: 'tool',
+ includeInJSON: false
}
}
],
diff -r 063a1d690724b3485f41c620f664f11c7390ceef -r 603e4ed98fa7cb3b3c47f71b3b77bedd67f50fea static/scripts/viz/paramamonster.js
--- a/static/scripts/viz/paramamonster.js
+++ b/static/scripts/viz/paramamonster.js
@@ -6,7 +6,7 @@
/**
* Tree for a tool's parameters.
*/
-var ToolParameterTree = Backbone.Model.extend({
+var ToolParameterTree = Backbone.RelationalModel.extend({
defaults: {
tool: null,
tree_data: null
@@ -18,9 +18,6 @@
this.get('tool').get('inputs').each(function(input) {
if (!input.get_samples()) { return; }
- // All inputs are in tree to start.
- self.add_param(input);
-
// Listen for changes to input's attributes.
input.on('change:min change:max change:num_samples', function(input) {
if (input.get('in_ptree')) {
@@ -38,7 +35,16 @@
}, self);
});
- self.set_tree_data();
+ // If there is a config, use it.
+ if (options.config) {
+ _.each(options.config, function(input_config) {
+ var input = self.get('tool').get('inputs').find(function(input) {
+ return input.get('name') === input_config.name;
+ });
+ self.add_param(input);
+ input.set(input_config);
+ });
+ }
},
add_param: function(param) {
@@ -203,16 +209,51 @@
cur_node = find_child(cur_node.children);
}
return cur_node;
+ },
+
+ /**
+ * Returns a list of parameters used in tree.
+ */
+ toJSON: function() {
+ // FIXME: returning and jsonifying complete param causes trouble on the server side,
+ // so just use essential attributes for now.
+ return this.get_tree_params().map(function(param) {
+ return {
+ name: param.get('name'),
+ min: param.get('min'),
+ max: param.get('max'),
+ num_samples: param.get('num_samples')
+ };
+ });
}
});
-var ParamaMonsterTrack = Backbone.Model.extend({
+var ParamaMonsterTrack = Backbone.RelationalModel.extend({
defaults: {
track: null,
settings: null,
regions: null
},
+ relations: [
+ {
+ type: Backbone.HasMany,
+ key: 'regions',
+ relatedModel: 'GenomeRegion'
+ }
+ ],
+
+ initialize: function(options) {
+ // FIXME: find a better way to deal with needed URLs:
+ var track_config = _.extend({
+ data_url: galaxy_paths.get('raw_data_url'),
+ converted_datasets_state_url: galaxy_paths.get('dataset_state_url')
+ }, options.track);
+ // HACK: remove prefs b/c they cause a redraw, which is not supported now.
+ delete track_config.mode;
+ this.set('track', object_from_template(track_config, {}, null));
+ },
+
same_settings: function(a_track) {
var this_settings = this.get('settings'),
other_settings = a_track.get('settings');
@@ -223,6 +264,14 @@
}
}
return true;
+ },
+
+ toJSON: function() {
+ return {
+ track: this.get('track').to_dict(),
+ settings: this.get('settings'),
+ regions: this.get('regions')
+ };
}
});
@@ -235,18 +284,45 @@
*/
var ParamaMonsterVisualization = Visualization.extend({
defaults: _.extend({}, Visualization.prototype.defaults, {
+ dataset: null,
tool: null,
parameter_tree: null,
regions: null,
tracks: null
}),
+
+ relations: [
+ {
+ type: Backbone.HasOne,
+ key: 'dataset',
+ relatedModel: 'Dataset'
+ },
+ {
+ type: Backbone.HasOne,
+ key: 'tool',
+ relatedModel: 'Tool'
+ },
+ {
+ type: Backbone.HasMany,
+ key: 'regions',
+ relatedModel: 'GenomeRegion'
+ },
+ {
+ type: Backbone.HasMany,
+ key: 'tracks',
+ relatedModel: 'ParamaMonsterTrack'
+ }
+ // NOTE: cannot use relationship for parameter tree because creating tree is complex.
+ ],
initialize: function(options) {
var tool_with_samplable_inputs = this.get('tool').copy(true);
this.set('tool_with_samplable_inputs', tool_with_samplable_inputs);
- this.set('parameter_tree', new ToolParameterTree({ tool: tool_with_samplable_inputs }));
- this.set('tracks', new TrackCollection());
+ this.set('parameter_tree', new ToolParameterTree({
+ tool: tool_with_samplable_inputs,
+ config: options.tree_config
+ }));
},
add_placeholder: function(settings) {
@@ -255,6 +331,20 @@
add_track: function(track) {
this.get('tracks').add(track);
+ },
+
+ toJSON: function() {
+ // TODO: could this be easier by using relational models?
+ return {
+ id: this.get('id'),
+ title: 'Parameter exploration for dataset \'' + this.get('dataset').get('name') + '\'',
+ type: 'paramamonster',
+ dataset_id: this.get('dataset').id,
+ tool_id: this.get('tool').id,
+ regions: this.get('regions').toJSON(),
+ tree_config: this.get('parameter_tree').toJSON(),
+ tracks: this.get('tracks').toJSON()
+ };
}
});
@@ -301,7 +391,7 @@
settings_td.prepend(icon_menu.$el);
// Render tile placeholders.
- _.each(this.model.get('regions'), function() {
+ this.model.get('regions').each(function() {
self.$el.append($('<td/>').addClass('tile').html(
$('<img/>').attr('src', galaxy_paths.get('image_path') + '/loading_large_white_bg.gif')
));
@@ -322,7 +412,7 @@
// When data is ready, draw tiles.
$.when(track.data_manager.data_is_ready()).then(function(data_ok) {
// Draw tile for each region.
- _.each(regions, function(region, index) {
+ regions.each(function(region, index) {
var resolution = region.length() / 300,
w_scale = 1/resolution,
mode = 'Pack';
@@ -550,6 +640,12 @@
// Handle node clicks for tree data.
this.model.get('parameter_tree').on('change:tree_data', this.handle_node_clicks, this);
+
+ // Each track must have a view so it has a canvas manager.
+ var self = this;
+ this.model.get('tracks').each(function(track) {
+ track.get('track').view = self;
+ });
},
render: function() {
@@ -565,13 +661,17 @@
regions = self.model.get('regions'),
tr = $('<tr/>').appendTo(this.track_collection_container);
- _.each(regions, function(region) {
+ regions.each(function(region) {
tr.append( $('<th>').text(region.toString()) );
});
tr.children().first().attr('colspan', 2);
$('#right').append(this.track_collection_container);
+ self.model.get('tracks').each(function(track) {
+ self.add_track(track);
+ });
+
// Render tool parameter tree in center panel.
this.tool_param_tree_view.render();
$('#center').append(this.tool_param_tree_view.$el);
@@ -588,6 +688,34 @@
});
},
+ /**
+ * Add track to model and view.
+ */
+ add_track: function(pm_track) {
+ var self = this;
+ self.model.add_track(pm_track);
+ var track_view = new ParamaMonsterTrackView({
+ model: pm_track,
+ canvas_manager: self.canvas_manager
+ });
+ track_view.on('run_on_dataset', self.run_tool_on_dataset, self);
+ self.track_collection_container.append(track_view.$el);
+ track_view.$el.hover(function() {
+ var settings_leaf = param_tree.get_leaf(settings);
+ var connected_node_ids = _.pluck(param_tree.get_connected_nodes(settings_leaf), 'id');
+
+ // TODO: can do faster with enter?
+ d3.select(self.tool_param_tree_view.$el[0]).selectAll("g.node")
+ .filter(function(d) {
+ return _.find(connected_node_ids, function(id) { return id === d.id; }) !== undefined;
+ }).style('fill', '#f00');
+ },
+ function() {
+ d3.select(self.tool_param_tree_view.$el[0]).selectAll("g.node").style('fill', '#000');
+ });
+ return pm_track;
+ },
+
handle_node_clicks: function() {
// When node clicked in tree, run tool and add tracks to model.
var self = this,
diff -r 063a1d690724b3485f41c620f664f11c7390ceef -r 603e4ed98fa7cb3b3c47f71b3b77bedd67f50fea static/scripts/viz/visualization.js
--- a/static/scripts/viz/visualization.js
+++ b/static/scripts/viz/visualization.js
@@ -69,7 +69,7 @@
this.load_pattern( 'left_strand', "/visualization/strand_left.png" );
this.load_pattern( 'right_strand_inv', "/visualization/strand_right_inv.png" );
this.load_pattern( 'left_strand_inv', "/visualization/strand_left_inv.png" );
-}
+};
_.extend( CanvasManager.prototype, {
load_pattern: function( key, path ) {
@@ -79,7 +79,7 @@
image.src = galaxy_paths.attributes.image_path + path;
image.onload = function() {
patterns[key] = dummy_context.createPattern( image, "repeat" );
- }
+ };
},
get_pattern: function( key ) {
return this.patterns[key];
@@ -215,8 +215,8 @@
// ReferenceDataManager does not have dataset.
if (dataset) {
- params['dataset_id'] = dataset.id;
- params['hda_ldda'] = dataset.get('hda_ldda');
+ params.dataset_id = dataset.id;
+ params.hda_ldda = dataset.get('hda_ldda');
}
$.extend(params, extra_params);
@@ -265,17 +265,16 @@
// TODO: this logic could be improved if the visualization knew whether
// the data was "index" or "data."
//
- var
- key_ary = this.get('key_ary'),
+ var key_ary = this.get('key_ary'),
obj_cache = this.get('obj_cache'),
- key, region, entry_region, mode, entry;
+ key, entry_region;
for (var i = 0; i < key_ary.length; i++) {
entry_region = new GenomeRegion(key_ary[i]);
if (entry_region.contains(region)) {
// This entry has data in the requested range. Return if data
// is compatible and can be subsetted.
- var entry = obj_cache[key];
+ entry = obj_cache[key];
if ( is_deferred(entry) ||
( this.get('data_mode_compatible')(entry, mode) && this.get('can_subset')(entry) ) ) {
this.move_key_to_end(key, i);
@@ -298,8 +297,6 @@
this.set_elt(region, entry);
},
- /**
-
/** "Deep" data request; used as a parameter for DataManager.get_more_data() */
DEEP_DATA_REQ: "deep",
@@ -341,7 +338,7 @@
//
var
data_manager = this,
- new_data_request = this.load_data(query_region, mode, resolution, extra_params)
+ new_data_request = this.load_data(query_region, mode, resolution, extra_params),
new_data_available = $.Deferred();
// load_data sets cache to new_data_request, but use custom deferred object so that signal and data
// is all data, not just new data.
@@ -408,7 +405,7 @@
/**
* A genomic region.
*/
-var GenomeRegion = Backbone.Model.extend({
+var GenomeRegion = Backbone.RelationalModel.extend({
defaults: {
chrom: null,
start: 0,
@@ -431,9 +428,9 @@
!this.get('end') && 'as_str' in options) {
var pieces = options.as_str.split(':'),
chrom = pieces[0],
- pieces = pieces.split('-'),
- start = pieces[0],
- end = pieces[1];
+ start_end = pieces.split('-'),
+ start = start_end[0],
+ end = start_end[1];
this.set('chrom', chrom);
this.set('start', start);
this.set('end', end);
@@ -462,7 +459,7 @@
chrom: this.get('chrom'),
start: this.get('start'),
end: this.get('end')
- }
+ };
},
/**
@@ -556,7 +553,7 @@
datasets: []
},
- url: function() { return galaxy_paths.get("visualization_url"); },
+ url: galaxy_paths.get("visualization_url"),
/**
* POSTs visualization's JSON to its URL using the parameter 'vis_json'
@@ -565,7 +562,7 @@
*/
save: function() {
return $.ajax({
- url: this.url(),
+ url: this.url,
type: "POST",
dataType: "json",
data: {
@@ -818,7 +815,7 @@
requests[requests.length] = $.ajax({
url: add_track_async_url,
data: data,
- dataType: "json",
+ dataType: "json"
});
});
// To preserve order, wait until there are definitions for all tracks and then add
diff -r 063a1d690724b3485f41c620f664f11c7390ceef -r 603e4ed98fa7cb3b3c47f71b3b77bedd67f50fea templates/base_panels.mako
--- a/templates/base_panels.mako
+++ b/templates/base_panels.mako
@@ -57,7 +57,8 @@
data_url: '${h.url_for( controller="tracks", action="data" )}',
raw_data_url: '${h.url_for( controller="tracks", action="raw_data" )}',
converted_datasets_state_url: '${h.url_for( controller="tracks", action="converted_datasets_state" )}',
- dataset_state_url: '${h.url_for( controller="tracks", action="dataset_state" )}'
+ dataset_state_url: '${h.url_for( controller="tracks", action="dataset_state" )}',
+ visualization_url: '${h.url_for( controller="visualization", action="save" )}'
});
</script></%def>
diff -r 063a1d690724b3485f41c620f664f11c7390ceef -r 603e4ed98fa7cb3b3c47f71b3b77bedd67f50fea templates/visualization/paramamonster.mako
--- a/templates/visualization/paramamonster.mako
+++ b/templates/visualization/paramamonster.mako
@@ -90,34 +90,43 @@
<script type="text/javascript">
var viz;
$(function() {
- // -- Viz set up. --
-
- var tool = new Tool(JSON.parse('${ h.to_json_string( tool ) }')),
- regions = [
- new GenomeRegion({
- chrom: 'chr19',
- start: '10000',
- end: '26000'
- }),
- new GenomeRegion({
- chrom: 'chr19',
- start: '150000',
- end: '175000'
- })
- ],
- // HACK: need to replace \ with \\ due to simplejson bug.
- dataset = new Dataset(JSON.parse('${ h.to_json_string( dataset.get_api_value() ).replace('\\', '\\\\' ) }'));
-
-
- viz = new ParamaMonsterVisualization({
- tool: tool,
- dataset: dataset,
- regions: regions
- });
+ // -- Viz set up. --
+ var viz = new ParamaMonsterVisualization(
+ ${ h.to_json_string( config ).replace('\\', '\\\\' )}
+ );
var viz_view = new ParamaMonsterVisualizationView({ model: viz });
viz_view.render();
$('.unified-panel-body').append(viz_view.$el);
+
+ // -- Menu set up. --
+ var menu = create_icon_buttons_menu([
+ { icon_class: 'disk--arrow', title: 'Save', on_click: function() {
+ // Show saving dialog box
+ show_modal("Saving...", "progress");
+
+ viz.save().success(function(vis_info) {
+ hide_modal();
+ viz.set({
+ 'id': vis_info.vis_id,
+ 'has_changes': false
+ });
+ })
+ .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 = "${h.url_for( controller='visualization', action='list' )}";
+ } }
+ ],
+ {
+ tipsy_config: {gravity: 'n'}
+ });
+
+ menu.$el.attr("style", "float: right");
+ $("#right .unified-panel-header-inner").append(menu.$el);
});
</script></%def>
@@ -129,4 +138,8 @@
</%def><%def name="right_panel()">
+ <div class="unified-panel-header" unselectable="on">
+ <div class="unified-panel-header-inner">
+ </div>
+ </div></%def>
\ 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
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/063a1d690724/
changeset: 063a1d690724
user: jgoecks
date: 2012-06-28 19:31:20
summary: Update backbone-relational lib.
affected #: 1 file
diff -r adc8114131fa700da3b5800d7ba4568bd665c9b5 -r 063a1d690724b3485f41c620f664f11c7390ceef static/scripts/libs/backbone-relational.js
--- a/static/scripts/libs/backbone-relational.js
+++ b/static/scripts/libs/backbone-relational.js
@@ -1,4 +1,4 @@
-/**
+/**
* Backbone-relational.js 0.5.0
* (c) 2011 Paul Uithol
*
@@ -19,15 +19,15 @@
exports = module.exports = Backbone;
}
else {
- var _ = window._;
+ _ = window._;
Backbone = window.Backbone;
exports = window;
}
-
+
Backbone.Relational = {
showWarnings: true
};
-
+
/**
* Semaphore mixin; can be used as both binary and counting.
**/
@@ -116,37 +116,87 @@
* Backbone.Store keeps track of all created (and destruction of) Backbone.RelationalModel.
* Handles lookup for relations.
*/
- Backbone.Store = function() {
+ Backbone.Store = function() {
this._collections = [];
this._reverseRelations = [];
+ this._subModels = [];
+ this._modelScopes = [ exports ];
};
_.extend( Backbone.Store.prototype, Backbone.Events, {
- _collections: null,
- _reverseRelations: null,
+ addModelScope: function( scope ) {
+ this._modelScopes.push( scope );
+ },
+
+ /**
+ * Add a set of subModelTypes to the store, that can be used to resolve the '_superModel'
+ * for a model later in 'setupSuperModel'.
+ *
+ * @param {Backbone.RelationalModel} subModelTypes
+ * @param {Backbone.RelationalModel} superModelType
+ */
+ addSubModels: function( subModelTypes, superModelType ) {
+ this._subModels.push({
+ 'superModelType': superModelType,
+ 'subModels': subModelTypes
+ });
+ },
+
+ /**
+ * Check if the given modelType is registered as another model's subModel. If so, add it to the super model's
+ * '_subModels', and set the modelType's '_superModel', '_subModelTypeName', and '_subModelTypeAttribute'.
+ *
+ * @param {Backbone.RelationalModel} modelType
+ */
+ setupSuperModel: function( modelType ) {
+ _.find( this._subModels, function( subModelDef ) {
+ return _.find( subModelDef.subModels, function( subModelTypeName, typeValue ) {
+ var subModelType = this.getObjectByName( subModelTypeName );
+
+ if ( modelType === subModelType ) {
+ // Set 'modelType' as a child of the found superModel
+ subModelDef.superModelType._subModels[ typeValue ] = modelType;
+
+ // Set '_superModel', '_subModelTypeValue', and '_subModelTypeAttribute' on 'modelType'.
+ modelType._superModel = subModelDef.superModelType;
+ modelType._subModelTypeValue = typeValue;
+ modelType._subModelTypeAttribute = subModelDef.superModelType.prototype.subModelTypeAttribute;
+ return true;
+ }
+ }, this );
+ }, this );
+ },
/**
* Add a reverse relation. Is added to the 'relations' property on model's prototype, and to
* existing instances of 'model' in the store as well.
- * @param {object} relation
+ * @param {Object} relation
* @param {Backbone.RelationalModel} relation.model
* @param {String} relation.type
* @param {String} relation.key
- * @param {String|object} relation.relatedModel
+ * @param {String|Object} relation.relatedModel
*/
addReverseRelation: function( relation ) {
var exists = _.any( this._reverseRelations, function( rel ) {
- return _.all( relation, function( val, key ) {
- return val === rel[ key ];
+ return _.all( relation, function( val, key ) {
+ return val === rel[ key ];
+ });
});
- });
if ( !exists && relation.model && relation.type ) {
this._reverseRelations.push( relation );
- if ( !relation.model.prototype.relations ) {
- relation.model.prototype.relations = [];
- }
- relation.model.prototype.relations.push( relation );
+ var addRelation = function( model, relation ) {
+ if ( !model.prototype.relations ) {
+ model.prototype.relations = [];
+ }
+ model.prototype.relations.push( relation );
+
+ _.each( model._subModels, function( subModel ) {
+ addRelation( subModel, relation );
+ }, this );
+ };
+
+ addRelation( relation.model, relation );
this.retroFitRelation( relation );
}
@@ -154,11 +204,15 @@
/**
* Add a 'relation' to all existing instances of 'relation.model' in the store
- * @param {object} relation
+ * @param {Object} relation
*/
retroFitRelation: function( relation ) {
var coll = this.getCollection( relation.model );
coll.each( function( model ) {
+ if ( !( model instanceof relation.model ) ) {
+ return;
+ }
+
new relation.type( model, relation );
}, this);
},
@@ -169,9 +223,17 @@
* @return {Backbone.Collection} A collection if found (or applicable for 'model'), or null
*/
getCollection: function( model ) {
- var coll = _.detect( this._collections, function( c ) {
- // Check if model is the type itself (a ref to the constructor), or is of type c.model
- return model === c.model || model.constructor === c.model;
+ if ( model instanceof Backbone.RelationalModel ) {
+ model = model.constructor;
+ }
+
+ var rootModel = model;
+ while ( rootModel._superModel ) {
+ rootModel = rootModel._superModel;
+ }
+
+ var coll = _.detect( this._collections, function( c ) {
+ return c.model === rootModel;
});
if ( !coll ) {
@@ -187,22 +249,32 @@
* @return {Object}
*/
getObjectByName: function( name ) {
- var type = _.reduce( name.split( '.' ), function( memo, val ) {
- return memo[ val ];
- }, exports);
- return type !== exports ? type: null;
+ var parts = name.split( '.' ),
+ type = null;
+
+ _.find( this._modelScopes, function( scope ) {
+ type = _.reduce( parts, function( memo, val ) {
+ return memo[ val ];
+ }, scope );
+
+ if ( type && type !== scope ) {
+ return true;
+ }
+ }, this );
+
+ return type;
},
_createCollection: function( type ) {
var coll;
- // If 'type' is an instance, take it's constructor
+ // If 'type' is an instance, take its constructor
if ( type instanceof Backbone.RelationalModel ) {
type = type.constructor;
}
// Type should inherit from Backbone.RelationalModel.
- if ( type.prototype instanceof Backbone.RelationalModel.prototype.constructor ) {
+ if ( type.prototype instanceof Backbone.RelationalModel ) {
coll = new Backbone.Collection();
coll.model = type;
@@ -213,7 +285,7 @@
},
/**
- * Find an id
+ * Find the attribute that is to be used as the `id` on a given object
* @param type
* @param {String|Number|Object|Backbone.RelationalModel} item
*/
@@ -240,7 +312,18 @@
find: function( type, item ) {
var id = this.resolveIdForItem( type, item );
var coll = this.getCollection( type );
- return coll && coll.get( id );
+
+ // Because the found object could be of any of the type's superModel
+ // types, only return it if it's actually of the type asked for.
+ if ( coll ) {
+ var obj = coll.get( id );
+
+ if ( obj instanceof type ) {
+ return obj;
+ }
+ }
+
+ return null;
},
/**
@@ -281,19 +364,19 @@
* are used to regulate addition and removal of models from relations.
*
* @param {Backbone.RelationalModel} instance
- * @param {object} options
+ * @param {Object} options
* @param {string} options.key
* @param {Backbone.RelationalModel.constructor} options.relatedModel
- * @param {Boolean|String} [options.includeInJSON=true] Serialize the given attribute for related model(s)' in toJSON, or just their ids.
+ * @param {Boolean|String} [options.includeInJSON=true] Serialize the given attribute for related model(s)' in toJSON, or just their ids.
* @param {Boolean} [options.createModels=true] Create objects from the contents of keys if the object is not found in Backbone.store.
- * @param {object} [options.reverseRelation] Specify a bi-directional relation. If provided, Relation will reciprocate
+ * @param {Object} [options.reverseRelation] Specify a bi-directional relation. If provided, Relation will reciprocate
* the relation to the 'relatedModel'. Required and optional properties match 'options', except that it also needs
* {Backbone.Relation|String} type ('HasOne' or 'HasMany').
*/
Backbone.Relation = function( instance, options ) {
this.instance = instance;
// Make sure 'options' is sane, and fill with defaults from subclasses and this object's prototype
- options = ( typeof options === 'object' && options ) || {};
+ options = _.isObject( options ) ? options : {};
this.reverseRelation = _.defaults( options.reverseRelation || {}, this.options.reverseRelation );
this.reverseRelation.type = !_.isString( this.reverseRelation.type ) ? this.reverseRelation.type :
Backbone[ this.reverseRelation.type ] || Backbone.Relational.store.getObjectByName( this.reverseRelation.type );
@@ -302,7 +385,7 @@
this.key = this.options.key;
this.keySource = this.options.keySource || this.key;
- this.keyDestination = this.options.keyDestination || this.options.keySource || this.key;
+ this.keyDestination = this.options.keyDestination || this.keySource || this.key;
// 'exports' should be the global object where 'relatedModel' can be found on if given as a string.
this.relatedModel = this.options.relatedModel;
@@ -340,7 +423,7 @@
_.bindAll( this, '_modelRemovedFromCollection', '_relatedModelAdded', '_relatedModelRemoved' );
- if( instance ) {
+ if ( instance ) {
this.initialize();
// When a model in the store is destroyed, check if it is 'this.instance'.
@@ -405,28 +488,28 @@
return false;
}
// Check if the type in 'relatedModel' inherits from Backbone.RelationalModel
- if ( !( m.prototype instanceof Backbone.RelationalModel.prototype.constructor ) ) {
+ if ( !( m.prototype instanceof Backbone.RelationalModel ) ) {
warn && console.warn( 'Relation=%o; model does not inherit from Backbone.RelationalModel (%o)', this, i );
return false;
}
// Check if the type in 'relatedModel' inherits from Backbone.RelationalModel
- if ( !( rm.prototype instanceof Backbone.RelationalModel.prototype.constructor ) ) {
+ if ( !( rm.prototype instanceof Backbone.RelationalModel ) ) {
warn && console.warn( 'Relation=%o; relatedModel does not inherit from Backbone.RelationalModel (%o)', this, rm );
return false;
}
// Check if this is not a HasMany, and the reverse relation is HasMany as well
- if ( this instanceof Backbone.HasMany && this.reverseRelation.type === Backbone.HasMany.prototype.constructor ) {
+ if ( this instanceof Backbone.HasMany && this.reverseRelation.type === Backbone.HasMany ) {
warn && console.warn( 'Relation=%o; relation is a HasMany, and the reverseRelation is HasMany as well.', this );
return false;
}
// Check if we're not attempting to create a duplicate relationship
- if( i && i._relations.length ) {
+ if ( i && i._relations.length ) {
var exists = _.any( i._relations, function( rel ) {
- var hasReverseRelation = this.reverseRelation.key && rel.reverseRelation.key;
- return rel.relatedModel === rm && rel.key === k &&
- ( !hasReverseRelation || this.reverseRelation.key === rel.reverseRelation.key );
- }, this );
+ var hasReverseRelation = this.reverseRelation.key && rel.reverseRelation.key;
+ return rel.relatedModel === rm && rel.key === k &&
+ ( !hasReverseRelation || this.reverseRelation.key === rel.reverseRelation.key );
+ }, this );
if ( exists ) {
warn && console.warn( 'Relation=%o between instance=%o.%s and relatedModel=%o.%s already exists',
@@ -451,12 +534,6 @@
this.instance.release();
},
- createModel: function( item ) {
- if ( this.options.createModels && typeof( item ) === 'object' ) {
- return new this.relatedModel( item );
- }
- },
-
/**
* Determine if a relation (on a different RelationalModel) is the reverse
* relation of the current one.
@@ -482,12 +559,12 @@
// Iterate over 'model', 'this.related.models' (if this.related is a Backbone.Collection), or wrap 'this.related' in an array.
var models = !_.isUndefined( model ) ? [ model ] : this.related && ( this.related.models || [ this.related ] );
_.each( models , function( related ) {
- _.each( related.getRelations(), function( relation ) {
- if ( this._isReverseRelation( relation ) ) {
- reverseRelations.push( relation );
- }
+ _.each( related.getRelations(), function( relation ) {
+ if ( this._isReverseRelation( relation ) ) {
+ reverseRelations.push( relation );
+ }
+ }, this );
}, this );
- }, this );
return reverseRelations;
},
@@ -501,7 +578,7 @@
sanitizeOptions: function( options ) {
options = options ? _.clone( options ) : {};
if ( options.silent ) {
- options = _.extend( {}, options, { silentChange: true } );
+ options.silentChange = true;
delete options.silent;
}
return options;
@@ -516,7 +593,7 @@
unsanitizeOptions: function( options ) {
options = options ? _.clone( options ) : {};
if ( options.silentChange ) {
- options = _.extend( {}, options, { silent: true } );
+ options.silent = true;
delete options.silentChange;
}
return options;
@@ -551,10 +628,9 @@
this.setRelated( model );
// Notify new 'related' object of the new relation.
- var dit = this;
- _.each( dit.getReverseRelations(), function( relation ) {
- relation.addRelated( dit.instance );
- } );
+ _.each( this.getReverseRelations(), function( relation ) {
+ relation.addRelated( this.instance );
+ }, this );
},
findRelated: function( options ) {
@@ -565,15 +641,7 @@
model = item;
}
else if ( item ) {
- // Try to find an instance of the appropriate 'relatedModel' in the store, or create it
- model = Backbone.Relational.store.find( this.relatedModel, item );
-
- if ( model && _.isObject( item ) ) {
- model.set( item, options );
- }
- else if ( !model ) {
- model = this.createModel( item );
- }
+ model = this.relatedModel.findOrCreate( item, { create: this.options.createModels } );
}
return model;
@@ -583,7 +651,7 @@
* If the key is changed, notify old & new reverse relations and initialize the new relation
*/
onChange: function( model, attr, options ) {
- // Don't accept recursive calls to onChange (like onChange->findRelated->createModel->initializeRelations->addRelated->onChange)
+ // Don't accept recursive calls to onChange (like onChange->findRelated->findOrCreate->initializeRelations->addRelated->onChange)
if ( this.isLocked() ) {
return;
}
@@ -691,10 +759,10 @@
// Handle a custom 'collectionType'
this.collectionType = this.options.collectionType;
- if ( _( this.collectionType ).isString() ) {
+ if ( _.isString( this.collectionType ) ) {
this.collectionType = Backbone.Relational.store.getObjectByName( this.collectionType );
}
- if ( !this.collectionType.prototype instanceof Backbone.Collection.prototype.constructor ){
+ if ( !this.collectionType.prototype instanceof Backbone.Collection ){
throw new Error( 'collectionType must inherit from Backbone.Collection' );
}
@@ -710,7 +778,7 @@
},
_getCollectionOptions: function() {
- return _.isFunction( this.options.collectionOptions ) ?
+ return _.isFunction( this.options.collectionOptions ) ?
this.options.collectionOptions( this.instance ) :
this.options.collectionOptions;
},
@@ -737,12 +805,12 @@
if ( this.options.collectionKey ) {
var key = this.options.collectionKey === true ? this.options.reverseRelation.key : this.options.collectionKey;
- if (collection[ key ] && collection[ key ] !== this.instance ) {
+ if ( collection[ key ] && collection[ key ] !== this.instance ) {
if ( Backbone.Relational.showWarnings && typeof console !== 'undefined' ) {
console.warn( 'Relation=%o; collectionKey=%s already exists on collection=%o', this, key, this.options.collectionKey );
}
}
- else if (key) {
+ else if ( key ) {
collection[ key ] = this.instance;
}
}
@@ -768,19 +836,18 @@
// Try to find instances of the appropriate 'relatedModel' in the store
_.each( this.keyContents, function( item ) {
- var model = Backbone.Relational.store.find( this.relatedModel, item );
+ var model = null;
+ if ( item instanceof this.relatedModel ) {
+ model = item;
+ }
+ else {
+ model = this.relatedModel.findOrCreate( item, { create: this.options.createModels } );
+ }
- if ( model && _.isObject( item ) ) {
- model.set( item, options );
- }
- else if ( !model ) {
- model = this.createModel( item );
- }
-
- if ( model && !this.related.getByCid( model ) && !this.related.get( model ) ) {
- models.push( model );
- }
- }, this );
+ if ( model && !this.related.getByCid( model ) && !this.related.get( model ) ) {
+ models.push( model );
+ }
+ }, this );
}
// Add all found 'models' in on go, so 'add' will only be called once (and thus 'sort', etc.)
@@ -816,7 +883,7 @@
if ( this.related instanceof Backbone.Collection ) {
coll = this.related;
- coll.reset( [], { silent: true } );
+ coll.remove( coll.models );
}
else {
coll = this._prepareCollection();
@@ -842,9 +909,9 @@
if ( !this.related.getByCid( model ) && !this.related.get( model ) ) {
// Check if this new model was specified in 'this.keyContents'
var item = _.any( this.keyContents, function( item ) {
- var id = Backbone.Relational.store.resolveIdForItem( this.relatedModel, item );
- return id && id === model.id;
- }, this );
+ var id = Backbone.Relational.store.resolveIdForItem( this.relatedModel, item );
+ return id && id === model.id;
+ }, this );
if ( item ) {
this.related.add( model, options );
@@ -860,7 +927,7 @@
//console.debug('handleAddition called; args=%o', arguments);
// Make sure the model is in fact a valid model before continuing.
// (it can be invalid as a result of failing validation in Backbone.Collection._prepareModel)
- if( !( model instanceof Backbone.Model ) ) {
+ if ( !( model instanceof Backbone.Model ) ) {
return;
}
@@ -883,7 +950,7 @@
*/
handleRemoval: function( model, coll, options ) {
//console.debug('handleRemoval called; args=%o', arguments);
- if( !( model instanceof Backbone.Model ) ) {
+ if ( !( model instanceof Backbone.Model ) ) {
return;
}
@@ -940,6 +1007,9 @@
_deferProcessing: false,
_queue: null,
+ subModelTypeAttribute: 'type',
+ subModelTypes: null,
+
constructor: function( attributes, options ) {
// Nasty hack, for cases like 'model.get( <HasMany key> ).add( item )'.
// Defer 'processQueue', so that when 'Relation.createModels' is used we:
@@ -971,7 +1041,7 @@
this._queue.block();
Backbone.Relational.eventQueue.block();
- Backbone.Model.prototype.constructor.apply( this, arguments );
+ Backbone.Model.apply( this, arguments );
// Try to run the global queue holding external events
Backbone.Relational.eventQueue.unblock();
@@ -1004,7 +1074,7 @@
_.each( this.relations, function( rel ) {
var type = !_.isString( rel.type ) ? rel.type : Backbone[ rel.type ] || Backbone.Relational.store.getObjectByName( rel.type );
- if ( type && type.prototype instanceof Backbone.Relation.prototype.constructor ) {
+ if ( type && type.prototype instanceof Backbone.Relation ) {
new type( this, rel ); // Also pushes the new Relation into _relations
}
else {
@@ -1016,17 +1086,18 @@
this.release();
this.processQueue();
},
-
+
/**
* When new values are set, notify this model's relations (also if options.silent is set).
* (Relation.setRelated locks this model before calling 'set' on it to prevent loops)
*/
updateRelations: function( options ) {
- if( this._isInitialized && !this.isLocked() ) {
+ if ( this._isInitialized && !this.isLocked() ) {
_.each( this._relations, function( rel ) {
- var val = this.attributes[ rel.key ];
+ // Update from data in `rel.keySource` if set, or `rel.key` otherwise
+ var val = this.attributes[ rel.keySource ] || this.attributes[ rel.key ];
if ( rel.related !== val ) {
- this.trigger('relational:change:' + rel.key, this, val, options || {} );
+ this.trigger( 'relational:change:' + rel.key, this, val, options || {} );
}
}, this );
}
@@ -1072,10 +1143,11 @@
/**
* Retrieve related objects.
* @param key {string} The relation key to fetch models for.
- * @param options {object} Options for 'Backbone.Model.fetch' and 'Backbone.sync'.
+ * @param options {Object} Options for 'Backbone.Model.fetch' and 'Backbone.sync'.
+ * @param update {boolean} Whether to force a fetch from the server (updating existing models).
* @return {jQuery.when[]} An array of request objects
*/
- fetchRelated: function( key, options ) {
+ fetchRelated: function( key, options, update ) {
options || ( options = {} );
var setUrl,
requests = [],
@@ -1083,7 +1155,7 @@
keyContents = rel && rel.keyContents,
toFetch = keyContents && _.select( _.isArray( keyContents ) ? keyContents : [ keyContents ], function( item ) {
var id = Backbone.Relational.store.resolveIdForItem( rel.relatedModel, item );
- return id && !Backbone.Relational.store.find( rel.relatedModel, id );
+ return id && ( update || !Backbone.Relational.store.find( rel.relatedModel, id ) );
}, this );
if ( toFetch && toFetch.length ) {
@@ -1091,13 +1163,13 @@
var models = _.map( toFetch, function( item ) {
var model;
- if ( typeof( item ) === 'object' ) {
- model = new rel.relatedModel( item );
+ if ( _.isObject( item ) ) {
+ model = rel.relatedModel.build( item );
}
else {
var attrs = {};
attrs[ rel.relatedModel.prototype.idAttribute ] = item;
- model = new rel.relatedModel( attrs );
+ model = rel.relatedModel.build( attrs );
}
return model;
@@ -1117,9 +1189,9 @@
error: function() {
var args = arguments;
_.each( models, function( model ) {
- model.trigger( 'destroy', model, model.collection, options );
- options.error && options.error.apply( model, args );
- });
+ model.trigger( 'destroy', model, model.collection, options );
+ options.error && options.error.apply( model, args );
+ });
},
url: setUrl
},
@@ -1153,7 +1225,7 @@
// Duplicate backbone's behavior to allow separate key/value parameters, instead of a single 'attributes' object
var attributes;
- if (_.isObject( key ) || key == null) {
+ if ( _.isObject( key ) || key == null ) {
attributes = key;
options = value;
}
@@ -1164,10 +1236,12 @@
var result = Backbone.Model.prototype.set.apply( this, arguments );
- // 'set' is called quite late in 'Backbone.Model.prototype.constructor', but before 'initialize'.
// Ideal place to set up relations :)
if ( !this._isInitialized && !this.isLocked() ) {
+ this.constructor.initializeModelHierarchy();
+
Backbone.Relational.store.register( this );
+
this.initializeRelations();
}
// Update the 'idAttribute' in Backbone.store if; we don't want it to miss an 'id' update due to {silent:true}
@@ -1227,8 +1301,8 @@
}
_.each( this.getRelations(), function( rel ) {
- delete attributes[ rel.key ];
- });
+ delete attributes[ rel.key ];
+ });
return new this.constructor( attributes );
},
@@ -1245,36 +1319,233 @@
this.acquire();
var json = Backbone.Model.prototype.toJSON.call( this );
+ if ( this.constructor._superModel && !( this.constructor._subModelTypeAttribute in json ) ) {
+ json[ this.constructor._subModelTypeAttribute ] = this.constructor._subModelTypeValue;
+ }
+
_.each( this._relations, function( rel ) {
- var value = json[ rel.key ];
+ var value = json[ rel.key ];
- if ( rel.options.includeInJSON === true && value && _.isFunction( value.toJSON ) ) {
- json[ rel.keyDestination ] = value.toJSON();
- }
- else if ( _.isString( rel.options.includeInJSON ) ) {
- if ( value instanceof Backbone.Collection ) {
- json[ rel.keyDestination ] = value.pluck( rel.options.includeInJSON );
+ if ( rel.options.includeInJSON === true) {
+ if ( value && _.isFunction( value.toJSON ) ) {
+ json[ rel.keyDestination ] = value.toJSON();
+ }
+ else {
+ json[ rel.keyDestination ] = null;
+ }
}
- else if ( value instanceof Backbone.Model ) {
- json[ rel.keyDestination ] = value.get( rel.options.includeInJSON );
+ else if ( _.isString( rel.options.includeInJSON ) ) {
+ if ( value instanceof Backbone.Collection ) {
+ json[ rel.keyDestination ] = value.pluck( rel.options.includeInJSON );
+ }
+ else if ( value instanceof Backbone.Model ) {
+ json[ rel.keyDestination ] = value.get( rel.options.includeInJSON );
+ }
+ else {
+ json[ rel.keyDestination ] = null;
+ }
}
- }
- else {
- delete json[ rel.key ];
- }
+ else if ( _.isArray( rel.options.includeInJSON ) ) {
+ if ( value instanceof Backbone.Collection ) {
+ var valueSub = [];
+ value.each( function( model ) {
+ var curJson = {};
+ _.each( rel.options.includeInJSON, function( key ) {
+ curJson[ key ] = model.get( key );
+ });
+ valueSub.push( curJson );
+ });
+ json[ rel.keyDestination ] = valueSub;
+ }
+ else if ( value instanceof Backbone.Model ) {
+ var valueSub = {};
+ _.each( rel.options.includeInJSON, function( key ) {
+ valueSub[ key ] = value.get( key );
+ });
+ json[ rel.keyDestination ] = valueSub;
+ }
+ else {
+ json[ rel.keyDestination ] = null;
+ }
+ }
+ else {
+ delete json[ rel.key ];
+ }
- if ( rel.keyDestination !== rel.key ) {
- delete json[ rel.key ];
- }
- }, this );
+ if ( rel.keyDestination !== rel.key ) {
+ delete json[ rel.key ];
+ }
+ });
this.release();
return json;
}
+ },
+ {
+ setup: function( superModel ) {
+ // We don't want to share a relations array with a parent, as this will cause problems with
+ // reverse relations.
+ this.prototype.relations = ( this.prototype.relations || [] ).slice( 0 );
+
+ this._subModels = {};
+ this._superModel = null;
+
+ // If this model has 'subModelTypes' itself, remember them in the store
+ if ( this.prototype.hasOwnProperty( 'subModelTypes' ) ) {
+ Backbone.Relational.store.addSubModels( this.prototype.subModelTypes, this );
+ }
+ // The 'subModelTypes' property should not be inherited, so reset it.
+ else {
+ this.prototype.subModelTypes = null;
+ }
+
+ // Initialize all reverseRelations that belong to this new model.
+ _.each( this.prototype.relations, function( rel ) {
+ if ( !rel.model ) {
+ rel.model = this;
+ }
+
+ if ( rel.reverseRelation && rel.model === this ) {
+ var preInitialize = true;
+ if ( _.isString( rel.relatedModel ) ) {
+ /**
+ * The related model might not be defined for two reasons
+ * 1. it never gets defined, e.g. a typo
+ * 2. it is related to itself
+ * In neither of these cases do we need to pre-initialize reverse relations.
+ */
+ var relatedModel = Backbone.Relational.store.getObjectByName( rel.relatedModel );
+ preInitialize = relatedModel && ( relatedModel.prototype instanceof Backbone.RelationalModel );
+ }
+
+ var type = !_.isString( rel.type ) ? rel.type : Backbone[ rel.type ] || Backbone.Relational.store.getObjectByName( rel.type );
+ if ( preInitialize && type && type.prototype instanceof Backbone.Relation ) {
+ new type( null, rel );
+ }
+ }
+ }, this );
+ },
+
+ /**
+ * Create a 'Backbone.Model' instance based on 'attributes'.
+ * @param {Object} attributes
+ * @param {Object} [options]
+ * @return {Backbone.Model}
+ */
+ build: function( attributes, options ) {
+ var model = this;
+
+ // 'build' is a possible entrypoint; it's possible no model hierarchy has been determined yet.
+ this.initializeModelHierarchy();
+
+ // Determine what type of (sub)model should be built if applicable.
+ // Lookup the proper subModelType in 'this._subModels'.
+ if ( this._subModels && this.prototype.subModelTypeAttribute in attributes ) {
+ var subModelTypeAttribute = attributes[ this.prototype.subModelTypeAttribute ];
+ var subModelType = this._subModels[ subModelTypeAttribute ];
+ if ( subModelType ) {
+ model = subModelType;
+ }
+ }
+
+ return new model( attributes, options );
+ },
+
+ initializeModelHierarchy: function() {
+ // If we're here for the first time, try to determine if this modelType has a 'superModel'.
+ if ( _.isUndefined( this._superModel ) || _.isNull( this._superModel ) ) {
+ Backbone.Relational.store.setupSuperModel( this );
+
+ // If a superModel has been found, copy relations from the _superModel if they haven't been
+ // inherited automatically (due to a redefinition of 'relations').
+ // Otherwise, make sure we don't get here again for this type by making '_superModel' false so we fail
+ // the isUndefined/isNull check next time.
+ if ( this._superModel ) {
+ //
+ if ( this._superModel.prototype.relations ) {
+ var supermodelRelationsExist = _.any( this.prototype.relations, function( rel ) {
+ return rel.model && rel.model !== this;
+ }, this );
+
+ if ( !supermodelRelationsExist ) {
+ this.prototype.relations = this._superModel.prototype.relations.concat( this.prototype.relations );
+ }
+ }
+ }
+ else {
+ this._superModel = false;
+ }
+ }
+
+ // If we came here through 'build' for a model that has 'subModelTypes', and not all of them have been resolved yet, try to resolve each.
+ if ( this.prototype.subModelTypes && _.keys( this.prototype.subModelTypes ).length !== _.keys( this._subModels ).length ) {
+ _.each( this.prototype.subModelTypes, function( subModelTypeName ) {
+ var subModelType = Backbone.Relational.store.getObjectByName( subModelTypeName );
+ subModelType && subModelType.initializeModelHierarchy();
+ });
+ }
+ },
+
+ /**
+ * Find an instance of `this` type in 'Backbone.Relational.store'.
+ * - If `attributes` is a string or a number, `findOrCreate` will just query the `store` and return a model if found.
+ * - If `attributes` is an object, the model will be updated with `attributes` if found.
+ * Otherwise, a new model is created with `attributes` (unless `options.create` is explicitly set to `false`).
+ * @param {Object|String|Number} attributes Either a model's id, or the attributes used to create or update a model.
+ * @param {Object} [options]
+ * @param {Boolean} [options.create=true]
+ * @return {Backbone.RelationalModel}
+ */
+ findOrCreate: function( attributes, options ) {
+ // Try to find an instance of 'this' model type in the store
+ var model = Backbone.Relational.store.find( this, attributes );
+
+ // If we found an instance, update it with the data in 'item'; if not, create an instance
+ // (unless 'options.create' is false).
+ if ( _.isObject( attributes ) ) {
+ if ( model ) {
+ model.set( attributes, options );
+ }
+ else if ( !options || ( options && options.create !== false ) ) {
+ model = this.build( attributes, options );
+ }
+ }
+
+ return model;
+ }
});
_.extend( Backbone.RelationalModel.prototype, Backbone.Semaphore );
/**
+ * Override Backbone.Collection._prepareModel, so objects will be built using the correct type
+ * if the collection.model has subModels.
+ */
+ Backbone.Collection.prototype.__prepareModel = Backbone.Collection.prototype._prepareModel;
+ Backbone.Collection.prototype._prepareModel = function ( model, options ) {
+ options || (options = {});
+ if ( !( model instanceof Backbone.Model ) ) {
+ var attrs = model;
+ options.collection = this;
+
+ if ( typeof this.model.build !== 'undefined' ) {
+ model = this.model.build( attrs, options );
+ }
+ else {
+ model = new this.model( attrs, options );
+ }
+
+ if ( !model._validate( model.attributes, options ) ) {
+ model = false;
+ }
+ }
+ else if ( !model.collection ) {
+ model.collection = this;
+ }
+
+ return model;
+ }
+
+ /**
* Override Backbone.Collection.add, so objects fetched from the server multiple times will
* update the existing Model. Also, trigger 'relational:add'.
*/
@@ -1289,22 +1560,22 @@
//console.debug( 'calling add on coll=%o; model=%o, options=%o', this, models, options );
_.each( models, function( model ) {
- if ( !( model instanceof Backbone.Model ) ) {
- // Try to find 'model' in Backbone.store. If it already exists, set the new properties on it.
- var existingModel = Backbone.Relational.store.find( this.model, model[ this.model.prototype.idAttribute ] );
- if ( existingModel ) {
- existingModel.set( existingModel.parse ? existingModel.parse( model ) : model, options );
- model = existingModel;
+ if ( !( model instanceof Backbone.Model ) ) {
+ // Try to find 'model' in Backbone.store. If it already exists, set the new properties on it.
+ var existingModel = Backbone.Relational.store.find( this.model, model[ this.model.prototype.idAttribute ] );
+ if ( existingModel ) {
+ existingModel.set( existingModel.parse ? existingModel.parse( model ) : model, options );
+ model = existingModel;
+ }
+ else {
+ model = Backbone.Collection.prototype._prepareModel.call( this, model, options );
+ }
}
- else {
- model = Backbone.Collection.prototype._prepareModel.call( this, model, options );
+
+ if ( model instanceof Backbone.Model && !this.get( model ) && !this.getByCid( model ) ) {
+ modelsToAdd.push( model );
}
- }
-
- if ( model instanceof Backbone.Model && !this.get( model ) && !this.getByCid( model ) ) {
- modelsToAdd.push( model );
- }
- }, this );
+ }, this );
// Add 'models' in a single batch, so the original add will only be called once (and thus 'sort', etc).
@@ -1312,8 +1583,8 @@
add.call( this, modelsToAdd, options );
_.each( modelsToAdd, function( model ) {
- this.trigger('relational:add', model, this, options);
- }, this );
+ this.trigger( 'relational:add', model, this, options );
+ }, this );
}
return this;
@@ -1325,19 +1596,22 @@
var remove = Backbone.Collection.prototype.__remove = Backbone.Collection.prototype.remove;
Backbone.Collection.prototype.remove = function( models, options ) {
options || (options = {});
- if (!_.isArray( models ) ) {
+ if ( !_.isArray( models ) ) {
models = [ models ];
}
+ else {
+ models = models.slice( 0 );
+ }
//console.debug('calling remove on coll=%o; models=%o, options=%o', this, models, options );
_.each( models, function( model ) {
- model = this.getByCid( model ) || this.get( model );
+ model = this.getByCid( model ) || this.get( model );
- if ( model instanceof Backbone.Model ) {
- remove.call( this, model, options );
- this.trigger('relational:remove', model, this, options);
- }
- }, this );
+ if ( model instanceof Backbone.Model ) {
+ remove.call( this, model, options );
+ this.trigger('relational:remove', model, this, options);
+ }
+ }, this );
return this;
};
@@ -1348,7 +1622,18 @@
var reset = Backbone.Collection.prototype.__reset = Backbone.Collection.prototype.reset;
Backbone.Collection.prototype.reset = function( models, options ) {
reset.call( this, models, options );
- this.trigger( 'relational:reset', models, options );
+ this.trigger( 'relational:reset', this, options );
+
+ return this;
+ };
+
+ /**
+ * Override 'Backbone.Collection.sort' to trigger 'relational:reset'.
+ */
+ var sort = Backbone.Collection.prototype.__sort = Backbone.Collection.prototype.sort;
+ Backbone.Collection.prototype.sort = function( options ) {
+ sort.call( this, options );
+ this.trigger( 'relational:reset', this, options );
return this;
};
@@ -1372,35 +1657,12 @@
return this;
};
- // Override .extend() to check for reverseRelations to initialize.
+ // Override .extend() to automatically call .setup()
Backbone.RelationalModel.extend = function( protoProps, classProps ) {
var child = Backbone.Model.extend.apply( this, arguments );
-
- var relations = ( protoProps && protoProps.relations ) || [];
- _.each( relations, function( rel ) {
- if( rel.reverseRelation ) {
- rel.model = child;
-
- var preInitialize = true;
- if ( _.isString( rel.relatedModel ) ) {
- /**
- * The related model might not be defined for two reasons
- * 1. it never gets defined, e.g. a typo
- * 2. it is related to itself
- * In neither of these cases do we need to pre-initialize reverse relations.
- */
- var relatedModel = Backbone.Relational.store.getObjectByName( rel.relatedModel );
- preInitialize = relatedModel && ( relatedModel.prototype instanceof Backbone.RelationalModel.prototype.constructor );
- }
-
- var type = !_.isString( rel.type ) ? rel.type : Backbone[ rel.type ] || Backbone.Relational.store.getObjectByName( rel.type );
- if ( preInitialize && type && type.prototype instanceof Backbone.Relation.prototype.constructor ) {
- new type( null, rel );
- }
- }
- });
+
+ child.setup( this );
return child;
};
-
})();
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

27 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/adc8114131fa/
changeset: adc8114131fa
user: jgoecks
date: 2012-06-27 20:55:54
summary: Use url_for to generate logo URL.
affected #: 3 files
diff -r 8cd9f0ce913260795ee749536face3bd54f1bc62 -r adc8114131fa700da3b5800d7ba4568bd665c9b5 templates/webapps/community/base_panels.mako
--- a/templates/webapps/community/base_panels.mako
+++ b/templates/webapps/community/base_panels.mako
@@ -118,7 +118,7 @@
## Logo, layered over tabs to be clickable
<div class="title">
- <a href="${app.config.get( 'logo_url', '/' )}">
+ <a href="${h.url_for( app.config.get( 'logo_url', '/' ) )}"><img border="0" src="${h.url_for('/static/images/galaxyIcon_noText.png')}">
Galaxy Tool Shed
%if app.config.brand:
diff -r 8cd9f0ce913260795ee749536face3bd54f1bc62 -r adc8114131fa700da3b5800d7ba4568bd665c9b5 templates/webapps/galaxy/base_panels.mako
--- a/templates/webapps/galaxy/base_panels.mako
+++ b/templates/webapps/galaxy/base_panels.mako
@@ -184,7 +184,7 @@
## Logo, layered over tabs to be clickable
<div class="title">
- <a href="${app.config.get( 'logo_url', '/' )}">
+ <a href="${h.url_for( app.config.get( 'logo_url', '/' ) )}"><img border="0" src="${h.url_for('/static/images/galaxyIcon_noText.png')}">
Galaxy
%if app.config.brand:
diff -r 8cd9f0ce913260795ee749536face3bd54f1bc62 -r adc8114131fa700da3b5800d7ba4568bd665c9b5 templates/webapps/reports/base_panels.mako
--- a/templates/webapps/reports/base_panels.mako
+++ b/templates/webapps/reports/base_panels.mako
@@ -27,7 +27,7 @@
</div>
## Logo, layered over tabs to be clickable
<div class="title" style="position: absolute; top: 0; left: 0;">
- <a href="${app.config.get( 'logo_url', '/' )}">
+ <a href="${h.url_for( app.config.get( 'logo_url', '/' ) )}"><img border="0" src="${h.url_for('/static/images/galaxyIcon_noText.png')}" style="width: 26px; vertical-align: top;">
Galaxy Reports
%if app.config.brand:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: jgoecks: Add tipsy config to icon buttons and add tipsy to paramamonster.
by Bitbucket 27 Jun '12
by Bitbucket 27 Jun '12
27 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/8cd9f0ce9132/
changeset: 8cd9f0ce9132
user: jgoecks
date: 2012-06-27 18:12:43
summary: Add tipsy config to icon buttons and add tipsy to paramamonster.
affected #: 3 files
diff -r 27f54f28e9f1542e9681b8a4c238d856be7b9a34 -r 8cd9f0ce913260795ee749536face3bd54f1bc62 static/scripts/mvc/ui.js
--- a/static/scripts/mvc/ui.js
+++ b/static/scripts/mvc/ui.js
@@ -8,10 +8,14 @@
* defines an icon button. Each dictionary must have the following
* elements: icon_class, title, and on_click.
*/
-var create_icon_buttons_menu = function(config) {
+var create_icon_buttons_menu = function(config, global_config) {
+ if (!global_config) { global_config = {}; }
+
// Create and initialize menu.
var buttons = new IconButtonCollection(
- _.map(config, function(button_config) { return new IconButton(button_config); })
+ _.map(config, function(button_config) {
+ return new IconButton(_.extend(button_config, global_config));
+ })
);
return new IconButtonMenuView( {collection: buttons} );
@@ -38,7 +42,8 @@
defaults: {
title: "",
icon_class: "",
- on_click: null
+ on_click: null,
+ tipsy_config: {}
}
});
@@ -60,12 +65,17 @@
var self = this;
this.collection.each(function(button) {
// Create and add icon button to menu.
- $("<a/>").attr('href', 'javascript:void(0)')
+ var elt =
+ $('<a/>').attr('href', 'javascript:void(0)')
.attr('title', button.attributes.title)
.addClass('icon-button menu-button')
.addClass(button.attributes.icon_class)
.appendTo(self.$el)
.click(button.attributes.on_click);
+
+ if (button.attributes.tipsy_config) {
+ elt.tipsy(button.attributes.tipsy_config);
+ }
});
return this;
}
diff -r 27f54f28e9f1542e9681b8a4c238d856be7b9a34 -r 8cd9f0ce913260795ee749536face3bd54f1bc62 static/scripts/viz/paramamonster.js
--- a/static/scripts/viz/paramamonster.js
+++ b/static/scripts/viz/paramamonster.js
@@ -294,7 +294,8 @@
icon_class: 'gear track-settings',
on_click: function () {
settings_div.toggle();
- }
+ },
+ tipsy_config: { gravity: 's' }
}
]);
settings_td.prepend(icon_menu.$el);
@@ -390,7 +391,7 @@
var self = this,
menu = create_icon_buttons_menu([
{
- title: 'Add',
+ title: 'Add parameter to tree',
icon_class: 'plus-button',
on_click: function () {
input.set('in_ptree', true);
@@ -400,7 +401,7 @@
},
{
- title: 'Remove',
+ title: 'Remove parameter from tree',
icon_class: 'toggle',
on_click: function() {
// Remove parameter from tree params where name matches clicked paramter.
@@ -409,7 +410,10 @@
single_input_row.show();
}
}
- ]);
+ ],
+ {
+ tipsy_config: {gravity: 's'}
+ });
this.$el.prepend(menu.$el);
// Update input's min, max, number of samples as values change.
diff -r 27f54f28e9f1542e9681b8a4c238d856be7b9a34 -r 8cd9f0ce913260795ee749536face3bd54f1bc62 templates/tracks/browser.mako
--- a/templates/tracks/browser.mako
+++ b/templates/tracks/browser.mako
@@ -177,14 +177,14 @@
{ icon_class: 'cross-circle', title: 'Close', on_click: function() {
window.location = "${h.url_for( controller='visualization', action='list' )}";
} }
- ]);
+ ],
+ {
+ tipsy_config: {gravity: 'n'}
+ });
menu.$el.attr("style", "float: right");
$("#center .unified-panel-header-inner").append(menu.$el);
- // Manual tipsy config because default gravity is S and cannot be changed.
- $(".menu-button").tipsy( {gravity: 'n'} );
-
// Hide bookmarks by default right now.
parent.force_right_panel("hide");
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: jgoecks: (a) Paramamonster implemention; (b) bug fixes and small additions to style sheets; and (c) bug fixes for rerunning tools on complete datasets.
by Bitbucket 27 Jun '12
by Bitbucket 27 Jun '12
27 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/27f54f28e9f1/
changeset: 27f54f28e9f1
user: jgoecks
date: 2012-06-27 16:51:20
summary: (a) Paramamonster implemention; (b) bug fixes and small additions to style sheets; and (c) bug fixes for rerunning tools on complete datasets.
affected #: 10 files
diff -r 21ec1290ad02beb9c33516dcc4d5d4a732559414 -r 27f54f28e9f1542e9681b8a4c238d856be7b9a34 lib/galaxy/web/api/tools.py
--- a/lib/galaxy/web/api/tools.py
+++ b/lib/galaxy/web/api/tools.py
@@ -133,8 +133,9 @@
# Run tool on region if region is specificied.
run_on_regions = False
- regions = from_json_string( payload.get( 'regions', None ) )
+ regions = payload.get( 'regions', None )
if regions:
+ regions = from_json_string( regions )
if isinstance( regions, dict ):
# Regions is a single region.
regions = [ GenomeRegion.from_dict( regions ) ]
@@ -256,7 +257,8 @@
# Set input datasets for tool. If running on regions, extract and use subset
# when possible.
#
- regions_str = ",".join( [ str( r ) for r in regions ] )
+ if run_on_regions:
+ regions_str = ",".join( [ str( r ) for r in regions ] )
for jida in original_job.input_datasets:
# If param set previously by config actions, do nothing.
if jida.name in params_set:
diff -r 21ec1290ad02beb9c33516dcc4d5d4a732559414 -r 27f54f28e9f1542e9681b8a4c238d856be7b9a34 static/june_2007_style/base.less
--- a/static/june_2007_style/base.less
+++ b/static/june_2007_style/base.less
@@ -650,7 +650,7 @@
}
div.form-row-input {
- width: 300px;
+ width: 90%;
float: left;
}
@@ -696,7 +696,7 @@
select, textarea, input[type="text"], input[type="file"], input[type="password"] {
// -webkit-box-sizing: border-box;
- max-width: 300px;
+ max-width: 90%;
}
textarea, input[type="text"], input[type="password"] {
diff -r 21ec1290ad02beb9c33516dcc4d5d4a732559414 -r 27f54f28e9f1542e9681b8a4c238d856be7b9a34 static/june_2007_style/base_sprites.less.tmpl
--- a/static/june_2007_style/base_sprites.less.tmpl
+++ b/static/june_2007_style/base_sprites.less.tmpl
@@ -52,6 +52,10 @@
}
.icon-button.toggle {
-sprite-group: fugue;
+ -sprite-image: fugue/toggle-bw.png;
+}
+.icon-button.toggle:hover {
+ -sprite-group: fugue;
-sprite-image: fugue/toggle.png;
}
.icon-button.arrow-circle {
diff -r 21ec1290ad02beb9c33516dcc4d5d4a732559414 -r 27f54f28e9f1542e9681b8a4c238d856be7b9a34 static/june_2007_style/blue/base.css
--- a/static/june_2007_style/blue/base.css
+++ b/static/june_2007_style/blue/base.css
@@ -742,23 +742,24 @@
.icon-button.tag--plus{background:url(fugue.png) no-repeat 0px -52px;}
.icon-button.toggle-expand{background:url(fugue.png) no-repeat 0px -78px;}
.icon-button.toggle{background:url(fugue.png) no-repeat 0px -104px;}
-.icon-button.arrow-circle{background:url(fugue.png) no-repeat 0px -130px;}
-.icon-button.chevron{background:url(fugue.png) no-repeat 0px -156px;}
-.icon-button.bug{background:url(fugue.png) no-repeat 0px -182px;}
-.icon-button.disk{background:url(fugue.png) no-repeat 0px -208px;}
-.icon-button.information{background:url(fugue.png) no-repeat 0px -234px;}
-.icon-button.annotate{background:url(fugue.png) no-repeat 0px -260px;}
-.icon-button.go-to-full-screen{background:url(fugue.png) no-repeat 0px -286px;}
-.icon-button.import{background:url(fugue.png) no-repeat 0px -312px;}
-.icon-button.plus-button{background:url(fugue.png) no-repeat 0px -338px;}
-.icon-button.plus-button:hover{background:url(fugue.png) no-repeat 0px -364px;}
-.icon-button.gear{background:url(fugue.png) no-repeat 0px -390px;}
-.icon-button.chart_curve{background:url(fugue.png) no-repeat 0px -416px;}
-.icon-button.disk--arrow{background:url(fugue.png) no-repeat 0px -442px;}
-.icon-button.disk--arrow:hover{background:url(fugue.png) no-repeat 0px -468px;}
-.icon-button.cross-circle{background:url(fugue.png) no-repeat 0px -494px;}
-.icon-button.cross-circle:hover{background:url(fugue.png) no-repeat 0px -520px;}
-.text-and-autocomplete-select{background:url(fugue.png) no-repeat right -546px;}
+.icon-button.toggle:hover{background:url(fugue.png) no-repeat 0px -130px;}
+.icon-button.arrow-circle{background:url(fugue.png) no-repeat 0px -156px;}
+.icon-button.chevron{background:url(fugue.png) no-repeat 0px -182px;}
+.icon-button.bug{background:url(fugue.png) no-repeat 0px -208px;}
+.icon-button.disk{background:url(fugue.png) no-repeat 0px -234px;}
+.icon-button.information{background:url(fugue.png) no-repeat 0px -260px;}
+.icon-button.annotate{background:url(fugue.png) no-repeat 0px -286px;}
+.icon-button.go-to-full-screen{background:url(fugue.png) no-repeat 0px -312px;}
+.icon-button.import{background:url(fugue.png) no-repeat 0px -338px;}
+.icon-button.plus-button{background:url(fugue.png) no-repeat 0px -364px;}
+.icon-button.plus-button:hover{background:url(fugue.png) no-repeat 0px -390px;}
+.icon-button.gear{background:url(fugue.png) no-repeat 0px -416px;}
+.icon-button.chart_curve{background:url(fugue.png) no-repeat 0px -442px;}
+.icon-button.disk--arrow{background:url(fugue.png) no-repeat 0px -468px;}
+.icon-button.disk--arrow:hover{background:url(fugue.png) no-repeat 0px -494px;}
+.icon-button.cross-circle{background:url(fugue.png) no-repeat 0px -520px;}
+.icon-button.cross-circle:hover{background:url(fugue.png) no-repeat 0px -546px;}
+.text-and-autocomplete-select{background:url(fugue.png) no-repeat right -572px;}
div.historyItem-error .state-icon{background:url(history-states.png) no-repeat 0px 0px;}
div.historyItem-empty .state-icon{background:url(history-states.png) no-repeat 0px -25px;}
div.historyItem-queued .state-icon{background:url(history-states.png) no-repeat 0px -50px;}
diff -r 21ec1290ad02beb9c33516dcc4d5d4a732559414 -r 27f54f28e9f1542e9681b8a4c238d856be7b9a34 static/june_2007_style/blue/fugue.png
Binary file static/june_2007_style/blue/fugue.png has changed
diff -r 21ec1290ad02beb9c33516dcc4d5d4a732559414 -r 27f54f28e9f1542e9681b8a4c238d856be7b9a34 static/scripts/mvc/tools.js
--- a/static/scripts/mvc/tools.js
+++ b/static/scripts/mvc/tools.js
@@ -52,6 +52,26 @@
],
urlRoot: galaxy_paths.get('tool_url'),
+
+ /**
+ * Returns object copy, optionally including only inputs that can be sampled.
+ */
+ copy: function(only_samplable_inputs) {
+ var copy = new Tool(this.toJSON());
+
+ // Return only samplable inputs if flag is set.
+ if (only_samplable_inputs) {
+ var valid_inputs = new Backbone.Collection();
+ copy.get('inputs').each(function(input) {
+ if (input.get_samples()) {
+ valid_inputs.push(input);
+ }
+ });
+ copy.set('inputs', valid_inputs);
+ }
+
+ return copy;
+ },
apply_search_results: function(results) {
( _.indexOf(results, this.attributes.id) !== -1 ? this.show() : this.hide() );
@@ -81,7 +101,7 @@
* Run tool; returns a Deferred that resolves to the tool's output(s).
*/
run: function() {
- return this._run()
+ return this._run();
},
/**
@@ -94,6 +114,17 @@
regions: JSON.stringify(regions)
});
},
+
+ /**
+ * Returns input dict for tool's inputs.
+ */
+ get_inputs_dict: function() {
+ var input_dict = {};
+ this.get('inputs').each(function(input) {
+ input_dict[input.get('name')] = input.get('value');
+ });
+ return input_dict;
+ },
/**
* Run tool; returns a Deferred that resolves to the tool's output(s).
@@ -102,13 +133,9 @@
_run: function(additional_params) {
// Create payload.
var payload = _.extend({
- tool_id: this.id
- }, additional_params),
- input_dict = {};
- this.get('inputs').each(function(input) {
- input_dict[input.get('name')] = input.get('value');
- });
- payload.inputs = input_dict;
+ tool_id: this.id,
+ inputs: this.get_inputs_dict()
+ }, additional_params);
// Because job may require indexing datasets, use server-side
// deferred to ensure that job is run. Also use deferred that
@@ -145,21 +172,27 @@
label: null,
type: null,
value: null,
+ num_samples: 5
},
initialize: function() {
this.attributes.html = unescape(this.attributes.html);
},
+
+ copy: function() {
+ return new ToolInput(this.toJSON());
+ },
/**
* Returns samples from a tool input.
*/
- get_samples: function(num_samples) {
- var
- type = this.get('type'),
- samples = []
+ get_samples: function() {
+ var type = this.get('type'),
+ samples = null;
if (type === 'number') {
- samples = d3.scale.linear().domain([this.get('min'), this.get('max')]).ticks(num_samples);
+ samples = d3.scale.linear()
+ .domain([this.get('min'), this.get('max')])
+ .ticks(this.get('num_samples'));
}
else if (type === 'select') {
samples = _.map(this.get('options'), function(option) {
@@ -167,24 +200,11 @@
});
}
- return new ParamSamples({
- param: this,
- samples: samples
- });
+ return samples;
}
});
/**
- * A tool and parameter samples.
- */
-var ParamSamples = Backbone.Model.extend({
- defaults: {
- param: null,
- samples: null
- }
-})
-
-/**
* Wrap collection of tools for fast access/manipulation.
*/
var ToolCollection = Backbone.Collection.extend({
diff -r 21ec1290ad02beb9c33516dcc4d5d4a732559414 -r 27f54f28e9f1542e9681b8a4c238d856be7b9a34 static/scripts/mvc/ui.js
--- a/static/scripts/mvc/ui.js
+++ b/static/scripts/mvc/ui.js
@@ -51,6 +51,10 @@
*/
var IconButtonMenuView = Backbone.View.extend({
tagName: 'div',
+
+ initialize: function() {
+ this.render();
+ },
render: function() {
var self = this;
diff -r 21ec1290ad02beb9c33516dcc4d5d4a732559414 -r 27f54f28e9f1542e9681b8a4c238d856be7b9a34 static/scripts/viz/paramamonster.js
--- a/static/scripts/viz/paramamonster.js
+++ b/static/scripts/viz/paramamonster.js
@@ -4,95 +4,230 @@
*/
/**
- * --- Models ---
+ * Tree for a tool's parameters.
*/
-
var ToolParameterTree = Backbone.Model.extend({
defaults: {
tool: null,
- params: null,
- num_samples: 4
- },
-
-
- initialize: function(options) {
- //
- // -- Create tree data from tool. --
- //
-
- // Valid inputs for tree are number, select parameters.
- var tool = this.get('tool'),
- num_samples = this.get('num_samples'),
- params_samples = tool.get('inputs').map(function(input) {
- return input.get_samples(num_samples);
- }),
- filtered_params_samples = _.filter(params_samples, function(param_sample) {
- return param_sample.get('samples').length !== 0;
- });
-
- /**
- * Returns tree data. Params_sampling is an array of
- *
- */
- var create_tree_data = function(params_samples, index) {
- var
- param_samples = params_samples[index],
- param = param_samples.get('param'),
- param_label = param.get('label'),
- settings = param_samples.get('samples');
-
- // Create leaves when last parameter setting is reached.
- if (params_samples.length - 1 === index) {
- return _.map(settings, function(setting) {
- return {
- name: param_label + '=' + setting,
- param: param,
- value: setting
- }
- });
- }
-
- // Recurse to handle other parameters.
- return _.map(settings, function(setting) {
- return {
- name: param_label + '=' + setting,
- param: param,
- value: setting,
- children: create_tree_data(filtered_params_samples, index + 1)
- }
- });
- };
-
- var tree_data = {
- name: 'Parameter Tree for ' + tool.get('name'),
- children: create_tree_data(filtered_params_samples, 0)
- };
-
- // Set valid inputs, tree data for later use.
- this.set('params', _.map(params_samples, function(s) { return s.get('param') }));
- this.set('tree_data', tree_data);
- }
-
-});
-
-/**
- * Tile of rendered genomic data.
- */
-var Tile = Backbone.Model.extend({
- defaults: {
- track: null,
- index: null,
- region: null,
- resolution: null,
- data: null,
- stale: null,
- html_elt: null
+ tree_data: null
},
initialize: function(options) {
+ // Set up tool parameters to work with tree.
+ var self = this;
+ this.get('tool').get('inputs').each(function(input) {
+ if (!input.get_samples()) { return; }
+
+ // All inputs are in tree to start.
+ self.add_param(input);
+
+ // Listen for changes to input's attributes.
+ input.on('change:min change:max change:num_samples', function(input) {
+ if (input.get('in_ptree')) {
+ self.set_tree_data();
+ }
+ }, self);
+ input.on('change:in_ptree', function(input) {
+ if (input.get('in_ptree')) {
+ self.add_param(input);
+ }
+ else {
+ self.remove_param(input);
+ }
+ self.set_tree_data();
+ }, self);
+ });
+
+ self.set_tree_data();
+ },
+
+ add_param: function(param) {
+ // If parameter already present, do not add it.
+ if (param.get('ptree_index')) { return; }
+
+ param.set('in_ptree', true);
+ param.set('ptree_index', this.get_tree_params().length);
+ },
+
+ remove_param: function(param) {
+ // Remove param from tree.
+ param.set('in_ptree', false);
+ param.set('ptree_index', null);
+
+ // Update ptree indices for remaining params.
+ _(this.get_tree_params()).each(function(input, index) {
+ // +1 to use 1-based indexing.
+ input.set('ptree_index', index + 1);
+ });
+ },
+
+ /**
+ * Sets tree data using tool's inputs.
+ */
+ set_tree_data: function() {
+ // Get samples for each parameter.
+ var params_samples = _.map(this.get_tree_params(), function(param) {
+ return {
+ param: param,
+ samples: param.get_samples()
+ };
+ });
+ var node_id = 0,
+ // Creates tree data recursively.
+ create_tree_data = function(params_samples, index) {
+ var param_samples = params_samples[index],
+ param = param_samples.param,
+ param_label = param.get('label'),
+ settings = param_samples.samples;
+
+ // Create leaves when last parameter setting is reached.
+ if (params_samples.length - 1 === index) {
+ return _.map(settings, function(setting) {
+ return {
+ id: node_id++,
+ name: setting,
+ param: param,
+ value: setting
+ };
+ });
+ }
+
+ // Recurse to handle other parameters.
+ return _.map(settings, function(setting) {
+ return {
+ id: node_id++,
+ name: setting,
+ param: param,
+ value: setting,
+ children: create_tree_data(params_samples, index + 1)
+ };
+ });
+ };
+
+ this.set('tree_data', {
+ name: 'Root',
+ children: (params_samples.length !== 0 ? create_tree_data(params_samples, 0) : null)
+ });
+ },
+
+ get_tree_params: function() {
+ // Filter and sort parameters to get list in tree.
+ return _(this.get('tool').get('inputs').where( {in_ptree: true} ))
+ .sortBy( function(input) { return input.get('ptree_index'); } );
+ },
+
+ /**
+ * Returns number of leaves in tree.
+ */
+ get_num_leaves: function() {
+ return this.get_tree_params().reduce(function(memo, param) { return memo * param.get_samples().length; }, 1);
+ },
+
+ /**
+ * Returns array of settings based on a node and its subtree.
+ */
+ get_node_settings: function(target_node) {
+ // -- Get fixed settings from tool and parent nodes.
+
+ // Start with tool's settings.
+ var fixed_settings = this.get('tool').get_inputs_dict();
+
+ // Get fixed settings using node's parents.
+ var cur_node = target_node.parent;
+ if (cur_node) {
+ while(cur_node.depth !== 0) {
+ fixed_settings[cur_node.param.get('name')] = cur_node.value;
+ cur_node = cur_node.parent;
+ }
+ }
+ // Walk subtree starting at clicked node to get full list of settings.
+ var get_settings = function(node, settings) {
+ // Add setting for this node.
+ settings[node.param.get('name')] = node.value;
+
+ if (!node.children) {
+ // At leaf node: add param setting and return.
+ return settings;
+ }
+ else {
+ // At interior node: return list of subtree settings.
+ return _.flatten( _.map(node.children, function(c) { return get_settings(c, _.clone(settings)); }) );
+ }
+ },
+ all_settings = get_settings(target_node, fixed_settings);
+
+ // If user clicked on leaf, settings is a single dict. Convert to array for simplicity.
+ if (!_.isArray(all_settings)) { all_settings = [ all_settings ]; }
+
+ return all_settings;
+ },
+
+ /**
+ * Returns all nodes connected a particular node; this includes parents and children of the node.
+ */
+ get_connected_nodes: function(node) {
+ var get_subtree_nodes = function(a_node) {
+ if (!a_node.children) {
+ return a_node;
+ }
+ else {
+ // At interior node: return subtree nodes.
+ return _.flatten( [a_node, _.map(a_node.children, function(c) { return get_subtree_nodes(c); })] );
+ }
+ };
+
+ // Get node's parents.
+ var parents = [],
+ cur_parent = node.parent;
+ while(cur_parent) {
+ parents.push(cur_parent);
+ cur_parent = cur_parent.parent;
+ }
+
+ return _.flatten([parents, get_subtree_nodes(node)]);
+ },
+
+ /**
+ * Returns the leaf that corresponds to a settings collection.
+ */
+ get_leaf: function(settings) {
+ var cur_node = this.get('tree_data'),
+ find_child = function(children) {
+ return _.find(children, function(child) {
+ return settings[child.param.get('name')] === child.value;
+ });
+ };
+
+ while (cur_node.children) {
+ cur_node = find_child(cur_node.children);
+ }
+ return cur_node;
}
-
+});
+
+var ParamaMonsterTrack = Backbone.Model.extend({
+ defaults: {
+ track: null,
+ settings: null,
+ regions: null
+ },
+
+ same_settings: function(a_track) {
+ var this_settings = this.get('settings'),
+ other_settings = a_track.get('settings');
+ for (var prop in this_settings) {
+ if (!other_settings[prop] ||
+ this_settings[prop] !== other_settings[prop]) {
+ return false;
+ }
+ }
+ return true;
+ }
+});
+
+var TrackCollection = Backbone.Collection.extend({
+ model: ParamaMonsterTrack
});
/**
@@ -102,11 +237,24 @@
defaults: _.extend({}, Visualization.prototype.defaults, {
tool: null,
parameter_tree: null,
- regions: null
+ regions: null,
+ tracks: null
}),
initialize: function(options) {
- this.set('parameter_tree', new ToolParameterTree({ tool: this.get('tool') }));
+ var tool_with_samplable_inputs = this.get('tool').copy(true);
+ this.set('tool_with_samplable_inputs', tool_with_samplable_inputs);
+
+ this.set('parameter_tree', new ToolParameterTree({ tool: tool_with_samplable_inputs }));
+ this.set('tracks', new TrackCollection());
+ },
+
+ add_placeholder: function(settings) {
+ this.get('tracks').add(new PlaceholderTrack(settings));
+ },
+
+ add_track: function(track) {
+ this.get('tracks').add(track);
}
});
@@ -114,87 +262,388 @@
* --- Views ---
*/
-var TileView = Backbone.View.extend({
-
+/**
+ * ParamaMonster track view.
+ */
+var ParamaMonsterTrackView = Backbone.View.extend({
+ tagName: 'tr',
+
+ initialize: function(options) {
+ this.canvas_manager = options.canvas_manager;
+ this.render();
+ this.model.on('change:track', this.draw_tiles, this);
+ },
+
+ render: function() {
+ // Render settings icon and popup.
+ // TODO: use template.
+ var settings = this.model.get('settings'),
+ settings_td = $('<td/>').addClass('settings').appendTo(this.$el),
+ settings_div = $('<div/>').addClass('track-info').hide().appendTo(settings_td);
+ settings_div.append( $('<div/>').css('font-weight', 'bold').text('Track Settings') );
+ _.each(_.keys(settings), function(name) {
+ settings_div.append( name + ': ' + settings[name] + '<br/>');
+ });
+ var self = this,
+ run_on_dataset_button = $('<button/>').appendTo(settings_div).text('Run on complete dataset').click(function() {
+ self.trigger('run_on_dataset', settings);
+ });
+ var icon_menu = create_icon_buttons_menu([
+ {
+ title: 'Settings',
+ icon_class: 'gear track-settings',
+ on_click: function () {
+ settings_div.toggle();
+ }
+ }
+ ]);
+ settings_td.prepend(icon_menu.$el);
+
+ // Render tile placeholders.
+ _.each(this.model.get('regions'), function() {
+ self.$el.append($('<td/>').addClass('tile').html(
+ $('<img/>').attr('src', galaxy_paths.get('image_path') + '/loading_large_white_bg.gif')
+ ));
+ });
+
+ if (this.model.get('track')) {
+ this.draw_tiles();
+ }
+ },
+
+ draw_tiles: function() {
+ // Display tiles for regions of interest.
+ var self = this,
+ track = this.model.get('track'),
+ regions = this.model.get('regions'),
+ tile_containers = this.$el.find('td.tile');
+
+ // When data is ready, draw tiles.
+ $.when(track.data_manager.data_is_ready()).then(function(data_ok) {
+ // Draw tile for each region.
+ _.each(regions, function(region, index) {
+ var resolution = region.length() / 300,
+ w_scale = 1/resolution,
+ mode = 'Pack';
+ $.when(track.data_manager.get_data(region, mode, resolution, {})).then(function(tile_data) {
+ var canvas = self.canvas_manager.new_canvas();
+ canvas.width = 300;
+ canvas.height = track.get_canvas_height(tile_data, mode, w_scale, canvas.width);
+ track.draw_tile(tile_data, canvas.getContext('2d'), mode, resolution, region, w_scale);
+ $(tile_containers[index]).empty().append(canvas);
+ });
+ });
+ });
+ }
});
+/**
+ * Tool input (parameter) that enables both value and sweeping inputs. View is unusual as
+ * it augments an existing input form row rather than creates a completely new HTML element.
+ */
+var ToolInputValOrSweepView = Backbone.View.extend({
+
+ // Template for rendering sweep inputs:
+ number_input_template: '<div class="form-row-input sweep">' +
+ '<input class="min" type="text" size="6" value="<%= min %>"> - ' +
+ '<input class="max" type="text" size="6" value="<%= max %>">' +
+ ' samples: <input class="num_samples" type="text" size="1" value="<%= num_samples %>">' +
+ '</div>',
+
+ select_input_template: '<div class="form-row-input sweep"><%= options %></div>',
+
+ initialize: function(options) {
+ this.$el = options.tool_row;
+ this.render();
+ },
+
+ render: function() {
+ var input = this.model,
+ type = input.get('type'),
+ single_input_row = this.$el.find('.form-row-input'),
+ sweep_inputs_row = null;
+
+ // Update tool inputs as single input changes.
+ single_input_row.find('input').change(function() {
+ input.set('value', $(this).val());
+ });
+
+ // Add row for parameter sweep inputs.
+ if (type === 'number') {
+ sweep_inputs_row = $(_.template(this.number_input_template, this.model.toJSON()));
+ }
+ else if (type === 'select') {
+ var options = _.map(this.$el.find('select option'), function(option) {
+ return $(option).val();
+ }),
+ options_text = options.join(', ');
+ sweep_inputs_row = $(_.template(this.select_input_template, {
+ options: options_text
+ }));
+ }
+
+ // Fow now, assume parameter is included in tree to start.
+ sweep_inputs_row.insertAfter(single_input_row);
+ single_input_row.hide();
+
+ // Add buttons for adding/removing parameter.
+ var self = this,
+ menu = create_icon_buttons_menu([
+ {
+ title: 'Add',
+ icon_class: 'plus-button',
+ on_click: function () {
+ input.set('in_ptree', true);
+ single_input_row.hide();
+ sweep_inputs_row.show();
+ }
+
+ },
+ {
+ title: 'Remove',
+ icon_class: 'toggle',
+ on_click: function() {
+ // Remove parameter from tree params where name matches clicked paramter.
+ input.set('in_ptree', false);
+ sweep_inputs_row.hide();
+ single_input_row.show();
+ }
+ }
+ ]);
+ this.$el.prepend(menu.$el);
+
+ // Update input's min, max, number of samples as values change.
+ _.each(['min', 'max', 'num_samples'], function(attr) {
+ sweep_inputs_row.find('.' + attr).change(function() {
+ input.set(attr, parseFloat( $(this).val() ));
+ });
+ });
+ }
+});
+
+var ToolParameterTreeDesignView = Backbone.View.extend({
+ className: 'tree-design',
+
+ initialize: function(options) {
+ this.render();
+ },
+
+ render: function() {
+ // Start with tool form view.
+ var tool_form_view = new ToolFormView({
+ model: this.model.get('tool')
+ });
+ tool_form_view.render();
+ this.$el.append(tool_form_view.$el);
+
+ // Set up views for each tool input.
+ var self = this,
+ inputs = self.model.get('tool').get('inputs');
+ this.$el.find('.form-row').not('.form-actions').each(function(i) {
+ var input_view = new ToolInputValOrSweepView({
+ model: inputs.at(i),
+ tool_row: $(this)
+ });
+ });
+ }
+});
+
+/**
+ * Displays and updates parameter tree.
+ */
var ToolParameterTreeView = Backbone.View.extend({
className: 'tool-parameter-tree',
initialize: function(options) {
+ // When tree data changes, re-render.
+ this.model.on('change:tree_data', this.render, this);
},
render: function() {
- var width = 960,
- height = 2000;
+ var tree_params = this.model.get_tree_params();
+ // Start fresh.
+ this.$el.children().remove();
+
+ // Set width, height based on params and samples.
+ this.width = 100 * (2 + tree_params.length);
+ this.height = 15 * this.model.get_num_leaves();
+
+ var self = this;
// Layout tree.
var cluster = d3.layout.cluster()
- .size([height, width - 160]);
+ .size([this.height - 10, this.width - 160]);
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x]; });
+ // Layout nodes.
+ var nodes = cluster.nodes(this.model.get('tree_data'));
+
+ // Setup and add labels for tree levels.
+ var param_depths = _.uniq(_.pluck(nodes, "y"));
+ _.each(tree_params, function(param, index) {
+ var x = param_depths[index+1];
+ self.$el.append( $('<div>').addClass('label')
+ .text(param.get('label'))
+ // HACK: add 250 b/c in center panel.
+ .css('left', x + 250) );
+ });
+
// Set up vis element.
var vis = d3.select(this.$el[0])
.append("svg")
- .attr("width", width)
- .attr("height", height)
+ .attr("width", this.width)
+ .attr("height", this.height)
.append("g")
- .attr("transform", "translate(80, 0)");
+ .attr("transform", "translate(40, 10)");
- // Set up nodes, links.
- var nodes = cluster.nodes(this.model.get('tree_data'));
-
+ // Draw links.
var link = vis.selectAll("path.link")
.data(cluster.links(nodes))
.enter().append("path")
.attr("class", "link")
.attr("d", diagonal);
+ // Draw nodes.
var node = vis.selectAll("g.node")
.data(nodes)
.enter().append("g")
.attr("class", "node")
- .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
+ .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })
+ .on('mouseover', function(a_node) {
+ var connected_node_ids = _.pluck(self.model.get_connected_nodes(a_node), 'id');
+ // TODO: probably can use enter() to do this more easily.
+ node.filter(function(d) {
+ return _.find(connected_node_ids, function(id) { return id === d.id; }) !== undefined;
+ }).style('fill', '#f00');
+ })
+ .on('mouseout', function() {
+ node.style('fill', '#000');
+ });
node.append("circle")
- .attr("r", 4.5);
+ .attr("r", 9);
node.append("text")
- .attr("dx", function(d) { return d.children ? -8 : 8; })
+ .attr("dx", function(d) { return d.children ? -12 : 12; })
.attr("dy", 3)
.attr("text-anchor", function(d) { return d.children ? "end" : "start"; })
.text(function(d) { return d.name; });
}
});
+/**
+ * ParamaMonster visualization view. View requires rendering in 3-panel setup for now.
+ */
var ParamaMonsterVisualizationView = Backbone.View.extend({
className: 'paramamonster',
initialize: function(options) {
-
+ this.canvas_manager = new CanvasManager(this.$el.parents('body'));
+ this.tool_param_tree_view = new ToolParameterTreeView({ model: this.model.get('parameter_tree') });
+ this.track_collection_container = $('<table/>').addClass('tracks');
+
+ // Handle node clicks for tree data.
+ this.model.get('parameter_tree').on('change:tree_data', this.handle_node_clicks, this);
},
render: function() {
- // Set up tool parameter tree.
- var tool_param_tree_view = new ToolParameterTreeView({ model: this.model.get('parameter_tree') });
- tool_param_tree_view.render();
- this.$el.append(tool_param_tree_view.$el);
-
- // When node clicked in tree, run tool and show tiles.
- var node = d3.select(tool_param_tree_view.$el[0]).selectAll("g.node")
+ // Render tree design view in left panel.
+ var tree_design_view = new ToolParameterTreeDesignView({
+ model: this.model.get('parameter_tree')
+ });
+
+ $('#left').append(tree_design_view.$el);
+
+ // Render track collection container/view in right panel.
+ var self = this,
+ regions = self.model.get('regions'),
+ tr = $('<tr/>').appendTo(this.track_collection_container);
+
+ _.each(regions, function(region) {
+ tr.append( $('<th>').text(region.toString()) );
+ });
+ tr.children().first().attr('colspan', 2);
+
+ $('#right').append(this.track_collection_container);
+
+ // Render tool parameter tree in center panel.
+ this.tool_param_tree_view.render();
+ $('#center').append(this.tool_param_tree_view.$el);
+
+ this.handle_node_clicks();
+ },
+
+ run_tool_on_dataset: function(settings) {
+ var tool = this.model.get('tool'),
+ dataset = this.model.get('dataset');
+ tool.set_input_values(settings);
+ $.when(tool.rerun(dataset)).then(function(outputs) {
+ // TODO: show modal with information about how to get to datasets.
+ });
+ },
+
+ handle_node_clicks: function() {
+ // When node clicked in tree, run tool and add tracks to model.
+ var self = this,
+ param_tree = this.model.get('parameter_tree'),
+ regions = this.model.get('regions'),
+ node = d3.select(this.tool_param_tree_view.$el[0]).selectAll("g.node");
node.on("click", function(d, i) {
- console.log(d, i);
+ // TODO: Show popup menu.
- // Gather: (a) dataset of interest; (b) region(s) of interest and (c) sets of parameters based on node clicked.
-
- // Run job by submitting parameters + dataset as job inputs; get dataset ids as result.
-
- // Create tracks for all resulting dataset ids.
-
- // Display tiles for region(s) of interest.
+ // Get all settings corresponding to node.
+ var tool = self.model.get('tool'),
+ dataset = self.model.get('dataset'),
+ all_settings = param_tree.get_node_settings(d);
+
+ // Create and add tracks for each settings group.
+ var tracks = _.map(all_settings, function(settings) {
+ var pm_track = new ParamaMonsterTrack({
+ settings: settings,
+ regions: regions
+ });
+ self.model.add_track(pm_track);
+ var track_view = new ParamaMonsterTrackView({
+ model: pm_track,
+ canvas_manager: self.canvas_manager
+ });
+ track_view.on('run_on_dataset', self.run_tool_on_dataset, self);
+ self.track_collection_container.append(track_view.$el);
+ track_view.$el.hover(function() {
+ var settings_leaf = param_tree.get_leaf(settings);
+ var connected_node_ids = _.pluck(param_tree.get_connected_nodes(settings_leaf), 'id');
+
+ // TODO: can do faster with enter?
+ d3.select(self.tool_param_tree_view.$el[0]).selectAll("g.node")
+ .filter(function(d) {
+ return _.find(connected_node_ids, function(id) { return id === d.id; }) !== undefined;
+ }).style('fill', '#f00');
+ },
+ function() {
+ d3.select(self.tool_param_tree_view.$el[0]).selectAll("g.node").style('fill', '#000');
+ });
+ return pm_track;
+ });
+
+ // For each track, run tool using track's settings and update track.
+ _.each(tracks, function(pm_track, index) {
+ setTimeout(function() {
+ // Set inputs and run tool.
+ //console.log('running with settings', pm_track.get('settings'));
+ tool.set_input_values(pm_track.get('settings'));
+ $.when(tool.rerun(dataset, regions)).then(function(output) {
+ // Create and add track for output dataset.
+ var track_config = _.extend({
+ data_url: galaxy_paths.get('raw_data_url'),
+ converted_datasets_state_url: galaxy_paths.get('dataset_state_url')
+ }, output.first().get('track_config')),
+ track_obj = object_from_template(track_config, self, null);
+ pm_track.set('track', track_obj);
+ });
+ }, index * 10000);
+ });
});
-
- },
+ }
});
\ No newline at end of file
diff -r 21ec1290ad02beb9c33516dcc4d5d4a732559414 -r 27f54f28e9f1542e9681b8a4c238d856be7b9a34 templates/tracks/browser.mako
--- a/templates/tracks/browser.mako
+++ b/templates/tracks/browser.mako
@@ -179,7 +179,6 @@
} }
]);
- menu.render();
menu.$el.attr("style", "float: right");
$("#center .unified-panel-header-inner").append(menu.$el);
diff -r 21ec1290ad02beb9c33516dcc4d5d4a732559414 -r 27f54f28e9f1542e9681b8a4c238d856be7b9a34 templates/visualization/paramamonster.mako
--- a/templates/visualization/paramamonster.mako
+++ b/templates/visualization/paramamonster.mako
@@ -2,8 +2,8 @@
<%def name="init()"><%
- self.has_left_panel=False
- self.has_right_panel=False
+ self.has_left_panel=True
+ self.has_right_panel=True
self.active_view="visualization"
self.message_box_visible=False
%>
@@ -12,7 +12,7 @@
<%def name="stylesheets()">
${parent.stylesheets()}
<style>
- .unified-panel-body {
+ div#center {
overflow: auto;
}
.link {
@@ -27,6 +27,56 @@
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
+ cursor: pointer;
+ }
+ .node:hover {
+ fill: #f00;
+ }
+ .node:hover circle {
+ fill: #ccc;
+ stroke: #f00;
+ }
+ table.tracks {
+ border-collapse: separate;
+ border-spacing: 5px;
+ }
+ .tile {
+ border: solid 1px #DDD;
+ margin: 2px;
+ border-radius: 10px;
+ margin: 3px;
+ }
+ .label {
+ position: fixed;
+ font: 10px sans-serif;
+ font-weight: bold;
+ background-color: #DDD;
+ border-radius: 5px;
+ padding: 1px;
+ }
+ th,td {
+ text-align: center;
+ }
+ td.settings {
+ vertical-align: top;
+ }
+ .icon-button.track-settings {
+ float: none;
+ }
+ .track-info {
+ text-align: left;
+ font: 10px sans-serif;
+ position: fixed;
+ background-color: #CCC;
+ border: solid 1px #AAA;
+ border-radius: 2px;
+ padding: 2px;
+ }
+ .btn-primary, .btn-primary:hover {
+ color: #EEE;
+ background-color: #DDD;
+ background-image: none;
+ border-radius: 12px;
}
</style></%def>
@@ -34,28 +84,16 @@
<%def name="javascripts()">
${parent.javascripts()}
- ${h.templates( "tool_link", "panel_section", "tool_search" )}
- ${h.js( "libs/d3", "mvc/data", "mvc/tools", "viz/visualization", "viz/paramamonster" )}
+ ${h.templates( "tool_link", "panel_section", "tool_search", "tool_form" )}
+ ${h.js( "libs/d3", "mvc/data", "mvc/tools", "viz/visualization", "viz/paramamonster", "viz/trackster", "viz/trackster_ui", "jquery.ui.sortable.slider" )}
<script type="text/javascript">
- var tool;
+ var viz;
$(function() {
// -- Viz set up. --
- tool = new Tool(JSON.parse('${ h.to_json_string( tool ) }'));
- // HACK: need to replace \ with \\ due to simplejson bug.
- var dataset = new Dataset(JSON.parse('${ h.to_json_string( dataset.get_api_value() ).replace('\\', '\\\\' ) }')),
- paramamonster_viz = new ParamaMonsterVisualization({
- tool: tool,
- dataset: dataset
- });
- viz_view = new ParamaMonsterVisualizationView({ model: paramamonster_viz });
-
- viz_view.render();
- $('.unified-panel-body').append(viz_view.$el);
-
- // Tool testing.
- var regions = [
+ var tool = new Tool(JSON.parse('${ h.to_json_string( tool ) }')),
+ regions = [
new GenomeRegion({
chrom: 'chr19',
start: '10000',
@@ -63,25 +101,32 @@
}),
new GenomeRegion({
chrom: 'chr19',
- start: '30000',
- end: '36000'
+ start: '150000',
+ end: '175000'
})
- ];
+ ],
+ // HACK: need to replace \ with \\ due to simplejson bug.
+ dataset = new Dataset(JSON.parse('${ h.to_json_string( dataset.get_api_value() ).replace('\\', '\\\\' ) }'));
- $.when(tool.rerun(dataset, regions)).then(function(outputs) {
- console.log(outputs);
+
+ viz = new ParamaMonsterVisualization({
+ tool: tool,
+ dataset: dataset,
+ regions: regions
});
+ var viz_view = new ParamaMonsterVisualizationView({ model: viz });
+
+ viz_view.render();
+ $('.unified-panel-body').append(viz_view.$el);
});
</script></%def><%def name="center_panel()">
- <div class="unified-panel-header" unselectable="on">
- <div class="unified-panel-header-inner">
- <div style="float:left;" id="title"></div>
- </div>
- <div style="clear: both"></div>
- </div>
- <div class="unified-panel-body">
- </div></%def>
+
+<%def name="left_panel()">
+</%def>
+
+<%def name="right_panel()">
+</%def>
\ 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: inithello: Added remote authentication to the toolshed.
by Bitbucket 27 Jun '12
by Bitbucket 27 Jun '12
27 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/21ec1290ad02/
changeset: 21ec1290ad02
user: inithello
date: 2012-06-27 15:47:32
summary: Added remote authentication to the toolshed.
affected #: 3 files
diff -r 9576fb8cd71e8ad16e9a6426c0c42dc6aba63716 -r 21ec1290ad02beb9c33516dcc4d5d4a732559414 lib/galaxy/web/framework/__init__.py
--- a/lib/galaxy/web/framework/__init__.py
+++ b/lib/galaxy/web/framework/__init__.py
@@ -498,8 +498,10 @@
# remote user authenticates, we'll look for this information, and if missing, create it.
if not self.app.security_agent.get_private_user_role( user ):
self.app.security_agent.create_private_user_role( user )
- if not user.default_permissions:
- self.app.security_agent.user_set_default_permissions( user, history=True, dataset=True )
+ if 'webapp' not in self.environ or self.environ['webapp'] != 'community':
+ if not user.default_permissions:
+ self.app.security_agent.user_set_default_permissions( user )
+ self.app.security_agent.user_set_default_permissions( user, history=True, dataset=True )
elif user is None:
username = remote_user_email.split( '@', 1 )[0].lower()
random.seed()
@@ -520,7 +522,8 @@
self.sa_session.flush()
self.app.security_agent.create_private_user_role( user )
# We set default user permissions, before we log in and set the default history permissions
- self.app.security_agent.user_set_default_permissions( user )
+ if 'webapp' not in self.environ or self.environ['webapp'] != 'community':
+ self.app.security_agent.user_set_default_permissions( user )
#self.log_event( "Automatically created account '%s'", user.email )
return user
def __update_session_cookie( self, name='galaxysession' ):
diff -r 9576fb8cd71e8ad16e9a6426c0c42dc6aba63716 -r 21ec1290ad02beb9c33516dcc4d5d4a732559414 lib/galaxy/webapps/community/buildapp.py
--- a/lib/galaxy/webapps/community/buildapp.py
+++ b/lib/galaxy/webapps/community/buildapp.py
@@ -17,6 +17,7 @@
import galaxy.webapps.community.model.mapping
import galaxy.web.framework
from galaxy.webapps.community.framework.middleware import hg
+from galaxy import util
log = logging.getLogger( __name__ )
@@ -102,6 +103,15 @@
# other middleware):
app = httpexceptions.make_middleware( app, conf )
log.debug( "Enabling 'httpexceptions' middleware" )
+ # If we're using remote_user authentication, add middleware that
+ # protects Galaxy from improperly configured authentication in the
+ # upstream server
+ if asbool(conf.get( 'use_remote_user', False )):
+ from galaxy.webapps.community.framework.middleware.remoteuser import RemoteUser
+ app = RemoteUser( app, maildomain = conf.get( 'remote_user_maildomain', None ),
+ display_servers = util.listify( conf.get( 'display_servers', '' ) ),
+ admin_users = conf.get( 'admin_users', '' ).split( ',' ) )
+ log.debug( "Enabling 'remote user' middleware" )
# The recursive middleware allows for including requests in other
# requests or forwarding of requests, all on the server side.
if asbool(conf.get('use_recursive', True)):
diff -r 9576fb8cd71e8ad16e9a6426c0c42dc6aba63716 -r 21ec1290ad02beb9c33516dcc4d5d4a732559414 lib/galaxy/webapps/community/framework/middleware/remoteuser.py
--- /dev/null
+++ b/lib/galaxy/webapps/community/framework/middleware/remoteuser.py
@@ -0,0 +1,93 @@
+"""
+Middleware for handling $REMOTE_USER if use_remote_user is enabled.
+"""
+
+import socket
+
+errorpage = """
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en">
+ <head>
+ <title>Galaxy</title>
+ <style type="text/css">
+ body {
+ min-width: 500px;
+ text-align: center;
+ }
+ .errormessage {
+ font: 75%% verdana, "Bitstream Vera Sans", geneva, arial, helvetica, helve, sans-serif;
+ padding: 10px;
+ margin: 100px auto;
+ min-height: 32px;
+ max-width: 500px;
+ border: 1px solid #AA6666;
+ background-color: #FFCCCC;
+ text-align: left;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="errormessage">
+ <h4>%s</h4>
+ <p>%s</p>
+ </div>
+ </body>
+</html>
+"""
+
+class RemoteUser( object ):
+ def __init__( self, app, maildomain=None, display_servers=None, admin_users=None ):
+ self.app = app
+ self.maildomain = maildomain
+ self.display_servers = display_servers or []
+ self.admin_users = admin_users or []
+ def __call__( self, environ, start_response ):
+ environ[ 'webapp' ] = 'community'
+ # Allow display servers
+ if self.display_servers and environ.has_key( 'REMOTE_ADDR' ):
+ try:
+ host = socket.gethostbyaddr( environ[ 'REMOTE_ADDR' ] )[0]
+ except( socket.error, socket.herror, socket.gaierror, socket.timeout ):
+ # in the event of a lookup failure, deny access
+ host = None
+ if host in self.display_servers:
+ environ[ 'HTTP_REMOTE_USER' ] = 'remote_display_server@%s' % ( self.maildomain or 'example.org' )
+ return self.app( environ, start_response )
+ # Apache sets REMOTE_USER to the string '(null)' when using the
+ # Rewrite* method for passing REMOTE_USER and a user is
+ # un-authenticated. Any other possible values need to go here as well.
+ path_info = environ.get('PATH_INFO', '')
+ if environ.has_key( 'HTTP_REMOTE_USER' ) and environ[ 'HTTP_REMOTE_USER' ] != '(null)':
+ if not environ[ 'HTTP_REMOTE_USER' ].count( '@' ):
+ if self.maildomain is not None:
+ environ[ 'HTTP_REMOTE_USER' ] += '@' + self.maildomain
+ else:
+ title = "Access to Galaxy is denied"
+ message = """
+ Galaxy is configured to authenticate users via an external
+ method (such as HTTP authentication in Apache), but only a
+ username (not an email address) was provided by the
+ upstream (proxy) server. Since Galaxy usernames are email
+ addresses, a default mail domain must be set.</p>
+ <p>Please contact your local Galaxy administrator. The
+ variable <code>remote_user_maildomain</code> must be set
+ before you may access Galaxy.
+ """
+ return self.error( start_response, title, message )
+ return self.app( environ, start_response )
+ elif path_info.startswith( '/api/' ):
+ # The API handles its own authentication via keys
+ return self.app( environ, start_response )
+ else:
+ title = "Access to Galaxy is denied"
+ message = """
+ Galaxy is configured to authenticate users via an external
+ method (such as HTTP authentication in Apache), but a username
+ was not provided by the upstream (proxy) server. This is
+ generally due to a misconfiguration in the upstream server.</p>
+ <p>Please contact your local Galaxy administrator.
+ """
+ return self.error( start_response, title, message )
+ def error( self, start_response, title="Access denied", message="Please contact your local Galaxy administrator." ):
+ start_response( '403 Forbidden', [('Content-type', 'text/html')] )
+ return [errorpage % (title, message)]
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: scot...@gatech.edu: Generalized exit code and regex handling. TaskWrapper now uses the newly-generalized handling, too.
by Bitbucket 26 Jun '12
by Bitbucket 26 Jun '12
26 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/9576fb8cd71e/
changeset: 9576fb8cd71e
user: scot...(a)gatech.edu
date: 2012-06-26 23:31:30
summary: Generalized exit code and regex handling. TaskWrapper now uses the newly-generalized handling, too.
affected #: 2 files
diff -r fb67f73df9a24cb9eba278e7c62ba996fa11a6be -r 9576fb8cd71e8ad16e9a6426c0c42dc6aba63716 lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -306,78 +306,12 @@
#ERROR at this point means the job was deleted by an administrator.
return self.fail( job.info )
- err_msg = ""
- # Check exit codes and match regular expressions against stdout and
- # stderr if this tool was configured to do so.
- if ( len( self.tool.stdio_regexes ) > 0 or
- len( self.tool.stdio_exit_codes ) > 0 ):
- # We will check the exit code ranges in the order in which
- # they were specified. Each exit_code is a ToolStdioExitCode
- # that includes an applicable range. If the exit code was in
- # that range, then apply the error level and add in a message.
- # If we've reached a fatal error rule, then stop.
- max_error_level = galaxy.tools.StdioErrorLevel.NO_ERROR
- for stdio_exit_code in self.tool.stdio_exit_codes:
- if ( tool_exit_code >= stdio_exit_code.range_start and
- tool_exit_code <= stdio_exit_code.range_end ):
- if None != stdio_exit_code.desc:
- err_msg += stdio_exit_code.desc
- # TODO: Find somewhere to stick the err_msg - possibly to
- # the source (stderr/stdout), possibly in a new db column.
- max_error_level = max( max_error_level,
- stdio_exit_code.error_level )
- if max_error_level >= galaxy.tools.StdioErrorLevel.FATAL:
- break
- # If there is a regular expression for scanning stdout/stderr,
- # then we assume that the tool writer overwrote the default
- # behavior of just setting an error if there is *anything* on
- # stderr.
- if max_error_level < galaxy.tools.StdioErrorLevel.FATAL:
- # We'll examine every regex. Each regex specifies whether
- # it is to be run on stdout, stderr, or both. (It is
- # possible for neither stdout nor stderr to be scanned,
- # but those won't be scanned.) We record the highest
- # error level, which are currently "warning" and "fatal".
- # If fatal, then we set the job's state to ERROR.
- # If warning, then we still set the job's state to OK
- # but include a message. We'll do this if we haven't seen
- # a fatal error yet
- for regex in self.tool.stdio_regexes:
- # If ( this regex should be matched against stdout )
- # - Run the regex's match pattern against stdout
- # - If it matched, then determine the error level.
- # o If it was fatal, then we're done - break.
- # Repeat the stdout stuff for stderr.
- # TODO: Collapse this into a single function.
- if ( regex.stdout_match ):
- regex_match = re.search( regex.match, stdout )
- if ( regex_match ):
- err_msg += self.regex_err_msg( regex_match, regex )
- max_error_level = max( max_error_level, regex.error_level )
- if max_error_level >= galaxy.tools.StdioErrorLevel.FATAL:
- break
- if ( regex.stderr_match ):
- regex_match = re.search( regex.match, stderr )
- if ( regex_match ):
- err_msg += self.regex_err_msg( regex_match, regex )
- max_error_level = max( max_error_level,
- regex.error_level )
- if max_error_level >= galaxy.tools.StdioErrorLevel.FATAL:
- break
- # If we encountered a fatal error, then we'll need to set the
- # job state accordingly. Otherwise the job is ok:
- if max_error_level >= galaxy.tools.StdioErrorLevel.FATAL:
- job.state = job.states.ERROR
- else:
- job.state = job.states.OK
- # When there are no regular expressions and no exit codes to check,
- # default to the previous behavior: when there's anything on stderr
- # the job has an error, and the job is ok otherwise.
+ # Check the
+ if ( self.check_tool_output( stdout, stderr, tool_exit_code ) ):
+ job.state = job.states.OK
else:
- if stderr:
- job.state = job.states.ERROR
- else:
- job.state = job.states.OK
+ job.state = job.states.ERROR
+
if self.version_string_cmd:
version_filename = self.get_version_string_path()
if os.path.exists(version_filename):
@@ -566,6 +500,107 @@
if self.app.config.cleanup_job == 'always' or ( not stderr and self.app.config.cleanup_job == 'onsuccess' ):
self.cleanup()
+ def check_tool_output( self, stdout, stderr, tool_exit_code ):
+ """
+ Check the output of a tool - given the stdout, stderr, and the tool's
+ exit code, return True if the tool exited succesfully and False
+ otherwise. No exceptions should be thrown. If this code encounters
+ an exception, it returns True so that the workflow can continue;
+ otherwise, a bug in this code could halt workflow progress.
+ Note that, if the tool did not define any exit code handling or
+ any stdio/stderr handling, then it reverts back to previous behavior:
+ if stderr contains anything, then False is returned.
+ """
+ job = self.get_job()
+ err_msg = ""
+ # By default, the tool succeeded. This covers the case where the code
+ # has a bug but the tool was ok, and it lets a workflow continue.
+ success = True
+
+ try:
+ # Check exit codes and match regular expressions against stdout and
+ # stderr if this tool was configured to do so.
+ if ( len( self.tool.stdio_regexes ) > 0 or
+ len( self.tool.stdio_exit_codes ) > 0 ):
+ # We will check the exit code ranges in the order in which
+ # they were specified. Each exit_code is a ToolStdioExitCode
+ # that includes an applicable range. If the exit code was in
+ # that range, then apply the error level and add in a message.
+ # If we've reached a fatal error rule, then stop.
+ max_error_level = galaxy.tools.StdioErrorLevel.NO_ERROR
+ for stdio_exit_code in self.tool.stdio_exit_codes:
+ if ( tool_exit_code >= stdio_exit_code.range_start and
+ tool_exit_code <= stdio_exit_code.range_end ):
+ if None != stdio_exit_code.desc:
+ err_msg += stdio_exit_code.desc
+ # TODO: Find somewhere to stick the err_msg - possibly to
+ # the source (stderr/stdout), possibly in a new db column.
+ max_error_level = max( max_error_level,
+ stdio_exit_code.error_level )
+ if max_error_level >= galaxy.tools.StdioErrorLevel.FATAL:
+ break
+
+ # If there is a regular expression for scanning stdout/stderr,
+ # then we assume that the tool writer overwrote the default
+ # behavior of just setting an error if there is *anything* on
+ # stderr.
+ if max_error_level < galaxy.tools.StdioErrorLevel.FATAL:
+ # We'll examine every regex. Each regex specifies whether
+ # it is to be run on stdout, stderr, or both. (It is
+ # possible for neither stdout nor stderr to be scanned,
+ # but those won't be scanned.) We record the highest
+ # error level, which are currently "warning" and "fatal".
+ # If fatal, then we set the job's state to ERROR.
+ # If warning, then we still set the job's state to OK
+ # but include a message. We'll do this if we haven't seen
+ # a fatal error yet
+ for regex in self.tool.stdio_regexes:
+ # If ( this regex should be matched against stdout )
+ # - Run the regex's match pattern against stdout
+ # - If it matched, then determine the error level.
+ # o If it was fatal, then we're done - break.
+ # Repeat the stdout stuff for stderr.
+ # TODO: Collapse this into a single function.
+ if ( regex.stdout_match ):
+ regex_match = re.search( regex.match, stdout )
+ if ( regex_match ):
+ err_msg += self.regex_err_msg( regex_match, regex )
+ max_error_level = max( max_error_level, regex.error_level )
+ if max_error_level >= galaxy.tools.StdioErrorLevel.FATAL:
+ break
+ if ( regex.stderr_match ):
+ regex_match = re.search( regex.match, stderr )
+ if ( regex_match ):
+ err_msg += self.regex_err_msg( regex_match, regex )
+ max_error_level = max( max_error_level,
+ regex.error_level )
+ if max_error_level >= galaxy.tools.StdioErrorLevel.FATAL:
+ break
+
+ # If we encountered a fatal error, then we'll need to set the
+ # job state accordingly. Otherwise the job is ok:
+ if max_error_level >= galaxy.tools.StdioErrorLevel.FATAL:
+ success = False
+ else:
+ success = True
+
+ # When there are no regular expressions and no exit codes to check,
+ # default to the previous behavior: when there's anything on stderr
+ # the job has an error, and the job is ok otherwise.
+ else:
+ log.debug( "The tool did not define exit code or stdio handling; "
+ + "checking stderr for success" )
+ if stderr:
+ success = False
+ else:
+ success = True
+ # On any exception, return True.
+ except:
+ log.warning( "Tool check encountered unexpected exception; "
+ + "assuming tool was successful" )
+ success = True
+ return success
+
def regex_err_msg( self, match, regex ):
"""
Return a message about the match on tool output using the given
@@ -970,7 +1005,7 @@
self.sa_session.add( task )
self.sa_session.flush()
- def finish( self, stdout, stderr ):
+ def finish( self, stdout, stderr, tool_exit_code=0 ):
# DBTODO integrate previous finish logic.
# Simple finish for tasks. Just set the flag OK.
log.debug( 'task %s for job %d ended' % (self.task_id, self.job_id) )
@@ -991,10 +1026,10 @@
# Job was deleted by an administrator
self.fail( task.info )
return
- if stderr:
+ if ( self.check_tool_output( stdout, stderr, tool_exit_code ) ):
+ task.state = task.states.OK
+ else:
task.state = task.states.ERROR
- else:
- task.state = task.states.OK
# Save stdout and stderr
if len( stdout ) > 32768:
log.error( "stdout for task %d is greater than 32K, only first part will be logged to database" % task.id )
diff -r fb67f73df9a24cb9eba278e7c62ba996fa11a6be -r 9576fb8cd71e8ad16e9a6426c0c42dc6aba63716 lib/galaxy/jobs/runners/pbs.py
--- a/lib/galaxy/jobs/runners/pbs.py
+++ b/lib/galaxy/jobs/runners/pbs.py
@@ -560,7 +560,7 @@
def fail_job( self, pbs_job_state ):
"""
- Seperated out so we can use the worker threads for it.
+ Separated out so we can use the worker threads for it.
"""
if pbs_job_state.stop_job:
self.stop_job( self.sa_session.query( self.app.model.Job ).get( pbs_job_state.job_wrapper.job_id ) )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

26 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/fb67f73df9a2/
changeset: fb67f73df9a2
user: inithello
date: 2012-06-26 21:18:19
summary: Also added missing publicbuilds.txt
affected #: 2 files
diff -r e112508794a8585e96bc1ba15c2be1cce421393d -r fb67f73df9a24cb9eba278e7c62ba996fa11a6be .hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -51,6 +51,7 @@
tool-data/shared/rviewer/rviewer_build_sites.txt
tool-data/shared/ucsc/builds.txt
tool-data/shared/ensembl/builds.txt
+tool-data/shared/ucsc/publicbuilds.txt
tool-data/*.loc
tool-data/genome/*
diff -r e112508794a8585e96bc1ba15c2be1cce421393d -r fb67f73df9a24cb9eba278e7c62ba996fa11a6be tool-data/shared/ucsc/publicbuilds.txt
--- /dev/null
+++ b/tool-data/shared/ucsc/publicbuilds.txt
@@ -0,0 +1,96 @@
+#Harvested from http://genome.cse.ucsc.edu/cgi-bin/das/dsn
+? unspecified (?)
+hg19 Human Feb. 2009 (GRCh37/hg19) (hg19)
+hg18 Human Mar. 2006 (NCBI36/hg18) (hg18)
+hg17 Human May 2004 (NCBI35/hg17) (hg17)
+panTro3 Chimp Oct. 2010 (CGSC 2.1.3/panTro3) (panTro3)
+panTro2 Chimp Mar. 2006 (CGSC 2.1/panTro2) (panTro2)
+gorGor3 Gorilla May 2011 (gorGor3.1/gorGor3) (gorGor3)
+ponAbe2 Orangutan July 2007 (WUGSC 2.0.2/ponAbe2) (ponAbe2)
+nomLeu1 Gibbon Jan. 2010 (GGSC Nleu1.0/nomLeu1) (nomLeu1)
+rheMac2 Rhesus Jan. 2006 (MGSC Merged 1.0/rheMac2) (rheMac2)
+calJac3 Marmoset March 2009 (WUGSC 3.2/calJac3) (calJac3)
+calJac1 Marmoset June 2007 (WUGSC 2.0.2/calJac1) (calJac1)
+mm10 Mouse Dec. 2011 (GRCm38/mm10) (mm10)
+mm9 Mouse July 2007 (NCBI37/mm9) (mm9)
+mm8 Mouse Feb. 2006 (NCBI36/mm8) (mm8)
+rn5 Rat Mar. 2012 (RGSC 5.0/rn5) (rn5)
+rn4 Rat Nov. 2004 (Baylor 3.4/rn4) (rn4)
+hetGla1 Naked mole-rat Jul. 2011 (BGI HetGla_1.0/hetGla1) (hetGla1)
+cavPor3 Guinea pig Feb. 2008 (Broad/cavPor3) (cavPor3)
+oryCun2 Rabbit Apr. 2009 (Broad/oryCun2) (oryCun2)
+susScr2 Pig Nov. 2009 (SGSC Sscrofa9.2/susScr2) (susScr2)
+oviAri1 Sheep Feb. 2010 (ISGC Ovis_aries_1.0/oviAri1) (oviAri1)
+bosTau7 Cow Oct. 2011 (Baylor Btau_4.6.1/bosTau7) (bosTau7)
+bosTau6 Cow Nov. 2009 (Bos_taurus_UMD_3.1/bosTau6) (bosTau6)
+bosTau4 Cow Oct. 2007 (Baylor 4.0/bosTau4) (bosTau4)
+equCab2 Horse Sep. 2007 (Broad/equCab2) (equCab2)
+equCab1 Horse Jan. 2007 (Broad/equCab1) (equCab1)
+felCat4 Cat Dec. 2008 (NHGRI/GTB V17e/felCat4) (felCat4)
+felCat3 Cat Mar. 2006 (Broad/felCat3) (felCat3)
+canFam3 Dog Sep. 2011 (Broad CanFam3.1/canFam3) (canFam3)
+canFam2 Dog May 2005 (Broad/canFam2) (canFam2)
+ailMel1 Panda Dec. 2009 (BGI-Shenzhen 1.0/ailMel1) (ailMel1)
+myoLuc2 Microbat Jul. 2010 (Broad Institute Myoluc2.0/myoLuc2) (myoLuc2)
+loxAfr3 Elephant Jul. 2009 (Broad/loxAfr3) (loxAfr3)
+monDom5 Opossum Oct. 2006 (Broad/monDom5) (monDom5)
+monDom4 Opossum Jan. 2006 (Broad/monDom4) (monDom4)
+macEug2 Wallaby Sep. 2009 (TWGS Meug_1.1/macEug2) (macEug2)
+ornAna1 Platypus Mar. 2007 (WUGSC 5.0.1/ornAna1) (ornAna1)
+galGal4 Chicken Nov. 2011 (ICGSC Gallus_gallus-4.0/galGal4) (galGal4)
+galGal3 Chicken May 2006 (WUGSC 2.1/galGal3) (galGal3)
+melGal1 Turkey Dec. 2009 (TGC Turkey_2.01/melGal1) (melGal1)
+taeGut1 Zebra finch Jul. 2008 (WUGSC 3.2.4/taeGut1) (taeGut1)
+anoCar2 Lizard May 2010 (Broad AnoCar2.0/anoCar2) (anoCar2)
+anoCar1 Lizard Feb. 2007 (Broad/anoCar1) (anoCar1)
+chrPic1 Painted turtle Dec. 2011 (v3.0.1/chrPic1) (chrPic1)
+xenTro3 X. tropicalis Nov. 2009 (JGI 4.2/xenTro3) (xenTro3)
+xenTro2 X. tropicalis Aug. 2005 (JGI 4.1/xenTro2) (xenTro2)
+danRer7 Zebrafish Jul. 2010 (Zv9/danRer7) (danRer7)
+danRer6 Zebrafish Dec. 2008 (Zv8/danRer6) (danRer6)
+tetNig2 Tetraodon Mar. 2007 (Genoscope 8.0/tetNig2) (tetNig2)
+tetNig1 Tetraodon Feb. 2004 (Genoscope 7/tetNig1) (tetNig1)
+fr3 Fugu Oct. 2011 (FUGU5/fr3) (fr3)
+fr2 Fugu Oct. 2004 (JGI 4.0/fr2) (fr2)
+gasAcu1 Stickleback Feb. 2006 (Broad/gasAcu1) (gasAcu1)
+oryLat2 Medaka Oct. 2005 (NIG/UT MEDAKA1/oryLat2) (oryLat2)
+petMar1 Lamprey Mar. 2007 (WUGSC 3.0/petMar1) (petMar1)
+aplCal1 Sea hare Sept. 2008 (Broad 2.0/aplCal1) (aplCal1)
+braFlo1 Lancelet Mar. 2006 (JGI 1.0/braFlo1) (braFlo1)
+ci2 C. intestinalis Mar. 2005 (JGI 2.1/ci2) (ci2)
+ci1 C. intestinalis Dec. 2002 (JGI 1.0/ci1) (ci1)
+strPur2 S. purpuratus Sep. 2006 (Baylor 2.1/strPur2) (strPur2)
+strPur1 S. purpuratus Apr. 2005 (Baylor 1.1/strPur1) (strPur1)
+ce10 C. elegans Oct. 2010 (WS220/ce10) (ce10)
+ce6 C. elegans May 2008 (WS190/ce6) (ce6)
+ce4 C. elegans Jan. 2007 (WS170/ce4) (ce4)
+caePb2 C. brenneri Feb. 2008 (WUGSC 6.0.1/caePb2) (caePb2)
+caePb1 C. brenneri Jan. 2007 (WUGSC 4.0/caePb1) (caePb1)
+cb3 C. briggsae Jan. 2007 (WUGSC 1.0/cb3) (cb3)
+cb1 C. briggsae July 2002 (WormBase cb25.agp8/cb1) (cb1)
+caeRem3 C. remanei May 2007 (WUGSC 15.0.1/caeRem3) (caeRem3)
+caeRem2 C. remanei Mar. 2006 (WUGSC 1.0/caeRem2) (caeRem2)
+caeJap1 C. japonica Mar. 2008 (WUGSC 3.0.2/caeJap1) (caeJap1)
+priPac1 P. pacificus Feb. 2007 (WUGSC 5.0/priPac1) (priPac1)
+dm3 D. melanogaster Apr. 2006 (BDGP R5/dm3) (dm3)
+dm2 D. melanogaster Apr. 2004 (BDGP R4/dm2) (dm2)
+droSim1 D. simulans Apr. 2005 (WUGSC mosaic 1.0/droSim1) (droSim1)
+droSec1 D. sechellia Oct. 2005 (Broad/droSec1) (droSec1)
+droYak2 D. yakuba Nov. 2005 (WUGSC 7.1/droYak2) (droYak2)
+droYak1 D. yakuba Apr. 2004 (WUGSC 1.0/droYak1) (droYak1)
+droEre1 D. erecta Aug. 2005 (Agencourt prelim/droEre1) (droEre1)
+droAna2 D. ananassae Aug. 2005 (Agencourt prelim/droAna2) (droAna2)
+droAna1 D. ananassae July 2004 (TIGR/droAna1) (droAna1)
+dp3 D. pseudoobscura Nov. 2004 (FlyBase 1.03/dp3) (dp3)
+dp2 D. pseudoobscura Aug. 2003 (Baylor freeze1/dp2) (dp2)
+droPer1 D. persimilis Oct. 2005 (Broad/droPer1) (droPer1)
+droVir2 D. virilis Aug. 2005 (Agencourt prelim/droVir2) (droVir2)
+droVir1 D. virilis July 2004 (Agencourt prelim/droVir1) (droVir1)
+droMoj2 D. mojavensis Aug. 2005 (Agencourt prelim/droMoj2) (droMoj2)
+droMoj1 D. mojavensis Aug. 2004 (Agencourt prelim/droMoj1) (droMoj1)
+droGri1 D. grimshawi Aug. 2005 (Agencourt prelim/droGri1) (droGri1)
+anoGam1 A. gambiae Feb. 2003 (IAGEC MOZ2/anoGam1) (anoGam1)
+apiMel2 A. mellifera Jan. 2005 (Baylor 2.0/apiMel2) (apiMel2)
+apiMel1 A. mellifera July 2004 (Baylor 1.2/apiMel1) (apiMel1)
+sacCer3 S. cerevisiae Apr. 2011 (SacCer_Apr2011/sacCer3) (sacCer3)
+sacCer2 S. cerevisiae June 2008 (SGD/sacCer2) (sacCer2)
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: inithello: Added missing builds.txt for Ensembl, fixed erroneous first line in output.
by Bitbucket 26 Jun '12
by Bitbucket 26 Jun '12
26 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/e112508794a8/
changeset: e112508794a8
user: inithello
date: 2012-06-26 21:10:25
summary: Added missing builds.txt for Ensembl, fixed erroneous first line in output.
affected #: 2 files
diff -r 40ff9b0e1549c1b083a3822b25b8337808ad8995 -r e112508794a8585e96bc1ba15c2be1cce421393d cron/get_ensembl.py
--- a/cron/get_ensembl.py
+++ b/cron/get_ensembl.py
@@ -17,6 +17,7 @@
for genome in genomes:
builds[genome[0]] = dict( release=genome[3], species='%s (%s/%s)' % ( genome[1], genome[2], genome[0] ) )
for build in builds.items():
- lines.append( '\t'.join( [ build[0], '%d' % build[1]['release'], build[1]['species'] ] ) )
+ if build[0]:
+ lines.append( '\t'.join( [ build[0], '%d' % build[1]['release'], build[1]['species'] ] ) )
-print '\n'.join( lines )
\ No newline at end of file
+print '\n'.join( lines )
diff -r 40ff9b0e1549c1b083a3822b25b8337808ad8995 -r e112508794a8585e96bc1ba15c2be1cce421393d tool-data/shared/ensembl/builds.txt
--- /dev/null
+++ b/tool-data/shared/ensembl/builds.txt
@@ -0,0 +1,165 @@
+ 67 Microcebus_murinus (Mouse lemur/)
+MEDAKA1 67 Oryzias_latipes (Medaka/MEDAKA1)
+Myoluc2.0 67 Myotis_lucifugus (Microbat/Myoluc2.0)
+anoCar1 67 Anolis_carolinensis (Anole lizard/anoCar1)
+WS220 67 Caenorhabditis_elegans (C.elegans/WS220)
+WS180 67 Caenorhabditis_elegans (C.elegans/WS180)
+MICROBAT1 67 Myotis_lucifugus (Microbat/MICROBAT1)
+loxAfr3 67 Loxodonta_africana (Elephant/loxAfr3)
+AgamP3 67 Anopheles_gambiae (Mosquito/AgamP3)
+DROM3 67 Drosophila_melanogaster (Fly/DROM3)
+LatCha1 67 Latimeria_chalumnae (Coelacanth/LatCha1)
+vicPac1 67 Vicugna_pacos (Alpaca/vicPac1)
+COMMON_SHREW1 67 Sorex_araneus (Shrew/COMMON_SHREW1)
+MGSC3 67 Mus_musculus (Mouse/MGSC3)
+MGSC1 67 Mus_musculus (Mouse/MGSC1)
+JGI4.1 67 Xenopus_tropicalis (Xenopus/JGI4.1)
+RGSC1 67 Rattus_norvegicus (Rat/RGSC1)
+RGSC2 67 Rattus_norvegicus (Rat/RGSC2)
+gadMor1 67 Gadus_morhua (Atlantic cod/gadMor1)
+CSAV2.0 67 Ciona_savignyi (C.savignyi/CSAV2.0)
+oryCun2 67 Oryctolagus_cuniculus (Rabbit/oryCun2)
+ZFISH6 67 Danio_rerio (Zebrafish/ZFISH6)
+ZFISH7 67 Danio_rerio (Zebrafish/ZFISH7)
+ZFISH4 67 Danio_rerio (Zebrafish/ZFISH4)
+ZFISH5 67 Danio_rerio (Zebrafish/ZFISH5)
+ZFISH2 67 Danio_rerio (Zebrafish/ZFISH2)
+ZFISH3 67 Danio_rerio (Zebrafish/ZFISH3)
+MOZ2a 67 Anopheles_gambiae (Mosquito/MOZ2a)
+EquCab2 67 Equus_caballus (Horse/EquCab2)
+AMEL1.1 67 Apis_mellifera (Honeybee/AMEL1.1)
+MMUL_1 67 Macaca_mulatta (Macaque/MMUL_1)
+dasNov2 67 Dasypus_novemcinctus (Armadillo/dasNov2)
+choHof1 67 Choloepus_hoffmanni (Sloth/choHof1)
+lamPac1 50 Lama_pacos (Alpaca/lamPac1)
+OANA5 67 Ornithorhynchus_anatinus (Platypus/OANA5)
+CEL160 67 Caenorhabditis_elegans (C.elegans/CEL160)
+WBcel215 67 Caenorhabditis_elegans (C.elegans/WBcel215)
+gorGor3 67 Gorilla_gorilla (Gorilla/gorGor3)
+SQUIRREL 67 Spermophilus_tridecemlineatus (Ground Squirrel/SQUIRREL)
+gorGor1 67 Gorilla_gorilla (Gorilla/gorGor1)
+pteVam1 67 Pteropus_vampyrus (Flying fox/pteVam1)
+SGD1 67 Saccharomyces_cerevisiae (S.cerevisiae/SGD1)
+micMur1 67 Microcebus_murinus (Mouse lemur/micMur1)
+proCap1 67 Procavia_capensis (Rock hyrax/proCap1)
+NCBIM30 67 Mus_musculus (Mouse/NCBIM30)
+NCBIM33 67 Mus_musculus (Mouse/NCBIM33)
+NCBIM32 67 Mus_musculus (Mouse/NCBIM32)
+NCBIM35 67 Mus_musculus (Mouse/NCBIM35)
+AaegL1 67 Aedes_aegypti (A.aegypti/AaegL1)
+NCBIM37 67 Mus_musculus (Mouse/NCBIM37)
+NCBIM36 67 Mus_musculus (Mouse/NCBIM36)
+EF2 67 Saccharomyces_cerevisiae (S.cerevisiae/EF2)
+EF3 67 Saccharomyces_cerevisiae (S.cerevisiae/EF3)
+EF4 67 Saccharomyces_cerevisiae (S.cerevisiae/EF4)
+BDGP5.4 67 Drosophila_melanogaster (Fly/BDGP5.4)
+PPYG2 67 Pongo_abelii (Orangutan/PPYG2)
+CEL150 67 Caenorhabditis_elegans (C.elegans/CEL150)
+AMEL2.0 67 Apis_mellifera (Honeybee/AMEL2.0)
+WASHUC1 67 Gallus_gallus (Chicken/WASHUC1)
+WASHUC2 67 Gallus_gallus (Chicken/WASHUC2)
+Btau_3.1 67 Bos_taurus (Cow/Btau_3.1)
+gorGor3.1 67 Gorilla_gorilla (Gorilla/gorGor3.1)
+CEL130 67 Caenorhabditis_elegans (C.elegans/CEL130)
+Zv9 67 Danio_rerio (Zebrafish/Zv9)
+BROADS1 67 Gasterosteus_aculeatus (Stickleback/BROADS1)
+BROADD2 67 Canis_familiaris (Dog/BROADD2)
+BROADD1 67 Canis_familiaris (Dog/BROADD1)
+pika 67 Ochotona_princeps (Pika/pika)
+ZFISH08 67 Danio_rerio (Zebrafish/ZFISH08)
+ZFISH06 67 Danio_rerio (Zebrafish/ZFISH06)
+calJac3 67 Callithrix_jacchus (Marmoset/calJac3)
+CHIMP2.1.4 67 Pan_troglodytes (Chimp/CHIMP2.1.4)
+JGI2 67 Ciona_intestinalis (C.intestinalis/JGI2)
+JGI3 67 Xenopus_tropicalis (Xenopus/JGI3)
+UCSC 67 Homo_sapiens (Human/UCSC)
+Zv8 67 Danio_rerio (Zebrafish/Zv8)
+JGI4 67 Xenopus_tropicalis (Xenopus/JGI4)
+CEL140 67 Caenorhabditis_elegans (C.elegans/CEL140)
+HEDGEHOG 67 Erinaceus_europaeus (Hedgehog/HEDGEHOG)
+callJacc3 67 Callithrix_jacchus (Marmoset/callJacc3)
+WS210 67 Caenorhabditis_elegans (C.elegans/WS210)
+BDGP4 67 Drosophila_melanogaster (Fly/BDGP4)
+BDGP5 67 Drosophila_melanogaster (Fly/BDGP5)
+CHIMP1 67 Pan_troglodytes (Chimp/CHIMP1)
+OtoGar3 67 Otolemur_garnettii (Bushbaby/OtoGar3)
+MOZ2 67 Anopheles_gambiae (Mosquito/MOZ2)
+FUGU4 67 Takifugu_rubripes (Fugu/FUGU4)
+MOZ1 67 Anopheles_gambiae (Mosquito/MOZ1)
+GUINEAPIG 67 Cavia_porcellus (Guinea Pig/GUINEAPIG)
+BROADE1 67 Loxodonta_africana (Elephant/BROADE1)
+RABBIT 67 Oryctolagus_cuniculus (Rabbit/RABBIT)
+TETRAODON7 67 Tetraodon_nigroviridis (Tetraodon/TETRAODON7)
+TETRAODON8 67 Tetraodon_nigroviridis (Tetraodon/TETRAODON8)
+gorGor2 67 Gorilla_gorilla (Gorilla/gorGor2)
+SGD1.01 67 Saccharomyces_cerevisiae (S.cerevisiae/SGD1.01)
+ailMel1 67 Ailuropoda_melanoleuca (Panda/ailMel1)
+Sscrofa9 67 Sus_scrofa (Pig/Sscrofa9)
+cavPor3 67 Cavia_porcellus (Guinea Pig/cavPor3)
+Orenil1.0 67 Oreochromis_niloticus (Nile tilapia/Orenil1.0)
+BDGP4.2 67 Drosophila_melanogaster (Fly/BDGP4.2)
+BDGP4.3 67 Drosophila_melanogaster (Fly/BDGP4.3)
+Petromyzon_marin 64 Petromyzon_marinus (Lamprey/Petromyzon_marin)
+RGSC3.4 67 Rattus_norvegicus (Rat/RGSC3.4)
+Pmarinus_7.0 67 Petromyzon_marinus (Lamprey/Pmarinus_7.0)
+RGSC3.1 67 Rattus_norvegicus (Rat/RGSC3.1)
+BDGP5.25 67 Drosophila_melanogaster (Fly/BDGP5.25)
+ARMA 67 Dasypus_novemcinctus (Armadillo/ARMA)
+CINT1.95 67 Ciona_intestinalis (C.intestinalis/CINT1.95)
+Btau_1.0 67 Bos_taurus (Cow/Btau_1.0)
+JGI_4.2 67 Xenopus_tropicalis (Xenopus/JGI_4.2)
+CEL116 67 Caenorhabditis_elegans (C.elegans/CEL116)
+BUSHBABY1 67 Otolemur_garnettii (Bushbaby/BUSHBABY1)
+Sscrofa10.2 67 Sus_scrofa (Pig/Sscrofa10.2)
+BDGP3.2.1 67 Drosophila_melanogaster (Fly/BDGP3.2.1)
+taeGut3.2.4 67 Taeniopygia_guttata (Zebra finch/taeGut3.2.4)
+KH 67 Ciona_intestinalis (C.intestinalis/KH)
+JGI4_1 67 Xenopus_tropicalis (Xenopus/JGI4_1)
+spetri2 67 Spermophilus_tridecemlineatus (Ground Squirrel/spetri2)
+Btau_4.0 67 Bos_taurus (Cow/Btau_4.0)
+UMD2 67 Meleagris_gallopavo (Turkey/UMD2)
+NCBI28 67 Homo_sapiens (Human/NCBI28)
+NCBI29 67 Homo_sapiens (Human/NCBI29)
+Btau_2.0 67 Bos_taurus (Cow/Btau_2.0)
+NCBI26 67 Homo_sapiens (Human/NCBI26)
+CAT 67 Felis_catus (Cat/CAT)
+TENREC 67 Echinops_telfairi (Tenrec/TENREC)
+WS200 67 Caenorhabditis_elegans (C.elegans/WS200)
+AnoCar1.0 67 Anolis_carolinensis (Anole lizard/AnoCar1.0)
+Nleu1.0 67 Nomascus_leucogenys (Gibbon/Nleu1.0)
+Meug_1.0 67 Macropus_eugenii (Wallaby/Meug_1.0)
+C_jacchus3.2.1 67 Callithrix_jacchus (Marmoset/C_jacchus3.2.1)
+CHIMP2.1 67 Pan_troglodytes (Chimp/CHIMP2.1)
+WS190 67 Caenorhabditis_elegans (C.elegans/WS190)
+dipOrd1 67 Dipodomys_ordii (Kangaroo rat/dipOrd1)
+AnoCar2.0 67 Anolis_carolinensis (Anole lizard/AnoCar2.0)
+ACME0.1 67 None (None/ACME0.1)
+CEL95 67 Caenorhabditis_elegans (C.elegans/CEL95)
+CEL93 67 Caenorhabditis_elegans (C.elegans/CEL93)
+DEVIL7.0 67 Sarcophilus_harrisii (Tasmanian Devil/DEVIL7.0)
+CEL98 67 Caenorhabditis_elegans (C.elegans/CEL98)
+CEL102 67 Caenorhabditis_elegans (C.elegans/CEL102)
+TREESHREW 67 Tupaia_belangeri (Tree Shrew/TREESHREW)
+NCBI31 67 Homo_sapiens (Human/NCBI31)
+NCBI30 67 Homo_sapiens (Human/NCBI30)
+NCBI33 67 Homo_sapiens (Human/NCBI33)
+NCBI35 67 Homo_sapiens (Human/NCBI35)
+NCBI34 67 Homo_sapiens (Human/NCBI34)
+turTru1 67 Tursiops_truncatus (Bottlenose dolphin/turTru1)
+NCBI36 67 Homo_sapiens (Human/NCBI36)
+UMD3.1 67 Bos_taurus (Cow/UMD3.1)
+speTri1 67 Spermophilus_tridecemlineatus (Ground Squirrel/speTri1)
+GRCh37 67 Homo_sapiens (Human/GRCh37)
+CHIMP1A 67 Pan_troglodytes (Chimp/CHIMP1A)
+WB170 67 Caenorhabditis_elegans (C.elegans/WB170)
+FUGU1 67 Takifugu_rubripes (Fugu/FUGU1)
+FUGU2 67 Takifugu_rubripes (Fugu/FUGU2)
+NCBIM34 67 Mus_musculus (Mouse/NCBIM34)
+DROM3A 67 Drosophila_melanogaster (Fly/DROM3A)
+tarSyr1 67 Tarsius_syrichta (Tarsier/tarSyr1)
+CBR25 67 Caenorhabditis_briggsae (C.briggsae/CBR25)
+BROADO5 67 Monodelphis_domestica (Opossum/BROADO5)
+BROADO2 67 Monodelphis_domestica (Opossum/BROADO2)
+BROADO3 67 Monodelphis_domestica (Opossum/BROADO3)
+BDGP5.13 67 Drosophila_melanogaster (Fly/BDGP5.13)
+MMUL_0_1 67 Macaca_mulatta (Macaque/MMUL_0_1)
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

26 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/40ff9b0e1549/
changeset: 40ff9b0e1549
user: dannon
date: 2012-06-26 17:07:09
summary: Add share_string option to cloud_launch.
affected #: 2 files
diff -r 2e0254547b09bfccbd0834524a0fb4919b6a6efd -r 40ff9b0e1549c1b083a3822b25b8337808ad8995 lib/galaxy/web/controllers/cloudlaunch.py
--- a/lib/galaxy/web/controllers/cloudlaunch.py
+++ b/lib/galaxy/web/controllers/cloudlaunch.py
@@ -25,11 +25,11 @@
BaseUIController.__init__(self, app)
@web.expose
- def index(self, trans):
- return trans.fill_template("cloud/index.mako")
+ def index(self, trans, share_string=None):
+ return trans.fill_template("cloud/index.mako", share_string=share_string)
@web.expose
- def launch_instance(self, trans, cluster_name, password, key_id, secret, instance_type):
+ def launch_instance(self, trans, cluster_name, password, key_id, secret, instance_type, share_string):
ec2_error = None
try:
# Create security group & key pair used when starting an instance
@@ -47,6 +47,8 @@
'instance_type':instance_type}
if password:
user_provided_data['password'] = password
+ if share_string:
+ user_provided_data['share_string'] = share_string
rs = run_instance(ec2_conn=ec2_conn,
user_provided_data=user_provided_data,
key_name=kp_name,
diff -r 2e0254547b09bfccbd0834524a0fb4919b6a6efd -r 40ff9b0e1549c1b083a3822b25b8337808ad8995 templates/cloud/index.mako
--- a/templates/cloud/index.mako
+++ b/templates/cloud/index.mako
@@ -59,7 +59,7 @@
<form action="${h.url_for( controller='cloudlaunch', action='launch_instance' )}" method="post"><div class="form-row"><label for="id_cluster_name">Cluster Name</label>
- <input type="text" size="80" name="cluster_name" id="id_cluster_name"/><br/>
+ <input type="text" size="40" name="cluster_name" id="id_cluster_name"/><br/></div><div class="form-row"><label for="id_password">Password</label>
@@ -73,6 +73,14 @@
<label for="id_secret">Secret Key</label><input type="password" size="120" name="secret" id="id_secret"/><br/></div>
+ %if share_string:
+ <input type='hidden' name='share_string' value='${share_string}'/>
+ %else:
+ <div class="form-row">
+ <label for="id_share_string">Instance Share String (optional)</label>
+ <input type="text" size="120" name="share_string" id="id_share_string"/><br/>
+ </div>
+ %endif
<div class="form-row"><label for="id_instance_type">Instance Type</label><select name="instance_type" id="id_instance_type">
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/2e0254547b09/
changeset: 2e0254547b09
user: smcmanus
date: 2012-06-25 23:16:49
summary: Recommit of PBS and DRMAA fixes
affected #: 3 files
diff -r 319b2b0e832c8ea5ef520c76722f7ad6270507c3 -r 2e0254547b09bfccbd0834524a0fb4919b6a6efd lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -291,8 +291,6 @@
the output datasets based on stderr and stdout from the command, and
the contents of the output files.
"""
- # TODO: Eliminate debugging code after testing all runners
- log.debug( "JobWrapper.finish: exit code:" + str(tool_exit_code) )
# default post job setup
self.sa_session.expunge_all()
job = self.get_job()
diff -r 319b2b0e832c8ea5ef520c76722f7ad6270507c3 -r 2e0254547b09bfccbd0834524a0fb4919b6a6efd lib/galaxy/jobs/runners/drmaa.py
--- a/lib/galaxy/jobs/runners/drmaa.py
+++ b/lib/galaxy/jobs/runners/drmaa.py
@@ -39,6 +39,11 @@
drmaa.JobState.FAILED: 'job finished, but failed',
}
+# The last four lines (following the last fi) will:
+# - setup the env
+# - move to the job wrapper's working directory
+# - execute the command
+# - take the command's exit code ($?) and write it to a file.
drm_template = """#!/bin/sh
GALAXY_LIB="%s"
if [ "$GALAXY_LIB" != "None" ]; then
@@ -52,6 +57,7 @@
%s
cd %s
%s
+echo $? > %s
"""
def __lineno__():
"""Returns the current line number in our program."""
@@ -77,7 +83,7 @@
self.job_file = None
self.ofile = None
self.efile = None
- self.rcfile = None
+ self.ecfile = None
self.runner_url = None
class DRMAAJobRunner( BaseJobRunner ):
@@ -169,7 +175,7 @@
# define job attributes
ofile = "%s.drmout" % os.path.join(job_wrapper.working_directory, job_wrapper.get_id_tag())
efile = "%s.drmerr" % os.path.join(job_wrapper.working_directory, job_wrapper.get_id_tag())
- rcfile = "%s.drmrc" % os.path.join(job_wrapper.working_directory, job_wrapper.get_id_tag())
+ ecfile = "%s.drmec" % os.path.join(job_wrapper.working_directory, job_wrapper.get_id_tag())
job_name = "g%s_%s_%s" % ( job_wrapper.job_id, job_wrapper.tool.id, job_wrapper.user )
job_name = ''.join( map( lambda x: x if x in ( string.letters + string.digits + '_' ) else '_', job_name ) )
@@ -178,7 +184,7 @@
jt.jobName = job_name
jt.outputPath = ":%s" % ofile
jt.errorPath = ":%s" % efile
- jt.returnCodePath = ":%s" % rcfile
+ # Avoid a jt.exitCodePath for now - it's only used when finishing.
native_spec = self.get_native_spec( runner_url )
if native_spec is not None:
jt.nativeSpecification = native_spec
@@ -187,7 +193,8 @@
script = drm_template % ( job_wrapper.galaxy_lib_dir,
job_wrapper.get_env_setup_clause(),
os.path.abspath( job_wrapper.working_directory ),
- command_line )
+ command_line,
+ ecfile )
try:
fh = file( jt.remoteCommand, "w" )
@@ -231,7 +238,7 @@
drm_job_state.job_id = job_id
drm_job_state.ofile = ofile
drm_job_state.efile = efile
- drm_job_state.rcfile = rcfile
+ drm_job_state.ecfile = ecfile
drm_job_state.job_file = jt.remoteCommand
drm_job_state.old_state = 'new'
drm_job_state.running = False
@@ -316,17 +323,22 @@
"""
ofile = drm_job_state.ofile
efile = drm_job_state.efile
- rcfile = drm_job_state.rcfile
+ ecfile = drm_job_state.ecfile
job_file = drm_job_state.job_file
# collect the output
# wait for the files to appear
which_try = 0
+ # By default, the exit code is 0, which typically indicates success.
+ exit_code = 0
while which_try < (self.app.config.retry_job_output_collection + 1):
try:
ofh = file(ofile, "r")
efh = file(efile, "r")
+ ecfh = file(ecfile, "r")
stdout = ofh.read( 32768 )
stderr = efh.read( 32768 )
+ # The exit code should only be 8 bits, but read more anyway
+ exit_code_str = ecfh.read(32)
which_try = (self.app.config.retry_job_output_collection + 1)
except:
if which_try == self.app.config.retry_job_output_collection:
@@ -337,8 +349,15 @@
time.sleep(1)
which_try += 1
+ # Decode the exit code. If it's bogus, then just use 0.
try:
- drm_job_state.job_wrapper.finish( stdout, stderr )
+ exit_code = int(exit_code_str)
+ except:
+ log.warning( "Exit code " + exit_code_str + " invalid. Using 0." )
+ exit_code = 0
+
+ try:
+ drm_job_state.job_wrapper.finish( stdout, stderr, exit_code )
except:
log.exception("Job wrapper finish method failed")
@@ -382,7 +401,7 @@
drm_job_state = DRMAAJobState()
drm_job_state.ofile = "%s.drmout" % os.path.join(os.getcwd(), job_wrapper.working_directory, job_wrapper.get_id_tag())
drm_job_state.efile = "%s.drmerr" % os.path.join(os.getcwd(), job_wrapper.working_directory, job_wrapper.get_id_tag())
- drm_job_state.rcfile = "%s.drmrc" % os.path.join(os.getcwd(), job_wrapper.working_directory, job_wrapper.get_id_tag())
+ drm_job_state.ecfile = "%s.drmec" % os.path.join(os.getcwd(), job_wrapper.working_directory, job_wrapper.get_id_tag())
drm_job_state.job_file = "%s/galaxy_%s.sh" % (self.app.config.cluster_files_directory, job.id)
drm_job_state.job_id = str( job.job_runner_external_id )
drm_job_state.runner_url = job_wrapper.get_job_runner()
diff -r 319b2b0e832c8ea5ef520c76722f7ad6270507c3 -r 2e0254547b09bfccbd0834524a0fb4919b6a6efd lib/galaxy/jobs/runners/pbs.py
--- a/lib/galaxy/jobs/runners/pbs.py
+++ b/lib/galaxy/jobs/runners/pbs.py
@@ -532,16 +532,22 @@
stdout = ofh.read( 32768 )
stderr = efh.read( 32768 )
# This should be an 8-bit exit code, but read ahead anyway:
- exit_code = ecfh.read(32)
+ exit_code_str = ecfh.read(32)
except:
stdout = ''
stderr = 'Job output not returned by PBS: the output datasets were deleted while the job was running, the job was manually dequeued or there was a cluster error.'
# By default, the exit code is 0, which usually indicates success
# (although clearly some error happened).
+ exit_code_str = ""
+
+ # Translate the exit code string to an integer; use 0 on failure.
+ try:
+ exit_code = int( exit_code_str )
+ except:
+ log.warning( "Exit code " + exit_code_str + " was invalid. Using 0." )
exit_code = 0
- log.debug(stderr)
- log.debug( "Job exit code: " + exit_code )
+ # Call on the job wrapper to complete the call:
try:
pbs_job_state.job_wrapper.finish( stdout, stderr, exit_code )
except:
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: Scott McManus: Added exit code/regex parsing PBS runner and fixed DRMAA/SGE runner
by Bitbucket 25 Jun '12
by Bitbucket 25 Jun '12
25 Jun '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/fdccf979fd8f/
changeset: fdccf979fd8f
user: Scott McManus
date: 2012-06-25 22:43:18
summary: Added exit code/regex parsing PBS runner and fixed DRMAA/SGE runner
affected #: 3681 files
diff -r 319b2b0e832c8ea5ef520c76722f7ad6270507c3 -r fdccf979fd8f2a7dcd3de0a8266af1c7c68f0542 lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -291,8 +291,6 @@
the output datasets based on stderr and stdout from the command, and
the contents of the output files.
"""
- # TODO: Eliminate debugging code after testing all runners
- log.debug( "JobWrapper.finish: exit code:" + str(tool_exit_code) )
# default post job setup
self.sa_session.expunge_all()
job = self.get_job()
@@ -319,6 +317,7 @@
# that range, then apply the error level and add in a message.
# If we've reached a fatal error rule, then stop.
max_error_level = galaxy.tools.StdioErrorLevel.NO_ERROR
+ tool_exit_code = int( tool_exit_code )
for stdio_exit_code in self.tool.stdio_exit_codes:
if ( tool_exit_code >= stdio_exit_code.range_start and
tool_exit_code <= stdio_exit_code.range_end ):
diff -r 319b2b0e832c8ea5ef520c76722f7ad6270507c3 -r fdccf979fd8f2a7dcd3de0a8266af1c7c68f0542 lib/galaxy/jobs/runners/drmaa.py
--- a/lib/galaxy/jobs/runners/drmaa.py
+++ b/lib/galaxy/jobs/runners/drmaa.py
@@ -39,6 +39,11 @@
drmaa.JobState.FAILED: 'job finished, but failed',
}
+# The last four lines (following the last fi) will:
+# - setup the env
+# - move to the job wrapper's working directory
+# - execute the command
+# - take the command's exit code ($?) and write it to a file.
drm_template = """#!/bin/sh
GALAXY_LIB="%s"
if [ "$GALAXY_LIB" != "None" ]; then
@@ -52,6 +57,7 @@
%s
cd %s
%s
+echo $? > %s
"""
def __lineno__():
"""Returns the current line number in our program."""
@@ -77,7 +83,7 @@
self.job_file = None
self.ofile = None
self.efile = None
- self.rcfile = None
+ self.ecfile = None
self.runner_url = None
class DRMAAJobRunner( BaseJobRunner ):
@@ -169,7 +175,7 @@
# define job attributes
ofile = "%s.drmout" % os.path.join(job_wrapper.working_directory, job_wrapper.get_id_tag())
efile = "%s.drmerr" % os.path.join(job_wrapper.working_directory, job_wrapper.get_id_tag())
- rcfile = "%s.drmrc" % os.path.join(job_wrapper.working_directory, job_wrapper.get_id_tag())
+ ecfile = "%s.drmec" % os.path.join(job_wrapper.working_directory, job_wrapper.get_id_tag())
job_name = "g%s_%s_%s" % ( job_wrapper.job_id, job_wrapper.tool.id, job_wrapper.user )
job_name = ''.join( map( lambda x: x if x in ( string.letters + string.digits + '_' ) else '_', job_name ) )
@@ -178,7 +184,7 @@
jt.jobName = job_name
jt.outputPath = ":%s" % ofile
jt.errorPath = ":%s" % efile
- jt.returnCodePath = ":%s" % rcfile
+ # Avoid a jt.exitCodePath for now - it's only used when finishing.
native_spec = self.get_native_spec( runner_url )
if native_spec is not None:
jt.nativeSpecification = native_spec
@@ -187,7 +193,8 @@
script = drm_template % ( job_wrapper.galaxy_lib_dir,
job_wrapper.get_env_setup_clause(),
os.path.abspath( job_wrapper.working_directory ),
- command_line )
+ command_line,
+ ecfile )
try:
fh = file( jt.remoteCommand, "w" )
@@ -231,7 +238,7 @@
drm_job_state.job_id = job_id
drm_job_state.ofile = ofile
drm_job_state.efile = efile
- drm_job_state.rcfile = rcfile
+ drm_job_state.ecfile = ecfile
drm_job_state.job_file = jt.remoteCommand
drm_job_state.old_state = 'new'
drm_job_state.running = False
@@ -316,17 +323,22 @@
"""
ofile = drm_job_state.ofile
efile = drm_job_state.efile
- rcfile = drm_job_state.rcfile
+ ecfile = drm_job_state.ecfile
job_file = drm_job_state.job_file
# collect the output
# wait for the files to appear
which_try = 0
+ # By default, the exit code is 0, which typically indicates success.
+ exit_code = 0
while which_try < (self.app.config.retry_job_output_collection + 1):
try:
ofh = file(ofile, "r")
efh = file(efile, "r")
+ ecfh = file(ecfile, "r")
stdout = ofh.read( 32768 )
stderr = efh.read( 32768 )
+ # The exit code should only be 8 bits, but read more anyway
+ exit_code_str = ecfh.read(32)
which_try = (self.app.config.retry_job_output_collection + 1)
except:
if which_try == self.app.config.retry_job_output_collection:
@@ -337,8 +349,15 @@
time.sleep(1)
which_try += 1
+ # Decode the exit code. If it's bogus, then just use 0.
try:
- drm_job_state.job_wrapper.finish( stdout, stderr )
+ exit_code = int(exit_code_str)
+ except:
+ log.warning( "Exit code " + exit_code_str + " invalid. Using 0." )
+ exit_code = 0
+
+ try:
+ drm_job_state.job_wrapper.finish( stdout, stderr, int(exit_code) )
except:
log.exception("Job wrapper finish method failed")
@@ -382,7 +401,7 @@
drm_job_state = DRMAAJobState()
drm_job_state.ofile = "%s.drmout" % os.path.join(os.getcwd(), job_wrapper.working_directory, job_wrapper.get_id_tag())
drm_job_state.efile = "%s.drmerr" % os.path.join(os.getcwd(), job_wrapper.working_directory, job_wrapper.get_id_tag())
- drm_job_state.rcfile = "%s.drmrc" % os.path.join(os.getcwd(), job_wrapper.working_directory, job_wrapper.get_id_tag())
+ drm_job_state.ecfile = "%s.drmec" % os.path.join(os.getcwd(), job_wrapper.working_directory, job_wrapper.get_id_tag())
drm_job_state.job_file = "%s/galaxy_%s.sh" % (self.app.config.cluster_files_directory, job.id)
drm_job_state.job_id = str( job.job_runner_external_id )
drm_job_state.runner_url = job_wrapper.get_job_runner()
diff -r 319b2b0e832c8ea5ef520c76722f7ad6270507c3 -r fdccf979fd8f2a7dcd3de0a8266af1c7c68f0542 lib/galaxy/jobs/runners/pbs.py
--- a/lib/galaxy/jobs/runners/pbs.py
+++ b/lib/galaxy/jobs/runners/pbs.py
@@ -532,16 +532,22 @@
stdout = ofh.read( 32768 )
stderr = efh.read( 32768 )
# This should be an 8-bit exit code, but read ahead anyway:
- exit_code = ecfh.read(32)
+ exit_code_str = ecfh.read(32)
except:
stdout = ''
stderr = 'Job output not returned by PBS: the output datasets were deleted while the job was running, the job was manually dequeued or there was a cluster error.'
# By default, the exit code is 0, which usually indicates success
# (although clearly some error happened).
+ exit_code_str = ""
+
+ # Translate the exit code string to an integer; use 0 on failure.
+ try:
+ exit_code = int( exit_code_str )
+ except:
+ log.warning( "Exit code " + exit_code_str + " was invalid. Using 0." )
exit_code = 0
- log.debug(stderr)
- log.debug( "Job exit code: " + exit_code )
+ # Call on the job wrapper to complete the call:
try:
pbs_job_state.job_wrapper.finish( stdout, stderr, exit_code )
except:
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/changeset/c04ab20c6ee2/
changeset: c04ab20c6ee2
user: dan
date: 2012-06-25 21:53:57
summary: Fix for getting mime type of converted datasets when not specified explicitly for external display applications.
affected #: 1 file
diff -r 20e01e610de056e2f2855df9a3840c315b17587f -r c04ab20c6ee25af93a8aedc529a6689e8d64e8b2 lib/galaxy/datatypes/display_applications/parameters.py
--- a/lib/galaxy/datatypes/display_applications/parameters.py
+++ b/lib/galaxy/datatypes/display_applications/parameters.py
@@ -195,6 +195,8 @@
mime = self.trans.app.datatypes_registry.get_mimetype_by_extension( ".".split( self._url )[ -1 ], None )
if mime:
return mime
+ if hasattr( self.value, 'get_mime' ):
+ return self.value.get_mime()
return self.other_values[ DEFAULT_DATASET_NAME ].get_mime()
@property
def action_name( self ):
https://bitbucket.org/galaxy/galaxy-central/changeset/319b2b0e832c/
changeset: 319b2b0e832c
user: dan
date: 2012-06-25 21:54:27
summary: Add name parameter to IGV external display applications.
affected #: 2 files
diff -r c04ab20c6ee25af93a8aedc529a6689e8d64e8b2 -r 319b2b0e832c8ea5ef520c76722f7ad6270507c3 display_applications/igv/bam.xml
--- a/display_applications/igv/bam.xml
+++ b/display_applications/igv/bam.xml
@@ -81,9 +81,9 @@
</param><param type="template" name="redirect_url" strip="True" >
#if $site_id.startswith( 'local_' )
- ${site_link}?file=${bam_file.qp}&genome=${site_organism}&merge=true
+ ${site_link}?file=${bam_file.qp}&genome=${site_organism}&merge=true&name=${qp( $bam_file.name )}
#elif $site_id.startswith( 'web_link_' ):
- ${site_link}?sessionURL=${bam_file.qp}&genome=${site_organism}&merge=true
+ ${site_link}?sessionURL=${bam_file.qp}&genome=${site_organism}&merge=true&name=${qp( $bam_file.name )}
#else:
${jnlp.url}
#end if
diff -r c04ab20c6ee25af93a8aedc529a6689e8d64e8b2 -r 319b2b0e832c8ea5ef520c76722f7ad6270507c3 display_applications/igv/vcf.xml
--- a/display_applications/igv/vcf.xml
+++ b/display_applications/igv/vcf.xml
@@ -81,9 +81,9 @@
</param><param type="template" name="redirect_url" strip="True" >
#if $site_id.startswith( 'local_' )
- ${site_link}?file=${bgzip_file.qp}&genome=${site_organism}&merge=true
+ ${site_link}?file=${bgzip_file.qp}&genome=${site_organism}&merge=true&name=${qp( $bgzip_file.name )}
#elif $site_id.startswith( 'web_link_' ):
- ${site_link}?sessionURL=${bgzip_file.qp}&genome=${site_organism}&merge=true
+ ${site_link}?sessionURL=${bgzip_file.qp}&genome=${site_organism}&merge=true&name=${qp( $bgzip_file.name )}
#else:
${jnlp.url}
#end if
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