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: Trackster: put in framework to manage track collections.
by Bitbucket 23 Sep '11
by Bitbucket 23 Sep '11
23 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/c691f5c65011/
changeset: c691f5c65011
user: jgoecks
date: 2011-09-23 19:26:34
summary: Trackster: put in framework to manage track collections.
affected #: 3 files (-1 bytes)
--- a/static/scripts/packed/trackster.js Fri Sep 23 11:32:08 2011 -0400
+++ b/static/scripts/packed/trackster.js Fri Sep 23 13:26:34 2011 -0400
@@ -1,1 +1,1 @@
-var class_module=function(b,a){var c=function(){var f=arguments[0];for(var e=1;e<arguments.length;e++){var d=arguments[e];for(key in d){f[key]=d[key]}}return f};a.extend=c};var requestAnimationFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b,a){window.setTimeout(b,1000/60)}})();var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=BEFORE}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var trackster_module=function(f,W){var p=f("class").extend,r=f("slotting"),K=f("painters");var ad=function(ae,af){this.document=ae;this.default_font=af!==undefined?af:"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")};p(ad.prototype,{load_pattern:function(ae,ai){var af=this.patterns,ag=this.dummy_context,ah=new Image();ah.src=image_path+ai;ah.onload=function(){af[ae]=ag.createPattern(ah,"repeat")}},get_pattern:function(ae){return this.patterns[ae]},new_canvas:function(){var ae=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(ae)}ae.manager=this;return ae}});var m=function(ae,ag,ah){ah=".group";var af={};ae.bind("drag",{handle:"."+ag,relative:true},function(an,ao){var aq=$(this).parent(),al=aq.children(),ak,aj,ap,ai,am;aj=$(this).parents(ah);if(aj.length!==0){ap=aj.position().top;ai=ap+aj.outerHeight();if(ao.offsetY<ap){$(this).insertBefore(aj);return}else{if(ao.offsetY>ai){$(this).insertAfter(aj);return}}}aj=null;for(am=0;am<al.length;am++){ak=$(al.get(am));ap=ak.position().top;ai=ap+ak.outerHeight();if(ak.is(ah)&&this!==ak.get(0)&&ao.offsetY>=ap&&ao.offsetY<=ai){if(ao.offsetY-ap<ai-ao.offsetY){ak.find(".content-div").prepend(this)}else{ak.find(".content-div").append(this)}return}}for(am=0;am<al.length;am++){if(ao.offsetY<$(al.get(am)).position().top){break}}if(am===al.length){if(this!==al.get(am-1)){aq.append(this)}}else{if(this!==al.get(am)){$(this).insertBefore(al.get(am))}}}).bind("dragstart",function(){af["border-top"]=ae.css("border-top");af["border-bottom"]=ae.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(af)})};W.moveable=m;var ac=16,F=9,D=20,R=F+2,z=100,H=12000,P=200,C=5,u=10,J=5000,v=100,n="There was an error in indexing this dataset. ",I="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",s="Currently indexing... please wait",x="Tool cannot be rerun: ",a="Loading data...",X="Ready for display",d=10,t=5,B=5;function w(ae){return Math.round(ae*1000)/1000}var c=function(ae){this.num_elements=ae;this.clear()};p(c.prototype,{get:function(af){var ae=this.key_ary.indexOf(af);if(ae!==-1){if(this.obj_cache[af].stale){this.key_ary.splice(ae,1);delete this.obj_cache[af]}else{this.move_key_to_end(af,ae)}}return this.obj_cache[af]},set:function(af,ag){if(!this.obj_cache[af]){if(this.key_ary.length>=this.num_elements){var ae=this.key_ary.shift();delete this.obj_cache[ae]}this.key_ary.push(af)}this.obj_cache[af]=ag;return ag},move_key_to_end:function(af,ae){this.key_ary.splice(ae,1);this.key_ary.push(af)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var Q=function(af,ae,ag){c.call(this,af);this.track=ae;this.subset=(ag!==undefined?ag:true)};p(Q.prototype,c.prototype,{load_data:function(an,ai,al,af,ak){var am=this.track.view.chrom,ah={chrom:am,low:an,high:ai,mode:al,resolution:af,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(ah,ak);if(this.track.filters_manager){var ao=[];var ae=this.track.filters_manager.filters;for(var aj=0;aj<ae.length;aj++){ao[ao.length]=ae[aj].name}ah.filter_cols=JSON.stringify(ao)}var ag=this;return $.getJSON(this.track.data_url,ah,function(ap){ag.set_data(an,ai,al,ap)})},get_data:function(ae,ai,aj,af,ah){var ag=this.get_data_from_cache(ae,ai,aj);if(ag){return ag}ag=this.load_data(ae,ai,aj,af,ah);this.set_data(ae,ai,aj,ag);return ag},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(am,ah,al,ag,ak,ai){var an=this.get_data_from_cache(am,ah,al);if(!an){console.log("ERROR: no current data for: ",this.track,am,ah,al,ag,ak);return}an.stale=true;var af=am;if(ai===this.DEEP_DATA_REQ){$.extend(ak,{start_val:an.data.length+1})}else{if(ai===this.BROAD_DATA_REQ){af=(an.max_high?an.max_high:an.data[an.data.length-1][2])+1}}var ae=this,aj=this.load_data(af,ah,al,ag,ak);new_data_available=$.Deferred();this.set_data(am,ah,al,new_data_available);$.when(aj).then(function(ao){if(ao.data){ao.data=an.data.concat(ao.data);if(ao.max_low){ao.max_low=an.max_low}if(ao.message){ao.message=ao.message.replace(/[0-9]+/,ao.data.length)}}ae.set_data(am,ah,al,ao);new_data_available.resolve(ao)});return new_data_available},get_data_from_cache:function(ae,af,ag){return this.get(this.gen_key(ae,af,ag))},set_data:function(af,ag,ah,ae){return this.set(this.gen_key(af,ag,ah),ae)},gen_key:function(ae,ag,ah){var af=ae+"_"+ag+"_"+ah;return af},split_key:function(ae){return ae.split("_")}});var G=function(af,ae,ag){Q.call(this,af,ae,ag)};p(G.prototype,Q.prototype,c.prototype,{load_data:function(ag,ae,ai,aj,af,ah){if(af>1){return}return Q.prototype.load_data.call(this,ag,ae,ai,aj,af,ah)}});var ab=function(ae,ah,ag,af,ai){this.container=ae;this.chrom=null;this.vis_id=ag;this.dbkey=af;this.title=ah;this.tracks=[];this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init(ai);this.canvas_manager=new ad(ae.get(0).ownerDocument);this.reset()};p(ab.prototype,{init:function(ai){var ag=this.container,ae=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ag);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ag);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ag);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var ah=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_tracks()});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var af=function(aj){if(aj.type==="focusout"||(aj.keyCode||aj.which)===13||(aj.keyCode||aj.which)===27){if((aj.keyCode||aj.which)!==27){ae.go_to($(this).val())}$(this).hide();$(this).val("");ae.location_span.show();ae.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",af).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.click(function(){ae.location_span.hide();ae.chrom_select.hide();ae.nav_input.val(ae.chrom+":"+ae.low+"-"+ae.high);ae.nav_input.css("display","inline-block");ae.nav_input.select();ae.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a id='zoom-out' />").click(function(){ae.zoom_out();ae.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){ae.zoom_in();ae.request_redraw()}).appendTo(this.nav_controls);this.load_chroms({low:0},ai);this.chrom_select.bind("change",function(){ae.change_chrom(ae.chrom_select.val())});this.content_div.click(function(aj){$(this).find("input").trigger("blur")});this.content_div.bind("dblclick",function(aj){ae.zoom_in(aj.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(aj,ak){this.current_x=ak.offsetX}).bind("drag",function(aj,al){var am=al.offsetX-this.current_x;this.current_x=al.offsetX;var ak=Math.round(am/ae.viewport_container.width()*(ae.max_high-ae.max_low));ae.move_delta(-ak)});this.overview_close.click(function(){ae.reset_overview()});this.viewport_container.bind("draginit",function(aj,ak){if(aj.clientX>ae.viewport_container.width()-16){return false}}).bind("dragstart",function(aj,ak){ak.original_low=ae.low;ak.current_height=aj.clientY;ak.current_x=ak.offsetX}).bind("drag",function(al,an){var aj=$(this);var ao=an.offsetX-an.current_x;var ak=aj.scrollTop()-(al.clientY-an.current_height);aj.scrollTop(ak);an.current_height=al.clientY;an.current_x=an.offsetX;var am=Math.round(ao/ae.viewport_container.width()*(ae.high-ae.low));ae.move_delta(am)}).bind("mousewheel",function(al,an,ak,aj){if(ak){var am=Math.round(-ak/ae.viewport_container.width()*(ae.high-ae.low));ae.move_delta(am)}});this.top_labeltrack.bind("dragstart",function(aj,ak){return $("<div />").css({height:ae.content_div.height()+ae.top_labeltrack.height()+ae.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(an,ao){$(ao.proxy).css({left:Math.min(an.pageX,ao.startX),width:Math.abs(an.pageX-ao.startX)});var ak=Math.min(an.pageX,ao.startX)-ae.container.offset().left,aj=Math.max(an.pageX,ao.startX)-ae.container.offset().left,am=(ae.high-ae.low),al=ae.viewport_container.width();ae.update_location(Math.round(ak/al*am)+ae.low,Math.round(aj/al*am)+ae.low)}).bind("dragend",function(ao,ap){var ak=Math.min(ao.pageX,ap.startX),aj=Math.max(ao.pageX,ap.startX),am=(ae.high-ae.low),al=ae.viewport_container.width(),an=ae.low;ae.low=Math.round(ak/al*am)+an;ae.high=Math.round(aj/al*am)+an;$(ap.proxy).remove();ae.request_redraw()});this.add_label_track(new aa(this,this.top_labeltrack));this.add_label_track(new aa(this,this.nav_labeltrack));$(window).bind("resize",function(){ae.resize_window()});$(document).bind("redraw",function(){ae.redraw()});this.reset();$(window).trigger("resize");this.update_intro_div()},to_json:function(){var ae=this,af=[];this.viewport_container.children(".track,.group").each(function(){var ag=$(this).attr("id");ag=parseInt(ag.slice(ag.lastIndexOf("_")+1));af.push(ae.tracks[ag].to_json())});return af},update_intro_div:function(){if(this.num_tracks===0){this.intro_div.show()}else{this.intro_div.hide()}},update_location:function(ae,af){this.location_span.text(commatize(ae)+" - "+commatize(af));this.nav_input.val(this.chrom+":"+commatize(ae)+"-"+commatize(af))},load_chroms:function(af,ag){af.num=v;$.extend(af,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var ae=this;$.ajax({url:chrom_url,data:af,dataType:"json",success:function(ai){if(ai.chrom_info.length===0){alert("Invalid chromosome: "+af.chrom);return}if(ai.reference){ae.add_label_track(new A(ae))}ae.chrom_data=ai.chrom_info;var al='<option value="">Select Chrom/Contig</option>';for(var ak=0,ah=ae.chrom_data.length;ak<ah;ak++){var aj=ae.chrom_data[ak].chrom;al+='<option value="'+aj+'">'+aj+"</option>"}if(ai.prev_chroms){al+='<option value="previous">Previous '+v+"</option>"}if(ai.next_chroms){al+='<option value="next">Next '+v+"</option>"}ae.chrom_select.html(al);if(ag){ag()}ae.chrom_start_index=ai.start_index},error:function(){alert("Could not load chroms for this dbkey:",ae.dbkey)}})},change_chrom:function(ai,af,ak){if(!ai||ai==="None"){return}var ah=this;if(ai==="previous"){ah.load_chroms({low:this.chrom_start_index-v});return}if(ai==="next"){ah.load_chroms({low:this.chrom_start_index+v});return}var aj=$.grep(ah.chrom_data,function(am,an){return am.chrom===ai})[0];if(aj===undefined){ah.load_chroms({chrom:ai},function(){ah.change_chrom(ai,af,ak)});return}else{if(ai!==ah.chrom){ah.chrom=ai;ah.chrom_select.val(ah.chrom);ah.max_high=aj.len-1;ah.reset();ah.request_redraw(true);for(var al=0,ae=ah.tracks.length;al<ae;al++){var ag=ah.tracks[al];if(ag.init){ag.init()}}}if(af!==undefined&&ak!==undefined){ah.low=Math.max(af,0);ah.high=Math.min(ak,ah.max_high)}ah.reset_overview();ah.request_redraw()}},go_to:function(ai){var am=this,ae,ah,af=ai.split(":"),ak=af[0],al=af[1];if(al!==undefined){try{var aj=al.split("-");ae=parseInt(aj[0].replace(/,/g,""),10);ah=parseInt(aj[1].replace(/,/g,""),10)}catch(ag){return false}}am.change_chrom(ak,ae,ah)},move_fraction:function(ag){var ae=this;var af=ae.high-ae.low;this.move_delta(ag*af)},move_delta:function(ag){var ae=this;var af=ae.high-ae.low;if(ae.low-ag<ae.max_low){ae.low=ae.max_low;ae.high=ae.max_low+af}else{if(ae.high-ag>ae.max_high){ae.high=ae.max_high;ae.low=ae.max_high-af}else{ae.high-=ag;ae.low-=ag}}ae.request_redraw()},add_track:function(ae){ae.view=this;ae.track_id=this.track_id_counter;this.tracks.push(ae);if(ae.init){ae.init()}ae.container_div.attr("id","track_"+ae.track_id);m(ae.container_div,ae.drag_handle_class);this.track_id_counter+=1;this.num_tracks+=1;this.has_changes=true;this.update_intro_div()},add_label_track:function(ae){ae.view=this;this.label_tracks.push(ae)},remove_track:function(af){this.has_changes=true;this.tracks.splice(this.tracks.indexOf(af),1);this.num_tracks-=1;var ae=this;af.container_div.fadeOut("slow",function(){$(this).remove();ae.update_intro_div()})},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(am,ae,al,af){var ak=this,ai=(af?[af]:ak.tracks),ag;var af;for(var aj=0;aj<ai.length;aj++){af=ai[aj];ag=-1;for(var ah=0;ah<ak.tracks_to_be_redrawn.length;ah++){if(ak.tracks_to_be_redrawn[ah][0]===af){ag=ah;break}}if(ag<0){ak.tracks_to_be_redrawn.push([af,ae,al])}else{ak.tracks_to_be_redrawn[aj][1]=ae;ak.tracks_to_be_redrawn[aj][2]=al}}requestAnimationFrame(function(){ak._redraw(am)})},_redraw:function(ao){var al=this.low,ah=this.high;if(al<this.max_low){al=this.max_low}if(ah>this.max_high){ah=this.max_high}var an=this.high-this.low;if(this.high!==0&&an<this.min_separation){ah=al+this.min_separation}this.low=Math.floor(al);this.high=Math.ceil(ah);this.resolution=Math.pow(C,Math.ceil(Math.log((this.high-this.low)/P)/Math.log(C)));this.zoom_res=Math.pow(u,Math.max(0,Math.ceil(Math.log(this.resolution,u)/Math.log(u))));var ae=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ak=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ap=13;this.overview_box.css({left:ae,width:Math.max(ap,ak)}).show();if(ak<ap){this.overview_box.css("left",ae-(ap-ak)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ae,width:ak})}this.update_location(this.low,this.high);if(!ao){var ag,af,am;for(var ai=0,aj=this.tracks_to_be_redrawn.length;ai<aj;ai++){ag=this.tracks_to_be_redrawn[ai][0];af=this.tracks_to_be_redrawn[ai][1];am=this.tracks_to_be_redrawn[ai][2];if(ag&&ag.enabled){ag._draw(af,am)}}this.tracks_to_be_redrawn=[];for(ai=0,aj=this.label_tracks.length;ai<aj;ai++){this.label_tracks[ai]._draw()}}},zoom_in:function(af,ag){if(this.max_high===0||this.high-this.low<this.min_separation){return}var ah=this.high-this.low,ai=ah/2+this.low,ae=(ah/this.zoom_factor)/2;if(af){ai=af/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ai-ae);this.high=Math.round(ai+ae);this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var af=this.high-this.low,ag=af/2+this.low,ae=(af*this.zoom_factor)/2;this.low=Math.round(ag-ae);this.high=Math.round(ag+ae);this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.request_redraw()},set_overview:function(ae){$.when(ae.get_overview_tile()).then(function(af){view.overview_viewport.find(".track-tile").remove();view.overview_close.show();view.overview_viewport.append(af.canvas);view.overview_highlight.show().height(af.canvas.height());view.overview_viewport.height(af.canvas.height()+view.overview_box.outerHeight());view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=ae;ae.set_is_overview(true)});view.has_changes=true},reset_overview:function(){this.overview_viewport.find(".track-tile").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide();view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=null}});var q=function(ag,ak){this.track=ag;this.name=ak.name;this.params=[];var ar=ak.params;for(var ah=0;ah<ar.length;ah++){var am=ar[ah],af=am.name,aq=am.label,ai=unescape(am.html),at=am.value,ao=am.type;if(ao==="number"){this.params[this.params.length]=new g(af,aq,ai,at,am.min,am.max)}else{if(ao=="select"){this.params[this.params.length]=new M(af,aq,ai,at)}else{console.log("WARNING: unrecognized tool parameter type:",af,ao)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(av){av.stopPropagation()}).click(function(av){av.stopPropagation()}).bind("dblclick",function(av){av.stopPropagation()});var ap=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var an=this.params;var al=this;$.each(this.params,function(aw,az){var ay=$("<div>").addClass("param-row").appendTo(al.parent_div);var av=$("<div>").addClass("param-label").text(az.label).appendTo(ay);var ax=$("<div/>").addClass("slider").html(az.html).appendTo(ay);ax.find(":input").val(az.value);$("<div style='clear: both;'/>").appendTo(ay)});this.parent_div.find("input").click(function(){$(this).select()});var au=$("<div>").addClass("param-row").appendTo(this.parent_div);var aj=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(au);var ae=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(au);var al=this;ae.click(function(){al.run_on_region()});aj.click(function(){al.run_on_dataset()})};p(q.prototype,{get_param_values_dict:function(){var ae={};this.parent_div.find(":input").each(function(){var af=$(this).attr("name"),ag=$(this).val();ae[af]=JSON.stringify(ag)});return ae},get_param_values:function(){var af=[];var ae={};this.parent_div.find(":input").each(function(){var ag=$(this).attr("name"),ah=$(this).val();if(ag){af[af.length]=ah}});return af},run_on_dataset:function(){var ae=this;ae.run({dataset_id:this.track.original_dataset_id,tool_id:ae.name},null,function(af){show_modal(ae.name+" is Running",ae.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ae={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},ag=this.track,af=ae.tool_id+ag.tool_region_and_parameters_str(ae.chrom,ae.low,ae.high),ah;if(ag instanceof e){ah=new T(af,view,ag.hda_ldda,undefined,{},{},ag);ah.change_mode(ag.mode)}this.track.view.add_track(ah);ah.content_div.text("Starting job.");this.run(ae,ah,function(ai){ah.dataset_id=ai.dataset_id;ah.content_div.text("Running job.");ah.init()})},run:function(af,ag,ah){$.extend(af,this.get_param_values_dict());var ae=function(){$.getJSON(rerun_tool_url,af,function(ai){if(ai==="no converter"){ag.container_div.addClass("error");ag.content_div.text(I)}else{if(ai.error){ag.container_div.addClass("error");ag.content_div.text(x+ai.message)}else{if(ai==="pending"){ag.container_div.addClass("pending");ag.content_div.text("Converting input data so that it can be used quickly with tool.");setTimeout(ae,2000)}else{ah(ai)}}}})};ae()}});var M=function(af,ae,ag,ah){this.name=af;this.label=ae;this.html=ag;this.value=ah};var g=function(ag,af,ai,aj,ah,ae){M.call(this,ag,af,ai,aj);this.min=ah;this.max=ae};var h=function(af,ae,ag,ah){this.name=af;this.index=ae;this.tool_id=ag;this.tool_exp_name=ah};var U=function(af,ae,ag,ah){h.call(this,af,ae,ag,ah);this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.min=Number.MAX_VALUE;this.max=-Number.MAX_VALUE;this.container=null;this.slider=null;this.slider_label=null};p(U.prototype,{applies_to:function(ae){if(ae.length>this.index){return true}return false},keep:function(ae){if(!this.applies_to(ae)){return true}var af=parseFloat(ae[this.index]);return(isNaN(af)||(af>=this.low&&af<=this.high))},update_attrs:function(af){var ae=false;if(!this.applies_to(af)){return ae}if(af[this.index]<this.min){this.min=Math.floor(af[this.index]);ae=true}if(af[this.index]>this.max){this.max=Math.ceil(af[this.index]);ae=true}return ae},update_ui_elt:function(){if(this.min!=this.max){this.container.show()}else{this.container.hide()}var ag=function(aj,ah){var ai=ah-aj;return(ai<=2?0.01:1)};var af=this.slider.slider("option","min"),ae=this.slider.slider("option","max");if(this.min<af||this.max>ae){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",ag(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var Z=function(ao,av){this.track=ao;this.filters=[];for(var ap=0;ap<av.length;ap++){var aq=av[ap],aw=aq.name,ae=aq.type,ah=aq.index,au=aq.tool_id,at=aq.tool_exp_name;if(ae==="int"||ae==="float"){this.filters[ap]=new U(aw,ah,au,at)}else{console.log("ERROR: unsupported filter: ",aw,ae)}}var ai=function(ax,ay,az){ax.click(function(){var aA=ay.text();max=parseFloat(az.slider("option","max")),input_size=(max<=1?4:max<=1000000?max.toString().length:6),multi_value=false;if(az.slider("option","values")){input_size=2*input_size+1;multi_value=true}ay.text("");$("<input type='text'/>").attr("size",input_size).attr("maxlength",input_size).attr("value",aA).appendTo(ay).focus().select().click(function(aB){aB.stopPropagation()}).blur(function(){$(this).remove();ay.text(aA)}).keyup(function(aF){if(aF.keyCode===27){$(this).trigger("blur")}else{if(aF.keyCode===13){var aD=az.slider("option","min"),aB=az.slider("option","max"),aE=function(aG){return(isNaN(aG)||aG>aB||aG<aD)},aC=$(this).val();if(!multi_value){aC=parseFloat(aC);if(aE(aC)){alert("Parameter value must be in the range ["+aD+"-"+aB+"]");return $(this)}}else{aC=aC.split("-");aC=[parseFloat(aC[0]),parseFloat(aC[1])];if(aE(aC[0])||aE(aC[1])){alert("Parameter value must be in the range ["+aD+"-"+aB+"]");return $(this)}}az.slider((multi_value?"values":"value"),aC)}}})})};this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(ax){ax.stopPropagation()}).click(function(ax){ax.stopPropagation()}).bind("dblclick",function(ax){ax.stopPropagation()}).bind("keydown",function(ax){ax.stopPropagation()});var ar=$("<div/>").addClass("sliders").appendTo(this.parent_div);var am=this;$.each(this.filters,function(aA,aC){aC.container=$("<div/>").addClass("slider-row").appendTo(ar);var aB=$("<div/>").addClass("elt-label").appendTo(aC.container);var az=$("<span/>").addClass("slider-name").text(aC.name+" ").appendTo(aB);var ay=$("<span/>");var aE=$("<span/>").addClass("slider-value").appendTo(aB).append("[").append(ay).append("]");var ax=$("<div/>").addClass("slider").appendTo(aC.container);aC.control_element=$("<div/>").attr("id",aC.name+"-filter-control").appendTo(ax);var aD=[0,0];aC.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(aG,aH){var aF=aH.values;ay.text(aF[0]+"-"+aF[1]);aC.low=aF[0];aC.high=aF[1];am.track.request_draw(true,true)},change:function(aF,aG){aC.control_element.slider("option","slide").call(aC.control_element,aF,aG)}});aC.slider=aC.control_element;aC.slider_label=ay;ai(aE,ay,aC.control_element);$("<div style='clear: both;'/>").appendTo(aC.container)});if(this.filters.length!==0){var aj=$("<div/>").addClass("param-row").appendTo(ar);var al=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(aj);var ag=this;al.click(function(){ag.run_on_dataset()})}var an=$("<div/>").addClass("display-controls").appendTo(this.parent_div),ak=$("<span/>").addClass("elt-label").text("Transparency:").appendTo(an),af=$("<select/>").attr("name","alpha_dropdown").appendTo(an);this.alpha_filter=null;$("<option/>").attr("value",-1).text("== None ==").appendTo(af);for(var ap=0;ap<this.filters.length;ap++){$("<option/>").attr("value",ap).text(this.filters[ap].name).appendTo(af)}af.change(function(){$(this).children("option:selected").each(function(){var ax=parseInt($(this).val());am.alpha_filter=(ax>=0?am.filters[ax]:null);am.track.request_draw(true,true)})});$("<div style='clear: both;'/>").appendTo(this.parent_div)};p(Z.prototype,{reset_filters:function(){for(var ae=0;ae<this.filters.length;ae++){filter=this.filters[ae];filter.slider.slider("option","values",[filter.min,filter.max])}this.alpha_filter=null},run_on_dataset:function(){var am=function(aq,ao,ap){if(!(ao in aq)){aq[ao]=ap}return aq[ao]};var ag={},ae,af,ah;for(var ai=0;ai<this.filters.length;ai++){ae=this.filters[ai];if(ae.tool_id){if(ae.min!=ae.low){af=am(ag,ae.tool_id,[]);af[af.length]=ae.tool_exp_name+" >= "+ae.low}if(ae.max!=ae.high){af=am(ag,ae.tool_id,[]);af[af.length]=ae.tool_exp_name+" <= "+ae.high}}}var ak=[];for(var an in ag){ak[ak.length]=[an,ag[an]]}var al=ak.length;(function aj(av,ar){var ap=ar[0],aq=ap[0],au=ap[1],at="("+au.join(") and (")+")",ao={cond:at,input:av,target_dataset_id:av,tool_id:aq},ar=ar.slice(1);$.getJSON(run_tool_url,ao,function(aw){if(aw.error){show_modal("Filter Dataset","Error running tool "+aq,{Close:hide_modal})}else{if(ar.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{aj(aw.dataset_id,ar)}}})})(this.track.dataset_id,ak)}});var N=function(af,ae){K.AlphaGenerator.call(this,ae);this.filter=af};N.prototype.gen_alpha=function(ae){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_alpha}return((parseFloat(ae[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var Y=function(ae){this.track=ae.track;this.params=ae.params;this.values={};if(ae.saved_values){this.restore_values(ae.saved_values)}this.onchange=ae.onchange};p(Y.prototype,{restore_values:function(ae){var af=this;$.each(this.params,function(ag,ah){if(ae[ah.key]!==undefined){af.values[ah.key]=ae[ah.key]}else{af.values[ah.key]=ah.default_value}})},build_form:function(){var af=this;var ae=$("<div />");$.each(this.params,function(aj,ah){if(!ah.hidden){var ag="param_"+aj;var al=af.values[ah.key];var ao=$("<div class='form-row' />").appendTo(ae);ao.append($("<label />").attr("for",ag).text(ah.label+":"));if(ah.type==="bool"){ao.append($('<input type="checkbox" />').attr("id",ag).attr("name",ag).attr("checked",al))}else{if(ah.type==="text"){ao.append($('<input type="text"/>').attr("id",ag).val(al).click(function(){$(this).select()}))}else{if(ah.type==="color"){var ak=$("<input />").attr("id",ag).attr("name",ag).val(al);var am=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var ai=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(am);var an=$("<div/>").appendTo(ai).farbtastic({width:100,height:100,callback:ak,color:al});$("<div />").append(ak).append(am).appendTo(ao).bind("click",function(ap){am.css({left:$(this).position().left+($(ak).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){am.hide();$(document).unbind("click.color-picker")});ap.stopPropagation()})}else{ao.append($("<input />").attr("id",ag).attr("name",ag).val(al))}}}}});return ae},update_from_form:function(ae){var ag=this;var af=false;$.each(this.params,function(ah,aj){if(!aj.hidden){var ak="param_"+ah;var ai=ae.find("#"+ak).val();if(aj.type==="float"){ai=parseFloat(ai)}else{if(aj.type==="int"){ai=parseInt(ai)}else{if(aj.type==="bool"){ai=ae.find("#"+ak).is(":checked")}}}if(ai!==ag.values[aj.key]){ag.values[aj.key]=ai;af=true}}});if(af){this.onchange()}}});var b=function(ag,af,ae,ah){this.index=ag;this.low=ag*P*af;this.high=(ag+1)*P*af;this.resolution=af;this.canvas=$("<div class='track-tile'/>").append(ae);this.data=ah;this.stale=false};var l=function(ag,af,ae,ah,ai){b.call(this,ag,af,ae,ah);this.max_val=ai};var O=function(ag,af,ae,ai,ah){b.call(this,ag,af,ae,ai);this.message=ah};var o=function(af,ae){this.name=af;this.view=ae;this.parent_element=ae.viewport_container};o.prototype.request_draw=function(){};o.prototype.draw=function(){};var y=function(af,ae){o.call(this,af,ae);this.members=[];this.drag_handle_class="group-handle";this.container_div=$("<div/>").addClass("group").appendTo(this.parent_element);this.container_div.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("group-name").text(this.name).appendTo(this.container_div);this.content_div=$("<div/>").addClass("content-div").appendTo(this.container_div)};p(y.prototype,o.prototype,{request_draw:function(af,ae){},draw:function(){}});var j=function(af,ae,ai,ag,ah){this.name=af;this.view=ae;this.parent_element=ai;this.data_url=(ag?ag:default_data_url);this.data_url_extra_params={};this.data_query_wait=(ah?ah:J);this.dataset_check_url=converted_datasets_state_url;this.drag_handle_class="draghandle";this.container_div=$("<div />").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)};p(j.prototype,{get_type:function(){if(this instanceof aa){return"LabelTrack"}else{if(this instanceof A){return"ReferenceTrack"}else{if(this instanceof k){return"LineTrack"}else{if(this instanceof V){return"ReadTrack"}else{if(this instanceof T){return"ToolDataFeatureTrack"}else{if(this instanceof S){return"VcfTrack"}else{if(this instanceof e){return"FeatureTrack"}}}}}}}return""},init:function(){var ae=this;ae.enabled=false;ae.tile_cache.clear();ae.data_manager.clear();ae.initial_canvas=undefined;ae.content_div.css("height","auto");ae.container_div.removeClass("nodata error pending");if(!ae.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:ae.hda_ldda,dataset_id:ae.dataset_id,chrom:ae.view.chrom},function(af){if(!af||af==="error"||af.kind==="error"){ae.container_div.addClass("error");ae.content_div.text(n);if(af.message){var ah=ae.view.tracks.indexOf(ae);var ag=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+af.message+"</pre>",{Close:hide_modal})});ae.content_div.append(ag)}}else{if(af==="no converter"){ae.container_div.addClass("error");ae.content_div.text(I)}else{if(af==="no data"||(af.data!==undefined&&(af.data===null||af.data.length===0))){ae.container_div.addClass("nodata");ae.content_div.text(E)}else{if(af==="pending"){ae.container_div.addClass("pending");ae.content_div.text(s);setTimeout(function(){ae.init()},ae.data_query_wait)}else{if(af.status==="data"){if(af.valid_chroms){ae.valid_chroms=af.valid_chroms;ae.make_name_popup_menu()}ae.content_div.text(X);if(ae.view.chrom){ae.content_div.text("");ae.content_div.css("height",ae.height_px+"px");ae.enabled=true;$.when(ae.predraw_init()).done(function(){ae.container_div.removeClass("nodata error pending");ae.request_draw()})}}}}}}})},predraw_init:function(){},set_name:function(ae){this.old_name=this.name;this.name=ae;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)}});var L=function(al,aj,am){var af=this,an=af.view;this.filters_manager=(al!==undefined?new Z(this,al):undefined);this.filters_available=false;this.filters_visible=false;this.tool=(aj!==undefined&&obj_length(aj)>0?new q(this,aj):undefined);this.is_overview=false;if(af.hidden){return}if(this.filters_manager){this.filters_div=this.filters_manager.parent_div;this.header_div.after(this.filters_div)}if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}if(af.display_modes!==undefined){if(af.mode_div===undefined){af.mode_div=$("<div class='right-float menubutton popup' />").appendTo(af.header_div);var ag=(af.track_config&&af.track_config.values.mode?af.track_config.values.mode:af.display_modes[0]);af.mode=ag;af.mode_div.text(ag);var ae={};for(var ah=0,ak=af.display_modes.length;ah<ak;ah++){var ai=af.display_modes[ah];ae[ai]=function(ao){return function(){af.change_mode(ao)}}(ai)}make_popupmenu(af.mode_div,ae)}else{af.mode_div.hide()}}this.make_name_popup_menu()};p(L.prototype,j.prototype,{to_json:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs}},change_mode:function(af){var ae=this;ae.mode_div.text(af);ae.mode=af;ae.track_config.values.mode=af;ae.tile_cache.clear();ae.request_draw()},make_name_popup_menu:function(){var af=this;var ae={};ae[(this.is_overview?"Hide overview":"Set as overview")]=function(){if(af.is_overview){af.view.reset_overview()}else{af.view.set_overview(af)}};ae["Edit configuration"]=function(){var aj=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ah=function(){af.track_config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ai=function(ak){if((ak.keyCode||ak.which)===27){aj()}else{if((ak.keyCode||ak.which)===13){ah()}}};$(window).bind("keypress.check_enter_esc",ai);show_modal("Configure Track",af.track_config.build_form(),{Cancel:aj,OK:ah})};if(af.filters_available>0){var ag=(af.filters_div.is(":visible")?"Hide filters":"Show filters");ae[ag]=function(){af.filters_visible=(af.filters_div.is(":visible"));if(af.filters_visible){af.filters_manager.reset_filters()}af.filters_div.toggle();af.make_name_popup_menu()}}if(af.tool){var ag=(af.dynamic_tool_div.is(":visible")?"Hide tool":"Show tool");ae[ag]=function(){if(!af.dynamic_tool_div.is(":visible")){af.set_name(af.name+af.tool_region_and_parameters_str())}else{menu_option_text="Show dynamic tool";af.revert_name()}af.dynamic_tool_div.toggle();af.make_name_popup_menu()}}if(af.valid_chroms){ae["List chrom/contigs with data"]=function(){show_modal("Chrom/contigs with data","<p>"+af.valid_chroms.join("<br/>")+"</p>",{Close:function(){hide_modal()}})}}ae.Remove=function(){view.remove_track(af);if(parent_obj.num_tracks===0){$("#no-tracks").show()}};make_popupmenu(af.name_div,ae)},set_is_overview:function(ae){this.is_overview=ae;this.make_name_popup_menu()},get_overview_tile:function(){var ae=this;view=ae.view,resolution=Math.pow(C,Math.ceil(Math.log((view.max_high-view.max_low)/P)/Math.log(C))),view_width=view.container.width(),w_scale=view_width/(view.max_high-view.max_low),overview_tile=$.Deferred();$.when(ae.data_manager.get_data(view.max_low,view.max_high,"Auto",resolution,ae.data_url_extra_params)).then(function(af){var ah=ae._gen_tile_cache_key(view_width,w_scale,0),aj=ae.tile_cache.get(ah);if(!aj){aj=ae.draw_tile(af,"Auto",resolution,0,w_scale);ae.tile_cache.set(ah,aj)}var am=$(aj.canvas.find("canvas")),ai=am.clone(),al=am.get(0).getContext("2d"),ag=ai.get(0).getContext("2d"),ak=al.getImageData(0,0,al.canvas.width,al.canvas.height);ag.putImageData(ak,-ae.left_offset,(aj.data.dataset_type==="summary_tree"?R:0));new_tile=new b(-1,resolution,ai);overview_tile.resolve(new_tile)});return overview_tile},_gen_tile_cache_key:function(af,ag,ae){return af+"_"+ag+"_"+ae},request_draw:function(af,ae){this.view.request_redraw(false,af,ae,this)},_draw:function(ag,ao){if(!(this instanceof A)&&(!this.dataset_id)){return}var an=this.view.low,ak=this.view.high,al=ak-an,ah=this.view.container.width(),ar=ah/al,aj=this.view.resolution,aq=$("<div style='position: relative;'></div>");if(!ao){this.content_div.children().remove()}this.content_div.append(aq);this.max_height=0;var af=Math.floor(an/aj/P);var am=true;var ap=[];var ae=0;while((af*P*aj)<ak){tile=this.draw_helper(ag,ah,af,aj,aq,ar);if(tile){ap.push(tile)}else{am=false}af+=1;ae++}var ai=this;if(am){ai.postdraw_actions(ap,ah,ar,ao)}},postdraw_actions:function(ai,aj,ak,ae){var ag=this;var ah=false;for(var af=0;af<ai.length;af++){if(ai[af].message){ah=true;break}}if(ah){for(var af=0;af<ai.length;af++){tile=ai[af];if(!tile.message){tile.canvas.css("padding-top",D)}}}},draw_helper:function(af,ag,ah,ak,aq,av,ar,al){var ai=this,ap=this._gen_tile_cache_key(ag,av,ah),am=ah*P*ak,au=am+P*ak;var an=(af?undefined:ai.tile_cache.get(ap));if(an){ai.show_tile(an,aq,av);return an}var ao=function(aw){return("isResolved" in aw)};var aj=true;var ae=ai.data_manager.get_data(am,au,ai.mode,ak,ai.data_url_extra_params);if(ao(ae)){aj=false}var at;if(view.reference_track&&av>view.canvas_manager.char_width_px){at=view.reference_track.data_manager.get_data(am,au,ai.mode,ak,view.reference_track.data_url_extra_params);if(ao(at)){aj=false}}if(aj){p(ae,al);var an=ai.draw_tile(ae,ai.mode,ak,ah,av,at);ai.tile_cache.set(ap,an);if(an!==undefined){ai.show_tile(an,aq,av)}return an}$.when(ae,at).then(function(){view.request_redraw()});return null},show_tile:function(al,an,ao){var ag=this,af=al.canvas,ak=af;if(al.message){var ap=$("<div/>"),am=$("<div/>").addClass("tile-message").text(al.message).css({height:D-1,width:al.canvas.width}).appendTo(ap),ai=$("<a href='javascript:void(0);'/>").addClass("icon more-down").appendTo(am),ae=$("<a href='javascript:void(0);'/>").addClass("icon more-across").appendTo(am);ap.append(af);ak=ap;ai.click(function(){al.stale=true;ag.data_manager.get_more_data(al.low,al.high,ag.mode,al.resolution,{},ag.data_manager.DEEP_DATA_REQ);ag.request_draw()}).dblclick(function(aq){aq.stopPropagation()});ae.click(function(){al.stale=true;ag.data_manager.get_more_data(al.low,al.high,ag.mode,al.resolution,{},ag.data_manager.BROAD_DATA_REQ);ag.request_draw()}).dblclick(function(aq){aq.stopPropagation()})}var aj=this.view.high-this.view.low,ah=(al.low-this.view.low)*ao;if(this.left_offset){ah-=this.left_offset}ak.css({position:"absolute",top:0,left:ah,height:""});an.append(ak);ag.max_height=Math.max(ag.max_height,ak.height());ag.content_div.css("height",ag.max_height+"px");an.children().css("height",ag.max_height+"px")},_get_tile_bounds:function(ae,af){var ah=ae*P*af,ai=P*af,ag=(ah+ai<=this.view.max_high?ah+ai:this.view.max_high);return[ah,ag]},tool_region_and_parameters_str:function(ag,ae,ah){var af=this,ai=(ag!==undefined&&ae!==undefined&&ah!==undefined?ag+":"+ae+"-"+ah:"all");return" - region=["+ai+"], parameters=["+af.tool.get_param_values().join(", ")+"]"}});var aa=function(ae,af){this.hidden=true;j.call(this,null,ae,af);this.container_div.addClass("label-track")};p(aa.prototype,j.prototype,{_draw:function(){var ag=this.view,ah=ag.high-ag.low,ak=Math.floor(Math.pow(10,Math.floor(Math.log(ah)/Math.log(10)))),ae=Math.floor(ag.low/ak)*ak,ai=this.view.container.width(),af=$("<div style='position: relative; height: 1.3em;'></div>");while(ae<ag.high){var aj=(ae-ag.low)/ah*ai;af.append($("<div class='label'>"+commatize(ae)+"</div>").css({position:"absolute",left:aj-1}));ae+=ak}this.content_div.children(":first").remove();this.content_div.append(af)}});var A=function(ae){this.hidden=true;j.call(this,null,ae,ae.top_labeltrack);L.call(this);ae.reference_track=this;this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url;this.data_url_extra_params={dbkey:ae.dbkey};this.data_manager=new G(B,this,false);this.tile_cache=new c(t)};p(A.prototype,L.prototype,{draw_tile:function(ao,ak,aj,af,ap){var ai=this,ag=P*aj;if(ap>this.view.canvas_manager.char_width_px){if(ao===null){ai.content_div.css("height","0px");return}var ah=this.view.canvas_manager.new_canvas();var an=ah.getContext("2d");ah.width=Math.ceil(ag*ap+ai.left_offset);ah.height=ai.height_px;an.font=an.canvas.manager.default_font;an.textAlign="center";ao=ao.data;for(var al=0,am=ao.length;al<am;al++){var ae=Math.round(al*ap);an.fillText(ao[al],ae+ai.left_offset,10)}return new b(af,aj,ah,ao)}this.content_div.css("height","0px")}});var k=function(ai,ag,aj,ae,ah){var af=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";j.call(this,ai,ag,ag.viewport_container);L.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=aj;this.dataset_id=ae;this.original_dataset_id=ae;this.data_manager=new Q(B,this);this.tile_cache=new c(t);this.left_offset=0;this.track_config=new Y({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ai},{key:"color",label:"Color",type:"color",default_value:"black"},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.height_px,hidden:true}],saved_values:ah,onchange:function(){af.set_name(af.prefs.name);af.vertical_range=af.prefs.max_value-af.prefs.min_value;$("#linetrack_"+af.track_id+"_minval").text(af.prefs.min_value);$("#linetrack_"+af.track_id+"_maxval").text(af.prefs.max_value);af.tile_cache.clear();af.request_draw()}});this.prefs=this.track_config.values;this.height_px=this.track_config.values.height;this.vertical_range=this.track_config.values.max_value-this.track_config.values.min_value;this.add_resize_handle()};p(k.prototype,L.prototype,{add_resize_handle:function(){var ae=this;var ah=false;var ag=false;var af=$("<div class='track-resize'>");$(ae.container_div).hover(function(){ah=true;af.show()},function(){ah=false;if(!ag){af.hide()}});af.hide().bind("dragstart",function(ai,aj){ag=true;aj.original_height=$(ae.content_div).height()}).bind("drag",function(aj,ak){var ai=Math.min(Math.max(ak.original_height+ak.deltaY,ae.min_height_px),ae.max_height_px);$(ae.content_div).css("height",ai);ae.height_px=ai;ae.request_draw(true)}).bind("dragend",function(ai,aj){ae.tile_cache.clear();ag=false;if(!ah){af.hide()}ae.track_config.values.height=ae.height_px}).appendTo(ae.container_div)},predraw_init:function(){var ae=this,af=ae.view.tracks.indexOf(ae);ae.vertical_range=undefined;return $.getJSON(ae.data_url,{stats:true,chrom:ae.view.chrom,low:null,high:null,hda_ldda:ae.hda_ldda,dataset_id:ae.dataset_id},function(ag){ae.container_div.addClass("line-track");var ai=ag.data;if(isNaN(parseFloat(ae.prefs.min_value))||isNaN(parseFloat(ae.prefs.max_value))){ae.prefs.min_value=ai.min;ae.prefs.max_value=ai.max;$("#track_"+af+"_minval").val(ae.prefs.min_value);$("#track_"+af+"_maxval").val(ae.prefs.max_value)}ae.vertical_range=ae.prefs.max_value-ae.prefs.min_value;ae.total_frequency=ai.total_frequency;ae.container_div.find(".yaxislabel").remove();var aj=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+af+"_minval").text(w(ae.prefs.min_value));var ah=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+af+"_maxval").text(w(ae.prefs.max_value));ah.css({position:"absolute",top:"24px",left:"10px"});ah.prependTo(ae.container_div);aj.css({position:"absolute",bottom:"2px",left:"10px"});aj.prependTo(ae.container_div)})},draw_tile:function(aq,aj,ai,ag,ap){if(this.vertical_range===undefined){return}var ae=this._get_tile_bounds(ag,ai),ak=ae[0],ao=ae[1],af=Math.ceil((ao-ak)*ap),am=this.height_px;var ah=this.view.canvas_manager.new_canvas();ah.width=af,ah.height=am;var an=ah.getContext("2d");var al=new K.LinePainter(aq.data,ak,ao,this.prefs,aj);al.draw(an,af,am);return new b(ag,ai,ah,aq.data)}});var e=function(ae,aj,ai,am,al,ag,ah,ak){var af=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];this.track_config=new Y({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ae},{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:al,onchange:function(){af.set_name(af.prefs.name);af.tile_cache.clear();af.request_draw()}});this.prefs=this.track_config.values;j.call(this,ae,aj,aj.viewport_container);L.call(this,ag,ah,ak);this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=ai;this.dataset_id=am;this.original_dataset_id=am;this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.inc_slots={};this.start_end_dct={};this.tile_cache=new c(d);this.data_manager=new Q(20,this);this.left_offset=200;this.painter=K.LinkedFeaturePainter};p(e.prototype,L.prototype,{postdraw_actions:function(au,ae,av,at){L.prototype.postdraw_actions.call(this,au,at);var ah=this;if(at){var aj=ah.content_div.children();var ak=false;for(var ai=aj.length-1,ao=0;ai>=ao;ai--){var ag=$(aj[ai]);if(ak){ag.remove()}else{if(ag.children().length!==0){ak=true}}}}if(ah.mode=="Histogram"){var an=-1;for(var ai=0;ai<au.length;ai++){var ar=au[ai].max_val;if(ar>an){an=ar}}for(var ai=0;ai<au.length;ai++){var aq=au[ai];if(aq.max_val!==an){aq.canvas.remove();ah.draw_helper(true,ae,aq.index,aq.resolution,aq.canvas.parent(),av,[],{max:an})}}}if(ah.filters_manager){var af=ah.filters_manager.filters;for(var am=0;am<af.length;am++){af[am].update_ui_elt()}var al=false,ap;for(var ai=0;ai<au.length;ai++){if(au[ai].data.length){ap=au[ai].data[0];for(var am=0;am<af.length;am++){if(af[am].applies_to(ap)){al=true;break}}}}if(ah.filters_available!==al){ah.filters_available=al;if(!ah.filters_available){ah.filters_div.hide()}ah.make_name_popup_menu()}}},update_auto_mode:function(ae){if(this.mode=="Auto"){if(ae=="no_detail"){ae="feature spans"}else{if(ae=="summary_tree"){ae="coverage histogram"}}this.mode_div.text("Auto ("+ae+")")}},incremental_slots:function(ai,af,ah){var ag=this.view.canvas_manager.dummy_context,ae=this.inc_slots[ai];if(!ae||(ae.mode!==ah)){ae=new (r.FeatureSlotter)(ai,ah==="Pack",z,function(aj){return ag.measureText(aj)});ae.mode=ah;this.inc_slots[ai]=ae}return ae.slot_features(af)},get_summary_tree_data:function(ai,al,ag,au){if(au>ag-al){au=ag-al}var ap=Math.floor((ag-al)/au),at=[],ah=0;var aj=0,ak=0,ao,ar=0,am=[],aq,an;var af=function(ax,aw,ay,av){ax[0]=aw+ay*av;ax[1]=aw+(ay+1)*av};while(ar<au&&aj!==ai.length){var ae=false;for(;ar<au&&!ae;ar++){af(am,al,ar,ap);for(ak=aj;ak<ai.length;ak++){ao=ai[ak].slice(1,3);if(is_overlap(ao,am)){ae=true;break}}if(ae){break}}data_start_index=ak;at[at.length]=aq=[am[0],0];for(;ak<ai.length;ak++){ao=ai[ak].slice(1,3);if(is_overlap(ao,am)){aq[1]++}else{break}}if(aq[1]>ah){ah=aq[1]}ar++}return{max:ah,delta:ap,data:at}},draw_tile:function(at,aw,aB,aF,ao,ah){var ay=this,aj=ay._get_tile_bounds(aF,aB),aH=aj[0],af=aj[1],av=af-aH,az=Math.ceil(av*ao),aL=25,ai=this.left_offset,au,ak;if(aw==="Auto"){if(at.dataset_type==="summary_tree"){aw=at.dataset_type}else{if(at.extra_info==="no_detail"){aw="no_detail"}else{var aK=at.data;if(this.view.high-this.view.low>H){aw="Squish"}else{aw="Pack"}}}this.update_auto_mode(aw)}if(aw==="summary_tree"||aw==="Histogram"){ak=this.summary_draw_height;this.container_div.find(".yaxislabel").remove();var ae=$("<div />").addClass("yaxislabel");ae.text(at.max);ae.css({position:"absolute",top:"24px",left:"10px",color:this.prefs.label_color});ae.prependTo(this.container_div);var ag=this.view.canvas_manager.new_canvas();ag.width=az+ai;ag.height=ak+R;if(at.dataset_type!="summary_tree"){var ap=this.get_summary_tree_data(at.data,aH,af,200);if(at.max){ap.max=at.max}at=ap}var aI=new K.SummaryTreePainter(at,aH,af,this.prefs);var aA=ag.getContext("2d");aA.translate(ai,R);aI.draw(aA,az,ak);return new l(aF,aB,ag,at.data,at.max)}var au,am=1;if(aw==="no_detail"||aw==="Squish"||aw==="Pack"){am=this.incremental_slots(ao,at.data,aw);au=this.inc_slots[ao].slots}var an=[];if(at.data){var aq=this.filters_manager.filters;for(var aC=0,aE=at.data.length;aC<aE;aC++){var al=at.data[aC];var aD=false;var ar;for(var aG=0,aJ=aq.length;aG<aJ;aG++){ar=aq[aG];ar.update_attrs(al);if(!ar.keep(al)){aD=true;break}}if(!aD){an.push(al)}}}var ax=(this.filters_manager.alpha_filter?new N(this.filters_manager.alpha_filter):null);var aI=new (this.painter)(an,aH,af,this.prefs,aw,ax,ah);var ak=Math.max(ac,aI.get_required_height(am));var ag=this.view.canvas_manager.new_canvas();ag.width=az+ai;ag.height=ak;var aA=ag.getContext("2d");aA.fillStyle=this.prefs.block_color;aA.font=aA.canvas.manager.default_font;aA.textAlign="right";this.container_div.find(".yaxislabel").remove();if(at.data){aA.translate(ai,0);aI.draw(aA,az,ak,au)}return new O(aF,aB,ag,at.data,at.message)}});var S=function(ah,af,aj,ae,ag,ai){e.call(this,ah,af,aj,ae,ag,ai);this.painter=K.VariantPainter};p(S.prototype,L.prototype,e.prototype);var V=function(ah,af,aj,ae,ag,ai){e.call(this,ah,af,aj,ae,ag,ai);this.track_config=new Y({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ah},{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ag,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.track_config.values;this.painter=K.ReadPainter;this.make_name_popup_menu()};p(V.prototype,L.prototype,e.prototype);var T=function(ai,ag,ak,ae,ah,aj,af){e.call(this,ai,ag,ak,ae,ah,aj,{},af);this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};p(T.prototype,L.prototype,e.prototype,{predraw_init:function(){var af=this;var ae=function(){if(af.data_manager.size()===0){setTimeout(ae,300)}else{af.data_url=default_data_url;af.data_query_wait=J;af.dataset_state_url=converted_datasets_state_url;$.getJSON(af.dataset_state_url,{dataset_id:af.dataset_id,hda_ldda:af.hda_ldda},function(ag){})}};ae()}});W.View=ab;W.DrawableCollection=y;W.LineTrack=k;W.FeatureTrack=e;W.ReadTrack=V};var slotting_module=function(c,b){var e=c("class").extend;var d=2,a=5;b.FeatureSlotter=function(j,h,f,g){this.slots={};this.start_end_dct={};this.w_scale=j;this.include_label=h;this.max_rows=f;this.measureText=g};e(b.FeatureSlotter.prototype,{slot_features:function(m){var p=this.w_scale,s=this.slots,h=this.start_end_dct,y=[],A=[],n=0,z=this.max_rows;for(var w=0,x=m.length;w<x;w++){var l=m[w],o=l[0];if(s[o]!==undefined){n=Math.max(n,s[o]);A.push(s[o])}else{y.push(w)}}var q=function(G,H){for(var F=0;F<=z;F++){var D=false,I=h[F];if(I!==undefined){for(var C=0,E=I.length;C<E;C++){var B=I[C];if(H>B[0]&&G<B[1]){D=true;break}}}if(!D){return F}}return -1};for(var w=0,x=y.length;w<x;w++){var l=m[y[w]],o=l[0],u=l[1],f=l[2],r=l[3],g=Math.floor(u*p),k=Math.ceil(f*p),v=this.measureText(r).width,j;if(r!==undefined&&this.include_label){v+=(d+a);if(g-v>=0){g-=v;j="left"}else{k+=v;j="right"}}var t=q(g,k);if(t>=0){if(h[t]===undefined){h[t]=[]}h[t].push([g,k]);s[o]=t;n=Math.max(n,t)}else{}}return n+1}})};var painters_module=function(k,x){var u=k("class").extend;var p=function(I,A,G,z,F,D){if(D===undefined){D=4}var C=z-A;var B=F-G;var E=Math.floor(Math.sqrt(C*C+B*B)/D);var J=C/E;var H=B/E;var y;for(y=0;y<E;y++,A+=J,G+=H){if(y%2!==0){continue}I.fillRect(A,G,D,1)}};var q=function(B,A,z,E){var D=A-E/2,C=A+E/2,F=z-Math.sqrt(E*3/2);B.beginPath();B.moveTo(D,F);B.lineTo(C,F);B.lineTo(A,z);B.lineTo(D,F);B.strokeStyle=this.fillStyle;B.fill();B.stroke();B.closePath()};var g=function(y){this.default_alpha=(y?y:1)};g.prototype.gen_alpha=function(y){return this.default_alpha};var n=function(A,C,y,z,B){this.data=A;this.view_start=C;this.view_end=y;this.prefs=u({},this.default_prefs,z);this.mode=B};n.prototype.default_prefs={};var v=function(A,C,y,z,B){n.call(this,A,C,y,z,B)};v.prototype.default_prefs={show_counts:false};v.prototype.draw=function(M,z,L){var E=this.view_start,O=this.view_end-this.view_start,N=z/O;var J=this.data.data,I=this.data.delta,G=this.data.max,B=L;delta_x_px=Math.ceil(I*N);M.save();for(var C=0,D=J.length;C<D;C++){var H=Math.floor((J[C][0]-E)*N);var F=J[C][1];if(!F){continue}var K=F/G*L;if(F!==0&&K<1){K=1}M.fillStyle=this.prefs.block_color;M.fillRect(H,B-K,delta_x_px,K);var A=4;if(this.prefs.show_counts&&(M.measureText(F).width+A)<delta_x_px){M.fillStyle=this.prefs.label_color;M.textAlign="center";M.fillText(F,H+(delta_x_px/2),10)}}M.restore()};var c=function(y,C,E,F,A){n.call(this,y,C,E,F,A);if(this.prefs.min_value===undefined){var G=Infinity;for(var z=0,B=this.data.length;z<B;z++){G=Math.min(G,this.data[z][1])}this.prefs.min_value=G}if(this.prefs.max_value===undefined){var D=-Infinity;for(var z=0,B=this.data.length;z<B;z++){D=Math.max(D,this.data[z][1])}this.prefs.max_value=D}};c.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};c.prototype.draw=function(N,M,K){var F=false,H=this.prefs.min_value,D=this.prefs.max_value,J=D-H,z=K,A=this.view_start,L=this.view_end-this.view_start,B=M/L,I=this.mode,T=this.data;N.save();var U=Math.round(K+H/J*K);if(I!=="Intensity"){N.fillStyle="#aaa";N.fillRect(0,U,M,1)}N.beginPath();var R,E,C;if(T.length>1){C=Math.ceil((T[1][0]-T[0][0])*B)}else{C=10}for(var O=0,P=T.length;O<P;O++){N.fillStyle=this.prefs.color;R=Math.round((T[O][0]-A)*B);E=T[O][1];var Q=false,G=false;if(E===null){if(F&&I==="Filled"){N.lineTo(R,z)}F=false;continue}if(E<H){G=true;E=H}else{if(E>D){Q=true;E=D}}if(I==="Histogram"){E=Math.round(E/J*z);N.fillRect(R,U,C,-E)}else{if(I==="Intensity"){E=255-Math.floor((E-H)/J*255);N.fillStyle="rgb("+E+","+E+","+E+")";N.fillRect(R,0,C,z)}else{E=Math.round(z-(E-H)/J*z);if(F){N.lineTo(R,E)}else{F=true;if(I==="Filled"){N.moveTo(R,z);N.lineTo(R,E)}else{N.moveTo(R,E)}}}}N.fillStyle=this.prefs.overflow_color;if(Q||G){var S;if(I==="Histogram"||I==="Intensity"){S=C}else{R-=2;S=4}if(Q){N.fillRect(R,0,S,3)}if(G){N.fillRect(R,z-3,S,3)}}N.fillStyle=this.prefs.color}if(I==="Filled"){if(F){N.lineTo(R,U);N.lineTo(0,U)}N.fill()}else{N.stroke()}N.restore()};var o=function(B,D,y,A,C,z){n.call(this,B,D,y,A,C);this.alpha_generator=(z?z:new g())};o.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};u(o.prototype,{get_required_height:function(z){var y=y_scale=this.get_row_height(),A=this.mode;if(A==="no_detail"||A==="Squish"||A==="Pack"){y=z*y_scale}return y+Math.max(Math.round(y_scale/2),5)},draw:function(K,B,J,G){var E=this.data,H=this.view_start,L=this.view_end;K.save();K.fillStyle=this.prefs.block_color;K.textAlign="right";var O=this.view_end-this.view_start,N=B/O,A=this.get_row_height();for(var D=0,F=E.length;D<F;D++){var M=E[D],C=M[0],y=M[1],z=M[2],I=(G&&G[C]!==undefined?G[C]:null);if((y<L&&z>H)&&(this.mode=="Dense"||I!==null)){this.draw_element(K,this.mode,M,I,H,L,N,A,B)}}K.restore()},draw_element:function(E,A,G,C,B,D,F,z,y){console.log("WARNING: Unimplemented function.")}});var d=10,j=3,m=5,w=10,f=1,s=3,e=3,a=9,l=2,h="#ccc";var r=function(B,D,y,A,C,z){o.call(this,B,D,y,A,C,z)};u(r.prototype,o.prototype,{get_row_height:function(){var z=this.mode,y;if(z==="Dense"){y=d}else{if(z==="no_detail"){y=j}else{if(z==="Squish"){y=m}else{y=w}}}return y},draw_element:function(K,D,S,F,M,ac,ag,ah,y){var P=S[0],ae=S[1],W=S[2],N=S[3],X=Math.floor(Math.max(0,(ae-M)*ag)),L=Math.ceil(Math.min(y,Math.max(0,(W-M)*ag))),V=(D==="Dense"?0:(0+F))*ah,J,aa,O=null,ai=null,B=this.prefs.block_color,Z=this.prefs.label_color;K.globalAlpha=this.alpha_generator.gen_alpha(S);if(D=="Dense"){F=1}if(D==="no_detail"){K.fillStyle=B;K.fillRect(X,V+5,L-X,f)}else{var I=S[4],U=S[5],Y=S[6],C=S[7];if(U&&Y){O=Math.floor(Math.max(0,(U-M)*ag));ai=Math.ceil(Math.min(y,Math.max(0,(Y-M)*ag)))}var af,Q;if(D==="Squish"||D==="Dense"){af=1;Q=e}else{af=5;Q=a}if(!C){if(S.strand){if(S.strand==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand_inv")}else{if(S.strand==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand_inv")}}}else{K.fillStyle=B}K.fillRect(X,V,L-X,Q)}else{var H,R;if(D==="Squish"||D==="Dense"){K.fillStyle=h;H=V+Math.floor(e/2)+1;R=1}else{if(I){var H=V;var R=Q;if(I==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand")}else{if(I==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand")}}}else{K.fillStyle=h;H+=(e/2)+1;R=1}}K.fillRect(X,H,L-X,R);for(var ad=0,A=C.length;ad<A;ad++){var E=C[ad],z=Math.floor(Math.max(0,(E[0]-M)*ag)),T=Math.ceil(Math.min(y,Math.max((E[1]-M)*ag)));if(z>T){continue}K.fillStyle=B;K.fillRect(z,V+(Q-af)/2+1,T-z,af);if(O!==undefined&&Y>U&&!(z>ai||T<O)){var ab=Math.max(z,O),G=Math.min(T,ai);K.fillRect(ab,V+1,G-ab,Q);if(C.length==1&&D=="Pack"){if(I==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand_inv")}else{if(I==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand_inv")}}if(ab+14<G){ab+=2;G-=2}K.fillRect(ab,V+1,G-ab,Q)}}}}if(D==="Pack"&&ae>M){K.fillStyle=Z;if(M===0&&X-K.measureText(N).width<0){K.textAlign="left";K.fillText(N,L+l,V+8)}else{K.textAlign="right";K.fillText(N,X-l,V+8)}}}K.globalAlpha=1}});var b=function(B,D,y,A,C,z){o.call(this,B,D,y,A,C,z)};u(b.prototype,o.prototype,{draw_element:function(R,M,G,C,U,A,J,S,P){var G=data[i],I=G[0],Q=G[1],B=G[2],L=G[3],E=Math.floor(Math.max(0,(Q-U)*J)),H=Math.ceil(Math.min(P,Math.max(0,(B-U)*J))),D=(M==="Dense"?0:(0+C))*S,y,V,z=null,K=null;if(no_label){R.fillStyle=block_color;R.fillRect(E+left_offset,D+5,H-E,1)}else{var T=G[4],O=G[5],F=G[6];y=9;V=1;R.fillRect(E+left_offset,D,H-E,y);if(M!=="Dense"&&L!==undefined&&Q>U){R.fillStyle=label_color;if(U===0&&E-R.measureText(L).width<0){R.textAlign="left";R.fillText(L,H+2+left_offset,D+8)}else{R.textAlign="right";R.fillText(L,E-2+left_offset,D+8)}R.fillStyle=block_color}var N=T+" / "+O;if(Q>U&&R.measureText(N).width<(H-E)){R.fillStyle="white";R.textAlign="center";R.fillText(N,left_offset+E+(H-E)/2,D+8);R.fillStyle=block_color}}}});var t=function(C,E,y,B,D,z,A){o.call(this,C,E,y,B,D,z);this.ref_seq=A};t.prototype.default_prefs=u({},o.prototype.default_prefs,{show_insertions:false});u(t.prototype,o.prototype,{get_row_height:function(){var y,z=this.mode;if(z==="Dense"){y=d}else{if(z==="Squish"){y=m}else{y=w;if(this.prefs.show_insertions){y*=2}}}return y},draw_read:function(U,P,L,Z,A,T,I,F,E){U.textAlign="center";var S=this,z=[Z,A],O=0,V=0,R=0;ref_seq=this.ref_seq,char_width_px=U.canvas.manager.char_width_px;var ae=[];if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){R=Math.round(L/2)}if(!I){I=[[0,F.length]]}for(var M=0,X=I.length;M<X;M++){var J=I[M],B="MIDNSHP=X"[J[0]],N=J[1];if(B==="H"||B==="S"){O-=N}var G=T+O,ad=Math.floor(Math.max(0,(G-Z)*L)),H=Math.floor(Math.max(0,(G+N-Z)*L));if(ad===H){H+=1}switch(B){case"H":break;case"S":case"M":case"=":if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(R>0){U.fillStyle=this.prefs.block_color;U.fillRect(ad-R,E+1,H-ad,9);U.fillStyle=h;for(var ab=0,y=Q.length;ab<y;ab++){if(this.prefs.show_differences&&ref_seq){var K=ref_seq[G-Z+ab];if(!K||K.toLowerCase()===Q[ab].toLowerCase()){continue}}if(G+ab>=Z&&G+ab<=A){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac,E+9)}}}else{U.fillStyle=this.prefs.block_color;U.fillRect(ad,E+4,H-ad,e)}}V+=N;O+=N;break;case"N":U.fillStyle=h;U.fillRect(ad-R,E+5,H-ad,1);O+=N;break;case"D":U.fillStyle="red";U.fillRect(ad-R,E+4,H-ad,3);O+=N;break;case"P":break;case"I":var Y=ad-R;if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(this.prefs.show_insertions){var D=ad-(H-ad)/2;if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){U.fillStyle="yellow";U.fillRect(D-R,E-9,H-ad,9);ae[ae.length]={type:"triangle",data:[Y,E+4,5]};U.fillStyle=h;switch(seq_tile_overlap){case (OVERLAP_START):Q=Q.slice(Z-G);break;case (OVERLAP_END):Q=Q.slice(0,G-A);break;case (CONTAINED_BY):break;case (CONTAINS):Q=Q.slice(Z-G,G-A);break}for(var ab=0,y=Q.length;ab<y;ab++){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac-(H-ad)/2,E)}}else{U.fillStyle="yellow";U.fillRect(D,E+(this.mode!=="Dense"?2:5),H-ad,(P!=="Dense"?e:s))}}else{if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){ae[ae.length]={type:"text",data:[Q.length,Y,E+9]}}else{}}}V+=N;break;case"X":V+=N;break}}U.fillStyle="yellow";var aa,C,af;for(var W=0;W<ae.length;W++){aa=ae[W];C=aa.type;af=aa.data;if(C==="text"){U.save();U.font="bold "+U.font;U.fillText(af[0],af[1],af[2]);U.restore()}else{if(C=="triangle"){q(U,af[0],af[1],af[2])}}}},draw_element:function(R,M,E,B,U,z,I,S,P){var H=E[0],Q=E[1],A=E[2],J=E[3],D=Math.floor(Math.max(0,(Q-U)*I)),F=Math.ceil(Math.min(P,Math.max(0,(A-U)*I))),C=(M==="Dense"?0:(0+B))*S,V=this.prefs.block_color,G=this.prefs.label_color,O=0;if((M==="Pack"||this.mode==="Auto")&&I>R.canvas.manager.char_width_px){var O=Math.round(I/2)}R.fillStyle=V;if(E[5] instanceof Array){var N=Math.floor(Math.max(0,(E[4][0]-U)*I)),L=Math.ceil(Math.min(P,Math.max(0,(E[4][1]-U)*I))),K=Math.floor(Math.max(0,(E[5][0]-U)*I)),y=Math.ceil(Math.min(P,Math.max(0,(E[5][1]-U)*I)));if(E[4][1]>=U&&E[4][0]<=z&&E[4][2]){this.draw_read(R,M,I,U,z,E[4][0],E[4][2],E[4][3],C)}if(E[5][1]>=U&&E[5][0]<=z&&E[5][2]){this.draw_read(R,M,I,U,z,E[5][0],E[5][2],E[5][3],C)}if(K>L){R.fillStyle=h;p(R,L-O,C+5,K-O,C+5)}}else{R.fillStyle=V;this.draw_read(R,M,I,U,z,Q,E[4],E[5],C)}if(M==="Pack"&&Q>U){R.fillStyle=this.prefs.label_color;var T=1;if(T===0&&D-R.measureText(J).width<0){R.textAlign="left";R.fillText(J,F+l-O,C+8)}else{R.textAlign="right";R.fillText(J,D-l-O,C+8)}R.fillStyle=V}}});x.AlphaGenerator=g;x.SummaryTreePainter=v;x.LinePainter=c;x.LinkedFeaturePainter=r;x.ReadPainter=t;x.VariantPainter=b};(function(d){var c={};var b=function(e){return c[e]};var a=function(f,g){var e={};g(b,e);c[f]=e};a("class",class_module);a("slotting",slotting_module);a("painters",painters_module);a("trackster",trackster_module);for(key in c.trackster){d[key]=c.trackster[key]}})(window);
\ No newline at end of file
+var class_module=function(b,a){var c=function(){var f=arguments[0];for(var e=1;e<arguments.length;e++){var d=arguments[e];for(key in d){f[key]=d[key]}}return f};a.extend=c};var requestAnimationFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b,a){window.setTimeout(b,1000/60)}})();var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=BEFORE}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var trackster_module=function(f,Z){var q=f("class").extend,t=f("slotting"),M=f("painters");var ag=function(ah,ai){this.document=ah;this.default_font=ai!==undefined?ai:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};q(ag.prototype,{load_pattern:function(ah,al){var ai=this.patterns,aj=this.dummy_context,ak=new Image();ak.src=image_path+al;ak.onload=function(){ai[ah]=aj.createPattern(ak,"repeat")}},get_pattern:function(ah){return this.patterns[ah]},new_canvas:function(){var ah=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(ah)}ah.manager=this;return ah}});var o={};var m=function(ah,ai){o[ah.attr("id")]=ai};var n=function(ah,aj,al,ak){al=".group";var ai={};o[ah.attr("id")]=ak;ah.bind("drag",{handle:"."+aj,relative:true},function(au,av){var at=$(this);var ay=$(this).parent(),ap=ay.children(),ar=o[$(this).attr("id")],ao,an,aw,am,aq;an=$(this).parents(al);if(an.length!==0){aw=an.position().top;am=aw+an.outerHeight();if(av.offsetY<aw){$(this).insertBefore(an);var ax=o[an.attr("id")];ax.remove_drawable(ar);ax.container.add_drawable_before(ar,ax);return}else{if(av.offsetY>am){$(this).insertAfter(an);var ax=o[an.attr("id")];ax.remove_drawable(ar);ax.container.add_drawable(ar);return}}}an=null;for(aq=0;aq<ap.length;aq++){ao=$(ap.get(aq));aw=ao.position().top;am=aw+ao.outerHeight();if(ao.is(al)&&this!==ao.get(0)&&av.offsetY>=aw&&av.offsetY<=am){if(av.offsetY-aw<am-av.offsetY){ao.find(".content-div").prepend(this)}else{ao.find(".content-div").append(this)}ar.container.remove_drawable(ar);o[ao.attr("id")].add_drawable(ar);return}}for(aq=0;aq<ap.length;aq++){if(av.offsetY<$(ap.get(aq)).position().top){break}}if(aq===ap.length){if(this!==ap.get(aq-1)){ay.append(this);o[ay.attr("id")].move_drawable(ar,aq)}}else{if(this!==ap.get(aq)){$(this).insertBefore(ap.get(aq));o[ay.attr("id")].move_drawable(ar,(av.deltaY>0?aq-1:aq))}}}).bind("dragstart",function(){ai["border-top"]=ah.css("border-top");ai["border-bottom"]=ah.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ai)})};Z.moveable=n;var af=16,H=9,F=20,U=H+2,B=100,J=12000,S=200,E=5,w=10,L=5000,x=100,p="There was an error in indexing this dataset. ",K="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",G="No data for this chrom/contig.",u="Currently indexing... please wait",z="Tool cannot be rerun: ",a="Loading data...",aa="Ready for display",d=10,v=5,D=5;function y(ah){return Math.round(ah*1000)/1000}var c=function(ah){this.num_elements=ah;this.clear()};q(c.prototype,{get:function(ai){var ah=this.key_ary.indexOf(ai);if(ah!==-1){if(this.obj_cache[ai].stale){this.key_ary.splice(ah,1);delete this.obj_cache[ai]}else{this.move_key_to_end(ai,ah)}}return this.obj_cache[ai]},set:function(ai,aj){if(!this.obj_cache[ai]){if(this.key_ary.length>=this.num_elements){var ah=this.key_ary.shift();delete this.obj_cache[ah]}this.key_ary.push(ai)}this.obj_cache[ai]=aj;return aj},move_key_to_end:function(ai,ah){this.key_ary.splice(ah,1);this.key_ary.push(ai)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var T=function(ai,ah,aj){c.call(this,ai);this.track=ah;this.subset=(aj!==undefined?aj:true)};q(T.prototype,c.prototype,{load_data:function(aq,al,ao,ai,an){var ap=this.track.view.chrom,ak={chrom:ap,low:aq,high:al,mode:ao,resolution:ai,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(ak,an);if(this.track.filters_manager){var ar=[];var ah=this.track.filters_manager.filters;for(var am=0;am<ah.length;am++){ar[ar.length]=ah[am].name}ak.filter_cols=JSON.stringify(ar)}var aj=this;return $.getJSON(this.track.data_url,ak,function(at){aj.set_data(aq,al,ao,at)})},get_data:function(ah,al,am,ai,ak){var aj=this.get_data_from_cache(ah,al,am);if(aj){return aj}aj=this.load_data(ah,al,am,ai,ak);this.set_data(ah,al,am,aj);return aj},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(ap,ak,ao,aj,an,al){var aq=this.get_data_from_cache(ap,ak,ao);if(!aq){console.log("ERROR: no current data for: ",this.track,ap,ak,ao,aj,an);return}aq.stale=true;var ai=ap;if(al===this.DEEP_DATA_REQ){$.extend(an,{start_val:aq.data.length+1})}else{if(al===this.BROAD_DATA_REQ){ai=(aq.max_high?aq.max_high:aq.data[aq.data.length-1][2])+1}}var ah=this,am=this.load_data(ai,ak,ao,aj,an);new_data_available=$.Deferred();this.set_data(ap,ak,ao,new_data_available);$.when(am).then(function(ar){if(ar.data){ar.data=aq.data.concat(ar.data);if(ar.max_low){ar.max_low=aq.max_low}if(ar.message){ar.message=ar.message.replace(/[0-9]+/,ar.data.length)}}ah.set_data(ap,ak,ao,ar);new_data_available.resolve(ar)});return new_data_available},get_data_from_cache:function(ah,ai,aj){return this.get(this.gen_key(ah,ai,aj))},set_data:function(ai,aj,ak,ah){return this.set(this.gen_key(ai,aj,ak),ah)},gen_key:function(ah,aj,ak){var ai=ah+"_"+aj+"_"+ak;return ai},split_key:function(ah){return ah.split("_")}});var I=function(ai,ah,aj){T.call(this,ai,ah,aj)};q(I.prototype,T.prototype,c.prototype,{load_data:function(aj,ah,al,am,ai,ak){if(ai>1){return}return T.prototype.load_data.call(this,aj,ah,al,am,ai,ak)}});var r=function(aj,ai,ak,ah){this.name=aj;this.view=ai;this.parent_element=ak;this.container=ah};r.prototype.request_draw=function(){};r.prototype.draw=function(){};var A=function(aj,ai,ak,ah){r.call(this,aj,ai,ak,ah);this.drawables=[]};q(A.prototype,r.prototype,{to_json:function(){var ai=[];for(var ah=0;ah<this.drawables.length;ah++){}},add_drawable:function(ah){this.drawables.push(ah);ah.container=this},add_drawable_before:function(aj,ah){var ai=this.drawables.indexOf(ah);if(ai!=-1){this.drawables.splice(ai,0,aj);return true}return false},remove_drawable:function(ai){var ah=this.drawables.indexOf(ai);if(ah!=-1){this.drawables.splice(ah,1);ai.container=null;return true}return false},move_drawable:function(ai,aj){var ah=this.drawables.indexOf(ai);if(ah!=-1){this.drawables.splice(ah,1);this.drawables.splice(aj,0,ai);return true}return false}});var R=function(aj,ai,ak,ah){A.call(this,aj,ai,ak,ah);this.drag_handle_class="group-handle";this.container_div=$("<div/>").addClass("group").appendTo(this.parent_element);this.container_div.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("group-name").text(this.name).appendTo(this.container_div);this.content_div=$("<div/>").addClass("content-div").appendTo(this.container_div);m(this.container_div,this)};q(R.prototype,A.prototype,r.prototype);var ae=function(ah,ak,aj,ai,al){A.call(this);this.container=ah;this.chrom=null;this.vis_id=aj;this.dbkey=ai;this.title=ak;this.tracks=this.drawables;this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init(al);this.canvas_manager=new ag(ah.get(0).ownerDocument);this.reset()};q(ae.prototype,A.prototype,{init:function(al){var aj=this.container,ah=this;this.top_container=$("<div/>").addClass("top-container").appendTo(aj);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(aj);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(aj);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.content_div);m(this.viewport_container,ah);this.intro_div=$("<div/>").addClass("intro");var ak=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_tracks()});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ai=function(am){if(am.type==="focusout"||(am.keyCode||am.which)===13||(am.keyCode||am.which)===27){if((am.keyCode||am.which)!==27){ah.go_to($(this).val())}$(this).hide();$(this).val("");ah.location_span.show();ah.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ai).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.click(function(){ah.location_span.hide();ah.chrom_select.hide();ah.nav_input.val(ah.chrom+":"+ah.low+"-"+ah.high);ah.nav_input.css("display","inline-block");ah.nav_input.select();ah.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a id='zoom-out' />").click(function(){ah.zoom_out();ah.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){ah.zoom_in();ah.request_redraw()}).appendTo(this.nav_controls);this.load_chroms({low:0},al);this.chrom_select.bind("change",function(){ah.change_chrom(ah.chrom_select.val())});this.content_div.click(function(am){$(this).find("input").trigger("blur")});this.content_div.bind("dblclick",function(am){ah.zoom_in(am.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(am,an){this.current_x=an.offsetX}).bind("drag",function(am,ao){var ap=ao.offsetX-this.current_x;this.current_x=ao.offsetX;var an=Math.round(ap/ah.viewport_container.width()*(ah.max_high-ah.max_low));ah.move_delta(-an)});this.overview_close.click(function(){ah.reset_overview()});this.viewport_container.bind("draginit",function(am,an){if(am.clientX>ah.viewport_container.width()-16){return false}}).bind("dragstart",function(am,an){an.original_low=ah.low;an.current_height=am.clientY;an.current_x=an.offsetX}).bind("drag",function(ao,aq){var am=$(this);var ar=aq.offsetX-aq.current_x;var an=am.scrollTop()-(ao.clientY-aq.current_height);am.scrollTop(an);aq.current_height=ao.clientY;aq.current_x=aq.offsetX;var ap=Math.round(ar/ah.viewport_container.width()*(ah.high-ah.low));ah.move_delta(ap)}).bind("mousewheel",function(ao,aq,an,am){if(an){var ap=Math.round(-an/ah.viewport_container.width()*(ah.high-ah.low));ah.move_delta(ap)}});this.top_labeltrack.bind("dragstart",function(am,an){return $("<div />").css({height:ah.content_div.height()+ah.top_labeltrack.height()+ah.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(aq,ar){$(ar.proxy).css({left:Math.min(aq.pageX,ar.startX),width:Math.abs(aq.pageX-ar.startX)});var an=Math.min(aq.pageX,ar.startX)-ah.container.offset().left,am=Math.max(aq.pageX,ar.startX)-ah.container.offset().left,ap=(ah.high-ah.low),ao=ah.viewport_container.width();ah.update_location(Math.round(an/ao*ap)+ah.low,Math.round(am/ao*ap)+ah.low)}).bind("dragend",function(ar,at){var an=Math.min(ar.pageX,at.startX),am=Math.max(ar.pageX,at.startX),ap=(ah.high-ah.low),ao=ah.viewport_container.width(),aq=ah.low;ah.low=Math.round(an/ao*ap)+aq;ah.high=Math.round(am/ao*ap)+aq;$(at.proxy).remove();ah.request_redraw()});this.add_label_track(new ad(this,this.top_labeltrack));this.add_label_track(new ad(this,this.nav_labeltrack));$(window).bind("resize",function(){ah.resize_window()});$(document).bind("redraw",function(){ah.redraw()});this.reset();$(window).trigger("resize");this.update_intro_div()},to_json:function(){var ah=this,ai=[];this.viewport_container.children(".track,.group").each(function(){var aj=$(this).attr("id");aj=parseInt(aj.slice(aj.lastIndexOf("_")+1));ai.push(ah.tracks[aj].to_json())});return ai},update_intro_div:function(){if(this.num_tracks===0){this.intro_div.appendTo(this.viewport_container)}else{this.intro_div.remove()}},update_location:function(ah,ai){this.location_span.text(commatize(ah)+" - "+commatize(ai));this.nav_input.val(this.chrom+":"+commatize(ah)+"-"+commatize(ai))},load_chroms:function(ai,aj){ai.num=x;$.extend(ai,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var ah=this;$.ajax({url:chrom_url,data:ai,dataType:"json",success:function(al){if(al.chrom_info.length===0){alert("Invalid chromosome: "+ai.chrom);return}if(al.reference){ah.add_label_track(new C(ah))}ah.chrom_data=al.chrom_info;var ao='<option value="">Select Chrom/Contig</option>';for(var an=0,ak=ah.chrom_data.length;an<ak;an++){var am=ah.chrom_data[an].chrom;ao+='<option value="'+am+'">'+am+"</option>"}if(al.prev_chroms){ao+='<option value="previous">Previous '+x+"</option>"}if(al.next_chroms){ao+='<option value="next">Next '+x+"</option>"}ah.chrom_select.html(ao);if(aj){aj()}ah.chrom_start_index=al.start_index},error:function(){alert("Could not load chroms for this dbkey:",ah.dbkey)}})},change_chrom:function(al,ai,an){if(!al||al==="None"){return}var ak=this;if(al==="previous"){ak.load_chroms({low:this.chrom_start_index-x});return}if(al==="next"){ak.load_chroms({low:this.chrom_start_index+x});return}var am=$.grep(ak.chrom_data,function(ap,aq){return ap.chrom===al})[0];if(am===undefined){ak.load_chroms({chrom:al},function(){ak.change_chrom(al,ai,an)});return}else{if(al!==ak.chrom){ak.chrom=al;ak.chrom_select.val(ak.chrom);ak.max_high=am.len-1;ak.reset();ak.request_redraw(true);for(var ao=0,ah=ak.tracks.length;ao<ah;ao++){var aj=ak.tracks[ao];if(aj.init){aj.init()}}}if(ai!==undefined&&an!==undefined){ak.low=Math.max(ai,0);ak.high=Math.min(an,ak.max_high)}ak.reset_overview();ak.request_redraw()}},go_to:function(al){var ap=this,ah,ak,ai=al.split(":"),an=ai[0],ao=ai[1];if(ao!==undefined){try{var am=ao.split("-");ah=parseInt(am[0].replace(/,/g,""),10);ak=parseInt(am[1].replace(/,/g,""),10)}catch(aj){return false}}ap.change_chrom(an,ah,ak)},move_fraction:function(aj){var ah=this;var ai=ah.high-ah.low;this.move_delta(aj*ai)},move_delta:function(aj){var ah=this;var ai=ah.high-ah.low;if(ah.low-aj<ah.max_low){ah.low=ah.max_low;ah.high=ah.max_low+ai}else{if(ah.high-aj>ah.max_high){ah.high=ah.max_high;ah.low=ah.max_high-ai}else{ah.high-=aj;ah.low-=aj}}ah.request_redraw()},add_track:function(ah){ah.view=this;ah.track_id=this.track_id_counter;this.tracks.push(ah);if(ah.init){ah.init()}ah.container_div.attr("id","track_"+ah.track_id);n(ah.container_div,ah.drag_handle_class,".group",ah);this.track_id_counter+=1;this.num_tracks+=1;this.has_changes=true;this.update_intro_div()},add_label_track:function(ah){ah.view=this;this.label_tracks.push(ah)},remove_track:function(ai){this.has_changes=true;this.tracks.splice(this.tracks.indexOf(ai),1);this.num_tracks-=1;var ah=this;ai.container_div.fadeOut("slow",function(){$(this).remove();ah.update_intro_div()})},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ap,ah,ao,ai){var an=this,al=(ai?[ai]:an.tracks),aj;var ai;for(var am=0;am<al.length;am++){ai=al[am];aj=-1;for(var ak=0;ak<an.tracks_to_be_redrawn.length;ak++){if(an.tracks_to_be_redrawn[ak][0]===ai){aj=ak;break}}if(aj<0){an.tracks_to_be_redrawn.push([ai,ah,ao])}else{an.tracks_to_be_redrawn[am][1]=ah;an.tracks_to_be_redrawn[am][2]=ao}}requestAnimationFrame(function(){an._redraw(ap)})},_redraw:function(ar){var ao=this.low,ak=this.high;if(ao<this.max_low){ao=this.max_low}if(ak>this.max_high){ak=this.max_high}var aq=this.high-this.low;if(this.high!==0&&aq<this.min_separation){ak=ao+this.min_separation}this.low=Math.floor(ao);this.high=Math.ceil(ak);this.resolution=Math.pow(E,Math.ceil(Math.log((this.high-this.low)/S)/Math.log(E)));this.zoom_res=Math.pow(w,Math.max(0,Math.ceil(Math.log(this.resolution,w)/Math.log(w))));var ah=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var an=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var at=13;this.overview_box.css({left:ah,width:Math.max(at,an)}).show();if(an<at){this.overview_box.css("left",ah-(at-an)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ah,width:an})}this.update_location(this.low,this.high);if(!ar){var aj,ai,ap;for(var al=0,am=this.tracks_to_be_redrawn.length;al<am;al++){aj=this.tracks_to_be_redrawn[al][0];ai=this.tracks_to_be_redrawn[al][1];ap=this.tracks_to_be_redrawn[al][2];if(aj&&aj.enabled){aj._draw(ai,ap)}}this.tracks_to_be_redrawn=[];for(al=0,am=this.label_tracks.length;al<am;al++){this.label_tracks[al]._draw()}}},zoom_in:function(ai,aj){if(this.max_high===0||this.high-this.low<this.min_separation){return}var ak=this.high-this.low,al=ak/2+this.low,ah=(ak/this.zoom_factor)/2;if(ai){al=ai/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(al-ah);this.high=Math.round(al+ah);this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ai=this.high-this.low,aj=ai/2+this.low,ah=(ai*this.zoom_factor)/2;this.low=Math.round(aj-ah);this.high=Math.round(aj+ah);this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.request_redraw()},set_overview:function(ah){$.when(ah.get_overview_tile()).then(function(ai){view.overview_viewport.find(".track-tile").remove();view.overview_close.show();view.overview_viewport.append(ai.canvas);view.overview_highlight.show().height(ai.canvas.height());view.overview_viewport.height(ai.canvas.height()+view.overview_box.outerHeight());view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=ah;ah.set_is_overview(true)});view.has_changes=true},reset_overview:function(){this.overview_viewport.find(".track-tile").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide();view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=null}});var s=function(aj,an){this.track=aj;this.name=an.name;this.params=[];var av=an.params;for(var ak=0;ak<av.length;ak++){var ap=av[ak],ai=ap.name,au=ap.label,al=unescape(ap.html),aw=ap.value,ar=ap.type;if(ar==="number"){this.params[this.params.length]=new g(ai,au,al,aw,ap.min,ap.max)}else{if(ar=="select"){this.params[this.params.length]=new O(ai,au,al,aw)}else{console.log("WARNING: unrecognized tool parameter type:",ai,ar)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(ay){ay.stopPropagation()}).click(function(ay){ay.stopPropagation()}).bind("dblclick",function(ay){ay.stopPropagation()});var at=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var aq=this.params;var ao=this;$.each(this.params,function(az,aC){var aB=$("<div>").addClass("param-row").appendTo(ao.parent_div);var ay=$("<div>").addClass("param-label").text(aC.label).appendTo(aB);var aA=$("<div/>").addClass("slider").html(aC.html).appendTo(aB);aA.find(":input").val(aC.value);$("<div style='clear: both;'/>").appendTo(aB)});this.parent_div.find("input").click(function(){$(this).select()});var ax=$("<div>").addClass("param-row").appendTo(this.parent_div);var am=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(ax);var ah=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(ax);var ao=this;ah.click(function(){var ay=this.track.parent_element,az=new A("New Group",ay);ao.run_on_region()});am.click(function(){ao.run_on_dataset()})};q(s.prototype,{get_param_values_dict:function(){var ah={};this.parent_div.find(":input").each(function(){var ai=$(this).attr("name"),aj=$(this).val();ah[ai]=JSON.stringify(aj)});return ah},get_param_values:function(){var ai=[];var ah={};this.parent_div.find(":input").each(function(){var aj=$(this).attr("name"),ak=$(this).val();if(aj){ai[ai.length]=ak}});return ai},run_on_dataset:function(){var ah=this;ah.run({dataset_id:this.track.original_dataset_id,tool_id:ah.name},null,function(ai){show_modal(ah.name+" is Running",ah.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ah={dataset_id:this.track.original_dataset_id,chrom:this.track.view.chrom,low:this.track.view.low,high:this.track.view.high,tool_id:this.name},aj=this.track,ai=ah.tool_id+aj.tool_region_and_parameters_str(ah.chrom,ah.low,ah.high),ak;if(aj instanceof e){ak=new W(ai,view,aj.hda_ldda,undefined,{},{},aj);ak.change_mode(aj.mode)}this.track.view.add_track(ak);ak.content_div.text("Starting job.");this.run(ah,ak,function(al){ak.dataset_id=al.dataset_id;ak.content_div.text("Running job.");ak.init()})},run:function(ai,aj,ak){$.extend(ai,this.get_param_values_dict());var ah=function(){$.getJSON(rerun_tool_url,ai,function(al){if(al==="no converter"){aj.container_div.addClass("error");aj.content_div.text(K)}else{if(al.error){aj.container_div.addClass("error");aj.content_div.text(z+al.message)}else{if(al==="pending"){aj.container_div.addClass("pending");aj.content_div.text("Converting input data so that it can be used quickly with tool.");setTimeout(ah,2000)}else{ak(al)}}}})};ah()}});var O=function(ai,ah,aj,ak){this.name=ai;this.label=ah;this.html=aj;this.value=ak};var g=function(aj,ai,al,am,ak,ah){O.call(this,aj,ai,al,am);this.min=ak;this.max=ah};var h=function(ai,ah,aj,ak){this.name=ai;this.index=ah;this.tool_id=aj;this.tool_exp_name=ak};var X=function(ai,ah,aj,ak){h.call(this,ai,ah,aj,ak);this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.min=Number.MAX_VALUE;this.max=-Number.MAX_VALUE;this.container=null;this.slider=null;this.slider_label=null};q(X.prototype,{applies_to:function(ah){if(ah.length>this.index){return true}return false},keep:function(ah){if(!this.applies_to(ah)){return true}var ai=parseFloat(ah[this.index]);return(isNaN(ai)||(ai>=this.low&&ai<=this.high))},update_attrs:function(ai){var ah=false;if(!this.applies_to(ai)){return ah}if(ai[this.index]<this.min){this.min=Math.floor(ai[this.index]);ah=true}if(ai[this.index]>this.max){this.max=Math.ceil(ai[this.index]);ah=true}return ah},update_ui_elt:function(){if(this.min!=this.max){this.container.show()}else{this.container.hide()}var aj=function(am,ak){var al=ak-am;return(al<=2?0.01:1)};var ai=this.slider.slider("option","min"),ah=this.slider.slider("option","max");if(this.min<ai||this.max>ah){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",aj(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var ac=function(ar,ay){this.track=ar;this.filters=[];for(var at=0;at<ay.length;at++){var au=ay[at],az=au.name,ah=au.type,ak=au.index,ax=au.tool_id,aw=au.tool_exp_name;if(ah==="int"||ah==="float"){this.filters[at]=new X(az,ak,ax,aw)}else{console.log("ERROR: unsupported filter: ",az,ah)}}var al=function(aA,aB,aC){aA.click(function(){var aD=aB.text();max=parseFloat(aC.slider("option","max")),input_size=(max<=1?4:max<=1000000?max.toString().length:6),multi_value=false;if(aC.slider("option","values")){input_size=2*input_size+1;multi_value=true}aB.text("");$("<input type='text'/>").attr("size",input_size).attr("maxlength",input_size).attr("value",aD).appendTo(aB).focus().select().click(function(aE){aE.stopPropagation()}).blur(function(){$(this).remove();aB.text(aD)}).keyup(function(aI){if(aI.keyCode===27){$(this).trigger("blur")}else{if(aI.keyCode===13){var aG=aC.slider("option","min"),aE=aC.slider("option","max"),aH=function(aJ){return(isNaN(aJ)||aJ>aE||aJ<aG)},aF=$(this).val();if(!multi_value){aF=parseFloat(aF);if(aH(aF)){alert("Parameter value must be in the range ["+aG+"-"+aE+"]");return $(this)}}else{aF=aF.split("-");aF=[parseFloat(aF[0]),parseFloat(aF[1])];if(aH(aF[0])||aH(aF[1])){alert("Parameter value must be in the range ["+aG+"-"+aE+"]");return $(this)}}aC.slider((multi_value?"values":"value"),aF)}}})})};this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(aA){aA.stopPropagation()}).click(function(aA){aA.stopPropagation()}).bind("dblclick",function(aA){aA.stopPropagation()}).bind("keydown",function(aA){aA.stopPropagation()});var av=$("<div/>").addClass("sliders").appendTo(this.parent_div);var ap=this;$.each(this.filters,function(aD,aF){aF.container=$("<div/>").addClass("slider-row").appendTo(av);var aE=$("<div/>").addClass("elt-label").appendTo(aF.container);var aC=$("<span/>").addClass("slider-name").text(aF.name+" ").appendTo(aE);var aB=$("<span/>");var aH=$("<span/>").addClass("slider-value").appendTo(aE).append("[").append(aB).append("]");var aA=$("<div/>").addClass("slider").appendTo(aF.container);aF.control_element=$("<div/>").attr("id",aF.name+"-filter-control").appendTo(aA);var aG=[0,0];aF.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(aJ,aK){var aI=aK.values;aB.text(aI[0]+"-"+aI[1]);aF.low=aI[0];aF.high=aI[1];ap.track.request_draw(true,true)},change:function(aI,aJ){aF.control_element.slider("option","slide").call(aF.control_element,aI,aJ)}});aF.slider=aF.control_element;aF.slider_label=aB;al(aH,aB,aF.control_element);$("<div style='clear: both;'/>").appendTo(aF.container)});if(this.filters.length!==0){var am=$("<div/>").addClass("param-row").appendTo(av);var ao=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(am);var aj=this;ao.click(function(){aj.run_on_dataset()})}var aq=$("<div/>").addClass("display-controls").appendTo(this.parent_div),an=$("<span/>").addClass("elt-label").text("Transparency:").appendTo(aq),ai=$("<select/>").attr("name","alpha_dropdown").appendTo(aq);this.alpha_filter=null;$("<option/>").attr("value",-1).text("== None ==").appendTo(ai);for(var at=0;at<this.filters.length;at++){$("<option/>").attr("value",at).text(this.filters[at].name).appendTo(ai)}ai.change(function(){$(this).children("option:selected").each(function(){var aA=parseInt($(this).val());ap.alpha_filter=(aA>=0?ap.filters[aA]:null);ap.track.request_draw(true,true)})});$("<div style='clear: both;'/>").appendTo(this.parent_div)};q(ac.prototype,{reset_filters:function(){for(var ah=0;ah<this.filters.length;ah++){filter=this.filters[ah];filter.slider.slider("option","values",[filter.min,filter.max])}this.alpha_filter=null},run_on_dataset:function(){var ap=function(au,ar,at){if(!(ar in au)){au[ar]=at}return au[ar]};var aj={},ah,ai,ak;for(var al=0;al<this.filters.length;al++){ah=this.filters[al];if(ah.tool_id){if(ah.min!=ah.low){ai=ap(aj,ah.tool_id,[]);ai[ai.length]=ah.tool_exp_name+" >= "+ah.low}if(ah.max!=ah.high){ai=ap(aj,ah.tool_id,[]);ai[ai.length]=ah.tool_exp_name+" <= "+ah.high}}}var an=[];for(var aq in aj){an[an.length]=[aq,aj[aq]]}var ao=an.length;(function am(ay,av){var at=av[0],au=at[0],ax=at[1],aw="("+ax.join(") and (")+")",ar={cond:aw,input:ay,target_dataset_id:ay,tool_id:au},av=av.slice(1);$.getJSON(run_tool_url,ar,function(az){if(az.error){show_modal("Filter Dataset","Error running tool "+au,{Close:hide_modal})}else{if(av.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{am(az.dataset_id,av)}}})})(this.track.dataset_id,an)}});var P=function(ai,ah){M.AlphaGenerator.call(this,ah);this.filter=ai};P.prototype.gen_alpha=function(ah){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_alpha}return((parseFloat(ah[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var ab=function(ah){this.track=ah.track;this.params=ah.params;this.values={};if(ah.saved_values){this.restore_values(ah.saved_values)}this.onchange=ah.onchange};q(ab.prototype,{restore_values:function(ah){var ai=this;$.each(this.params,function(aj,ak){if(ah[ak.key]!==undefined){ai.values[ak.key]=ah[ak.key]}else{ai.values[ak.key]=ak.default_value}})},build_form:function(){var ai=this;var ah=$("<div />");$.each(this.params,function(am,ak){if(!ak.hidden){var aj="param_"+am;var ao=ai.values[ak.key];var ar=$("<div class='form-row' />").appendTo(ah);ar.append($("<label />").attr("for",aj).text(ak.label+":"));if(ak.type==="bool"){ar.append($('<input type="checkbox" />').attr("id",aj).attr("name",aj).attr("checked",ao))}else{if(ak.type==="text"){ar.append($('<input type="text"/>').attr("id",aj).val(ao).click(function(){$(this).select()}))}else{if(ak.type==="color"){var an=$("<input />").attr("id",aj).attr("name",aj).val(ao);var ap=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var al=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(ap);var aq=$("<div/>").appendTo(al).farbtastic({width:100,height:100,callback:an,color:ao});$("<div />").append(an).append(ap).appendTo(ar).bind("click",function(at){ap.css({left:$(this).position().left+($(an).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){ap.hide();$(document).unbind("click.color-picker")});at.stopPropagation()})}else{ar.append($("<input />").attr("id",aj).attr("name",aj).val(ao))}}}}});return ah},update_from_form:function(ah){var aj=this;var ai=false;$.each(this.params,function(ak,am){if(!am.hidden){var an="param_"+ak;var al=ah.find("#"+an).val();if(am.type==="float"){al=parseFloat(al)}else{if(am.type==="int"){al=parseInt(al)}else{if(am.type==="bool"){al=ah.find("#"+an).is(":checked")}}}if(al!==aj.values[am.key]){aj.values[am.key]=al;ai=true}}});if(ai){this.onchange()}}});var b=function(aj,ai,ah,ak){this.index=aj;this.low=aj*S*ai;this.high=(aj+1)*S*ai;this.resolution=ai;this.canvas=$("<div class='track-tile'/>").append(ah);this.data=ak;this.stale=false};var l=function(aj,ai,ah,ak,al){b.call(this,aj,ai,ah,ak);this.max_val=al};var Q=function(aj,ai,ah,al,ak){b.call(this,aj,ai,ah,al);this.message=ak};var j=function(ai,ah,al,aj,ak){r.call(this,ai,ah,al,ah);this.data_url=(aj?aj:default_data_url);this.data_url_extra_params={};this.data_query_wait=(ak?ak:L);this.dataset_check_url=converted_datasets_state_url;this.drag_handle_class="draghandle";this.container_div=$("<div />").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)};q(j.prototype,{get_type:function(){if(this instanceof ad){return"LabelTrack"}else{if(this instanceof C){return"ReferenceTrack"}else{if(this instanceof k){return"LineTrack"}else{if(this instanceof Y){return"ReadTrack"}else{if(this instanceof W){return"ToolDataFeatureTrack"}else{if(this instanceof V){return"VcfTrack"}else{if(this instanceof e){return"FeatureTrack"}}}}}}}return""},init:function(){var ah=this;ah.enabled=false;ah.tile_cache.clear();ah.data_manager.clear();ah.initial_canvas=undefined;ah.content_div.css("height","auto");ah.container_div.removeClass("nodata error pending");if(!ah.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:ah.hda_ldda,dataset_id:ah.dataset_id,chrom:ah.view.chrom},function(ai){if(!ai||ai==="error"||ai.kind==="error"){ah.container_div.addClass("error");ah.content_div.text(p);if(ai.message){var ak=ah.view.tracks.indexOf(ah);var aj=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ai.message+"</pre>",{Close:hide_modal})});ah.content_div.append(aj)}}else{if(ai==="no converter"){ah.container_div.addClass("error");ah.content_div.text(K)}else{if(ai==="no data"||(ai.data!==undefined&&(ai.data===null||ai.data.length===0))){ah.container_div.addClass("nodata");ah.content_div.text(G)}else{if(ai==="pending"){ah.container_div.addClass("pending");ah.content_div.text(u);setTimeout(function(){ah.init()},ah.data_query_wait)}else{if(ai.status==="data"){if(ai.valid_chroms){ah.valid_chroms=ai.valid_chroms;ah.make_name_popup_menu()}ah.content_div.text(aa);if(ah.view.chrom){ah.content_div.text("");ah.content_div.css("height",ah.height_px+"px");ah.enabled=true;$.when(ah.predraw_init()).done(function(){ah.container_div.removeClass("nodata error pending");ah.request_draw()})}}}}}}})},predraw_init:function(){},set_name:function(ah){this.old_name=this.name;this.name=ah;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)}});var N=function(ao,am,ap){var ai=this,aq=ai.view;this.filters_manager=(ao!==undefined?new ac(this,ao):undefined);this.filters_available=false;this.filters_visible=false;this.tool=(am!==undefined&&obj_length(am)>0?new s(this,am):undefined);this.is_overview=false;if(ai.hidden){return}if(this.filters_manager){this.filters_div=this.filters_manager.parent_div;this.header_div.after(this.filters_div)}if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}if(ai.display_modes!==undefined){if(ai.mode_div===undefined){ai.mode_div=$("<div class='right-float menubutton popup' />").appendTo(ai.header_div);var aj=(ai.track_config&&ai.track_config.values.mode?ai.track_config.values.mode:ai.display_modes[0]);ai.mode=aj;ai.mode_div.text(aj);var ah={};for(var ak=0,an=ai.display_modes.length;ak<an;ak++){var al=ai.display_modes[ak];ah[al]=function(ar){return function(){ai.change_mode(ar)}}(al)}make_popupmenu(ai.mode_div,ah)}else{ai.mode_div.hide()}}this.make_name_popup_menu()};q(N.prototype,j.prototype,{to_json:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs}},change_mode:function(ai){var ah=this;ah.mode_div.text(ai);ah.mode=ai;ah.track_config.values.mode=ai;ah.tile_cache.clear();ah.request_draw()},make_name_popup_menu:function(){var ai=this;var ah={};ah[(this.is_overview?"Hide overview":"Set as overview")]=function(){if(ai.is_overview){ai.view.reset_overview()}else{ai.view.set_overview(ai)}};ah["Edit configuration"]=function(){var am=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ak=function(){ai.track_config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},al=function(an){if((an.keyCode||an.which)===27){am()}else{if((an.keyCode||an.which)===13){ak()}}};$(window).bind("keypress.check_enter_esc",al);show_modal("Configure Track",ai.track_config.build_form(),{Cancel:am,OK:ak})};if(ai.filters_available>0){var aj=(ai.filters_div.is(":visible")?"Hide filters":"Show filters");ah[aj]=function(){ai.filters_visible=(ai.filters_div.is(":visible"));if(ai.filters_visible){ai.filters_manager.reset_filters()}ai.filters_div.toggle();ai.make_name_popup_menu()}}if(ai.tool){var aj=(ai.dynamic_tool_div.is(":visible")?"Hide tool":"Show tool");ah[aj]=function(){if(!ai.dynamic_tool_div.is(":visible")){ai.set_name(ai.name+ai.tool_region_and_parameters_str())}else{menu_option_text="Show dynamic tool";ai.revert_name()}ai.dynamic_tool_div.toggle();ai.make_name_popup_menu()}}if(ai.valid_chroms){ah["List chrom/contigs with data"]=function(){show_modal("Chrom/contigs with data","<p>"+ai.valid_chroms.join("<br/>")+"</p>",{Close:function(){hide_modal()}})}}ah.Remove=function(){view.remove_track(ai);if(parent_obj.num_tracks===0){$("#no-tracks").show()}};make_popupmenu(ai.name_div,ah)},set_is_overview:function(ah){this.is_overview=ah;this.make_name_popup_menu()},get_overview_tile:function(){var ah=this;view=ah.view,resolution=Math.pow(E,Math.ceil(Math.log((view.max_high-view.max_low)/S)/Math.log(E))),view_width=view.container.width(),w_scale=view_width/(view.max_high-view.max_low),overview_tile=$.Deferred();$.when(ah.data_manager.get_data(view.max_low,view.max_high,"Auto",resolution,ah.data_url_extra_params)).then(function(ai){var ak=ah._gen_tile_cache_key(view_width,w_scale,0),am=ah.tile_cache.get(ak);if(!am){am=ah.draw_tile(ai,"Auto",resolution,0,w_scale);ah.tile_cache.set(ak,am)}var ap=$(am.canvas.find("canvas")),al=ap.clone(),ao=ap.get(0).getContext("2d"),aj=al.get(0).getContext("2d"),an=ao.getImageData(0,0,ao.canvas.width,ao.canvas.height);aj.putImageData(an,-ah.left_offset,(am.data.dataset_type==="summary_tree"?U:0));new_tile=new b(-1,resolution,al);overview_tile.resolve(new_tile)});return overview_tile},_gen_tile_cache_key:function(ai,aj,ah){return ai+"_"+aj+"_"+ah},request_draw:function(ai,ah){this.view.request_redraw(false,ai,ah,this)},_draw:function(aj,ar){if(!(this instanceof C)&&(!this.dataset_id)){return}var aq=this.view.low,an=this.view.high,ao=an-aq,ak=this.view.container.width(),av=ak/ao,am=this.view.resolution,au=$("<div style='position: relative;'></div>");if(!ar){this.content_div.children().remove()}this.content_div.append(au);this.max_height=0;var ai=Math.floor(aq/am/S);var ap=true;var at=[];var ah=0;while((ai*S*am)<an){tile=this.draw_helper(aj,ak,ai,am,au,av);if(tile){at.push(tile)}else{ap=false}ai+=1;ah++}var al=this;if(ap){al.postdraw_actions(at,ak,av,ar)}},postdraw_actions:function(al,am,an,ah){var aj=this;var ak=false;for(var ai=0;ai<al.length;ai++){if(al[ai].message){ak=true;break}}if(ak){for(var ai=0;ai<al.length;ai++){tile=al[ai];if(!tile.message){tile.canvas.css("padding-top",F)}}}},draw_helper:function(ai,aj,ak,an,au,ay,av,ao){var al=this,at=this._gen_tile_cache_key(aj,ay,ak),ap=ak*S*an,ax=ap+S*an;var aq=(ai?undefined:al.tile_cache.get(at));if(aq){al.show_tile(aq,au,ay);return aq}var ar=function(az){return("isResolved" in az)};var am=true;var ah=al.data_manager.get_data(ap,ax,al.mode,an,al.data_url_extra_params);if(ar(ah)){am=false}var aw;if(view.reference_track&&ay>view.canvas_manager.char_width_px){aw=view.reference_track.data_manager.get_data(ap,ax,al.mode,an,view.reference_track.data_url_extra_params);if(ar(aw)){am=false}}if(am){q(ah,ao);var aq=al.draw_tile(ah,al.mode,an,ak,ay,aw);al.tile_cache.set(at,aq);if(aq!==undefined){al.show_tile(aq,au,ay)}return aq}$.when(ah,aw).then(function(){view.request_redraw()});return null},show_tile:function(ao,aq,ar){var aj=this,ai=ao.canvas,an=ai;if(ao.message){var at=$("<div/>"),ap=$("<div/>").addClass("tile-message").text(ao.message).css({height:F-1,width:ao.canvas.width}).appendTo(at),al=$("<a href='javascript:void(0);'/>").addClass("icon more-down").appendTo(ap),ah=$("<a href='javascript:void(0);'/>").addClass("icon more-across").appendTo(ap);at.append(ai);an=at;al.click(function(){ao.stale=true;aj.data_manager.get_more_data(ao.low,ao.high,aj.mode,ao.resolution,{},aj.data_manager.DEEP_DATA_REQ);aj.request_draw()}).dblclick(function(au){au.stopPropagation()});ah.click(function(){ao.stale=true;aj.data_manager.get_more_data(ao.low,ao.high,aj.mode,ao.resolution,{},aj.data_manager.BROAD_DATA_REQ);aj.request_draw()}).dblclick(function(au){au.stopPropagation()})}var am=this.view.high-this.view.low,ak=(ao.low-this.view.low)*ar;if(this.left_offset){ak-=this.left_offset}an.css({position:"absolute",top:0,left:ak,height:""});aq.append(an);aj.max_height=Math.max(aj.max_height,an.height());aj.content_div.css("height",aj.max_height+"px");aq.children().css("height",aj.max_height+"px")},_get_tile_bounds:function(ah,ai){var ak=ah*S*ai,al=S*ai,aj=(ak+al<=this.view.max_high?ak+al:this.view.max_high);return[ak,aj]},tool_region_and_parameters_str:function(aj,ah,ak){var ai=this,al=(aj!==undefined&&ah!==undefined&&ak!==undefined?aj+":"+ah+"-"+ak:"all");return" - region=["+al+"], parameters=["+ai.tool.get_param_values().join(", ")+"]"}});var ad=function(ah,ai){this.hidden=true;j.call(this,null,ah,ai);this.container_div.addClass("label-track")};q(ad.prototype,j.prototype,{_draw:function(){var aj=this.view,ak=aj.high-aj.low,an=Math.floor(Math.pow(10,Math.floor(Math.log(ak)/Math.log(10)))),ah=Math.floor(aj.low/an)*an,al=this.view.container.width(),ai=$("<div style='position: relative; height: 1.3em;'></div>");while(ah<aj.high){var am=(ah-aj.low)/ak*al;ai.append($("<div class='label'>"+commatize(ah)+"</div>").css({position:"absolute",left:am-1}));ah+=an}this.content_div.children(":first").remove();this.content_div.append(ai)}});var C=function(ah){this.hidden=true;j.call(this,null,ah,ah.top_labeltrack);N.call(this);ah.reference_track=this;this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url;this.data_url_extra_params={dbkey:ah.dbkey};this.data_manager=new I(D,this,false);this.tile_cache=new c(v)};q(C.prototype,N.prototype,{draw_tile:function(ar,an,am,ai,at){var al=this,aj=S*am;if(at>this.view.canvas_manager.char_width_px){if(ar===null){al.content_div.css("height","0px");return}var ak=this.view.canvas_manager.new_canvas();var aq=ak.getContext("2d");ak.width=Math.ceil(aj*at+al.left_offset);ak.height=al.height_px;aq.font=aq.canvas.manager.default_font;aq.textAlign="center";ar=ar.data;for(var ao=0,ap=ar.length;ao<ap;ao++){var ah=Math.round(ao*at);aq.fillText(ar[ao],ah+al.left_offset,10)}return new b(ai,am,ak,ar)}this.content_div.css("height","0px")}});var k=function(al,aj,am,ah,ak){var ai=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";j.call(this,al,aj,aj.viewport_container);N.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=am;this.dataset_id=ah;this.original_dataset_id=ah;this.data_manager=new T(D,this);this.tile_cache=new c(v);this.left_offset=0;this.track_config=new ab({track:this,params:[{key:"name",label:"Name",type:"text",default_value:al},{key:"color",label:"Color",type:"color",default_value:"black"},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.height_px,hidden:true}],saved_values:ak,onchange:function(){ai.set_name(ai.prefs.name);ai.vertical_range=ai.prefs.max_value-ai.prefs.min_value;$("#linetrack_"+ai.track_id+"_minval").text(ai.prefs.min_value);$("#linetrack_"+ai.track_id+"_maxval").text(ai.prefs.max_value);ai.tile_cache.clear();ai.request_draw()}});this.prefs=this.track_config.values;this.height_px=this.track_config.values.height;this.vertical_range=this.track_config.values.max_value-this.track_config.values.min_value;this.add_resize_handle()};q(k.prototype,N.prototype,{add_resize_handle:function(){var ah=this;var ak=false;var aj=false;var ai=$("<div class='track-resize'>");$(ah.container_div).hover(function(){ak=true;ai.show()},function(){ak=false;if(!aj){ai.hide()}});ai.hide().bind("dragstart",function(al,am){aj=true;am.original_height=$(ah.content_div).height()}).bind("drag",function(am,an){var al=Math.min(Math.max(an.original_height+an.deltaY,ah.min_height_px),ah.max_height_px);$(ah.content_div).css("height",al);ah.height_px=al;ah.request_draw(true)}).bind("dragend",function(al,am){ah.tile_cache.clear();aj=false;if(!ak){ai.hide()}ah.track_config.values.height=ah.height_px}).appendTo(ah.container_div)},predraw_init:function(){var ah=this,ai=ah.view.tracks.indexOf(ah);ah.vertical_range=undefined;return $.getJSON(ah.data_url,{stats:true,chrom:ah.view.chrom,low:null,high:null,hda_ldda:ah.hda_ldda,dataset_id:ah.dataset_id},function(aj){ah.container_div.addClass("line-track");var al=aj.data;if(isNaN(parseFloat(ah.prefs.min_value))||isNaN(parseFloat(ah.prefs.max_value))){ah.prefs.min_value=al.min;ah.prefs.max_value=al.max;$("#track_"+ai+"_minval").val(ah.prefs.min_value);$("#track_"+ai+"_maxval").val(ah.prefs.max_value)}ah.vertical_range=ah.prefs.max_value-ah.prefs.min_value;ah.total_frequency=al.total_frequency;ah.container_div.find(".yaxislabel").remove();var am=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+ai+"_minval").text(y(ah.prefs.min_value));var ak=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+ai+"_maxval").text(y(ah.prefs.max_value));ak.css({position:"absolute",top:"24px",left:"10px"});ak.prependTo(ah.container_div);am.css({position:"absolute",bottom:"2px",left:"10px"});am.prependTo(ah.container_div)})},draw_tile:function(au,am,al,aj,at){if(this.vertical_range===undefined){return}var ah=this._get_tile_bounds(aj,al),an=ah[0],ar=ah[1],ai=Math.ceil((ar-an)*at),ap=this.height_px;var ak=this.view.canvas_manager.new_canvas();ak.width=ai,ak.height=ap;var aq=ak.getContext("2d");var ao=new M.LinePainter(au.data,an,ar,this.prefs,am);ao.draw(aq,ai,ap);return new b(aj,al,ak,au.data)}});var e=function(ah,am,al,ap,ao,aj,ak,an){var ai=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];this.track_config=new ab({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ah},{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ao,onchange:function(){ai.set_name(ai.prefs.name);ai.tile_cache.clear();ai.request_draw()}});this.prefs=this.track_config.values;j.call(this,ah,am,am.viewport_container);N.call(this,aj,ak,an);this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=al;this.dataset_id=ap;this.original_dataset_id=ap;this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.inc_slots={};this.start_end_dct={};this.tile_cache=new c(d);this.data_manager=new T(20,this);this.left_offset=200;this.painter=M.LinkedFeaturePainter};q(e.prototype,N.prototype,{postdraw_actions:function(ax,ah,ay,aw){N.prototype.postdraw_actions.call(this,ax,aw);var ak=this;if(aw){var am=ak.content_div.children();var an=false;for(var al=am.length-1,ar=0;al>=ar;al--){var aj=$(am[al]);if(an){aj.remove()}else{if(aj.children().length!==0){an=true}}}}if(ak.mode=="Histogram"){var aq=-1;for(var al=0;al<ax.length;al++){var av=ax[al].max_val;if(av>aq){aq=av}}for(var al=0;al<ax.length;al++){var au=ax[al];if(au.max_val!==aq){au.canvas.remove();ak.draw_helper(true,ah,au.index,au.resolution,au.canvas.parent(),ay,[],{max:aq})}}}if(ak.filters_manager){var ai=ak.filters_manager.filters;for(var ap=0;ap<ai.length;ap++){ai[ap].update_ui_elt()}var ao=false,at;for(var al=0;al<ax.length;al++){if(ax[al].data.length){at=ax[al].data[0];for(var ap=0;ap<ai.length;ap++){if(ai[ap].applies_to(at)){ao=true;break}}}}if(ak.filters_available!==ao){ak.filters_available=ao;if(!ak.filters_available){ak.filters_div.hide()}ak.make_name_popup_menu()}}},update_auto_mode:function(ah){if(this.mode=="Auto"){if(ah=="no_detail"){ah="feature spans"}else{if(ah=="summary_tree"){ah="coverage histogram"}}this.mode_div.text("Auto ("+ah+")")}},incremental_slots:function(al,ai,ak){var aj=this.view.canvas_manager.dummy_context,ah=this.inc_slots[al];if(!ah||(ah.mode!==ak)){ah=new (t.FeatureSlotter)(al,ak==="Pack",B,function(am){return aj.measureText(am)});ah.mode=ak;this.inc_slots[al]=ah}return ah.slot_features(ai)},get_summary_tree_data:function(al,ao,aj,ax){if(ax>aj-ao){ax=aj-ao}var at=Math.floor((aj-ao)/ax),aw=[],ak=0;var am=0,an=0,ar,av=0,ap=[],au,aq;var ai=function(aA,az,aB,ay){aA[0]=az+aB*ay;aA[1]=az+(aB+1)*ay};while(av<ax&&am!==al.length){var ah=false;for(;av<ax&&!ah;av++){ai(ap,ao,av,at);for(an=am;an<al.length;an++){ar=al[an].slice(1,3);if(is_overlap(ar,ap)){ah=true;break}}if(ah){break}}data_start_index=an;aw[aw.length]=au=[ap[0],0];for(;an<al.length;an++){ar=al[an].slice(1,3);if(is_overlap(ar,ap)){au[1]++}else{break}}if(au[1]>ak){ak=au[1]}av++}return{max:ak,delta:at,data:aw}},draw_tile:function(aw,az,aE,aI,ar,ak){var aB=this,am=aB._get_tile_bounds(aI,aE),aK=am[0],ai=am[1],ay=ai-aK,aC=Math.ceil(ay*ar),aO=25,al=this.left_offset,ax,an;if(az==="Auto"){if(aw.dataset_type==="summary_tree"){az=aw.dataset_type}else{if(aw.extra_info==="no_detail"){az="no_detail"}else{var aN=aw.data;if(this.view.high-this.view.low>J){az="Squish"}else{az="Pack"}}}this.update_auto_mode(az)}if(az==="summary_tree"||az==="Histogram"){an=this.summary_draw_height;this.container_div.find(".yaxislabel").remove();var ah=$("<div />").addClass("yaxislabel");ah.text(aw.max);ah.css({position:"absolute",top:"24px",left:"10px",color:this.prefs.label_color});ah.prependTo(this.container_div);var aj=this.view.canvas_manager.new_canvas();aj.width=aC+al;aj.height=an+U;if(aw.dataset_type!="summary_tree"){var at=this.get_summary_tree_data(aw.data,aK,ai,200);if(aw.max){at.max=aw.max}aw=at}var aL=new M.SummaryTreePainter(aw,aK,ai,this.prefs);var aD=aj.getContext("2d");aD.translate(al,U);aL.draw(aD,aC,an);return new l(aI,aE,aj,aw.data,aw.max)}var ax,ap=1;if(az==="no_detail"||az==="Squish"||az==="Pack"){ap=this.incremental_slots(ar,aw.data,az);ax=this.inc_slots[ar].slots}var aq=[];if(aw.data){var au=this.filters_manager.filters;for(var aF=0,aH=aw.data.length;aF<aH;aF++){var ao=aw.data[aF];var aG=false;var av;for(var aJ=0,aM=au.length;aJ<aM;aJ++){av=au[aJ];av.update_attrs(ao);if(!av.keep(ao)){aG=true;break}}if(!aG){aq.push(ao)}}}var aA=(this.filters_manager.alpha_filter?new P(this.filters_manager.alpha_filter):null);var aL=new (this.painter)(aq,aK,ai,this.prefs,az,aA,ak);var an=Math.max(af,aL.get_required_height(ap));var aj=this.view.canvas_manager.new_canvas();aj.width=aC+al;aj.height=an;var aD=aj.getContext("2d");aD.fillStyle=this.prefs.block_color;aD.font=aD.canvas.manager.default_font;aD.textAlign="right";this.container_div.find(".yaxislabel").remove();if(aw.data){aD.translate(al,0);aL.draw(aD,aC,an,ax)}return new Q(aI,aE,aj,aw.data,aw.message)}});var V=function(ak,ai,am,ah,aj,al){e.call(this,ak,ai,am,ah,aj,al);this.painter=M.VariantPainter};q(V.prototype,N.prototype,e.prototype);var Y=function(ak,ai,am,ah,aj,al){e.call(this,ak,ai,am,ah,aj,al);this.track_config=new ab({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ak},{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:aj,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.track_config.values;this.painter=M.ReadPainter;this.make_name_popup_menu()};q(Y.prototype,N.prototype,e.prototype);var W=function(al,aj,an,ah,ak,am,ai){e.call(this,al,aj,an,ah,ak,am,{},ai);this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};q(W.prototype,N.prototype,e.prototype,{predraw_init:function(){var ai=this;var ah=function(){if(ai.data_manager.size()===0){setTimeout(ah,300)}else{ai.data_url=default_data_url;ai.data_query_wait=L;ai.dataset_state_url=converted_datasets_state_url;$.getJSON(ai.dataset_state_url,{dataset_id:ai.dataset_id,hda_ldda:ai.hda_ldda},function(aj){})}};ah()}});Z.View=ae;Z.DrawableGroup=R;Z.LineTrack=k;Z.FeatureTrack=e;Z.ReadTrack=Y};var slotting_module=function(c,b){var e=c("class").extend;var d=2,a=5;b.FeatureSlotter=function(j,h,f,g){this.slots={};this.start_end_dct={};this.w_scale=j;this.include_label=h;this.max_rows=f;this.measureText=g};e(b.FeatureSlotter.prototype,{slot_features:function(m){var p=this.w_scale,s=this.slots,h=this.start_end_dct,y=[],A=[],n=0,z=this.max_rows;for(var w=0,x=m.length;w<x;w++){var l=m[w],o=l[0];if(s[o]!==undefined){n=Math.max(n,s[o]);A.push(s[o])}else{y.push(w)}}var q=function(G,H){for(var F=0;F<=z;F++){var D=false,I=h[F];if(I!==undefined){for(var C=0,E=I.length;C<E;C++){var B=I[C];if(H>B[0]&&G<B[1]){D=true;break}}}if(!D){return F}}return -1};for(var w=0,x=y.length;w<x;w++){var l=m[y[w]],o=l[0],u=l[1],f=l[2],r=l[3],g=Math.floor(u*p),k=Math.ceil(f*p),v=this.measureText(r).width,j;if(r!==undefined&&this.include_label){v+=(d+a);if(g-v>=0){g-=v;j="left"}else{k+=v;j="right"}}var t=q(g,k);if(t>=0){if(h[t]===undefined){h[t]=[]}h[t].push([g,k]);s[o]=t;n=Math.max(n,t)}else{}}return n+1}})};var painters_module=function(k,x){var u=k("class").extend;var p=function(I,A,G,z,F,D){if(D===undefined){D=4}var C=z-A;var B=F-G;var E=Math.floor(Math.sqrt(C*C+B*B)/D);var J=C/E;var H=B/E;var y;for(y=0;y<E;y++,A+=J,G+=H){if(y%2!==0){continue}I.fillRect(A,G,D,1)}};var q=function(B,A,z,E){var D=A-E/2,C=A+E/2,F=z-Math.sqrt(E*3/2);B.beginPath();B.moveTo(D,F);B.lineTo(C,F);B.lineTo(A,z);B.lineTo(D,F);B.strokeStyle=this.fillStyle;B.fill();B.stroke();B.closePath()};var g=function(y){this.default_alpha=(y?y:1)};g.prototype.gen_alpha=function(y){return this.default_alpha};var n=function(A,C,y,z,B){this.data=A;this.view_start=C;this.view_end=y;this.prefs=u({},this.default_prefs,z);this.mode=B};n.prototype.default_prefs={};var v=function(A,C,y,z,B){n.call(this,A,C,y,z,B)};v.prototype.default_prefs={show_counts:false};v.prototype.draw=function(M,z,L){var E=this.view_start,O=this.view_end-this.view_start,N=z/O;var J=this.data.data,I=this.data.delta,G=this.data.max,B=L;delta_x_px=Math.ceil(I*N);M.save();for(var C=0,D=J.length;C<D;C++){var H=Math.floor((J[C][0]-E)*N);var F=J[C][1];if(!F){continue}var K=F/G*L;if(F!==0&&K<1){K=1}M.fillStyle=this.prefs.block_color;M.fillRect(H,B-K,delta_x_px,K);var A=4;if(this.prefs.show_counts&&(M.measureText(F).width+A)<delta_x_px){M.fillStyle=this.prefs.label_color;M.textAlign="center";M.fillText(F,H+(delta_x_px/2),10)}}M.restore()};var c=function(y,C,E,F,A){n.call(this,y,C,E,F,A);if(this.prefs.min_value===undefined){var G=Infinity;for(var z=0,B=this.data.length;z<B;z++){G=Math.min(G,this.data[z][1])}this.prefs.min_value=G}if(this.prefs.max_value===undefined){var D=-Infinity;for(var z=0,B=this.data.length;z<B;z++){D=Math.max(D,this.data[z][1])}this.prefs.max_value=D}};c.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};c.prototype.draw=function(N,M,K){var F=false,H=this.prefs.min_value,D=this.prefs.max_value,J=D-H,z=K,A=this.view_start,L=this.view_end-this.view_start,B=M/L,I=this.mode,T=this.data;N.save();var U=Math.round(K+H/J*K);if(I!=="Intensity"){N.fillStyle="#aaa";N.fillRect(0,U,M,1)}N.beginPath();var R,E,C;if(T.length>1){C=Math.ceil((T[1][0]-T[0][0])*B)}else{C=10}for(var O=0,P=T.length;O<P;O++){N.fillStyle=this.prefs.color;R=Math.round((T[O][0]-A)*B);E=T[O][1];var Q=false,G=false;if(E===null){if(F&&I==="Filled"){N.lineTo(R,z)}F=false;continue}if(E<H){G=true;E=H}else{if(E>D){Q=true;E=D}}if(I==="Histogram"){E=Math.round(E/J*z);N.fillRect(R,U,C,-E)}else{if(I==="Intensity"){E=255-Math.floor((E-H)/J*255);N.fillStyle="rgb("+E+","+E+","+E+")";N.fillRect(R,0,C,z)}else{E=Math.round(z-(E-H)/J*z);if(F){N.lineTo(R,E)}else{F=true;if(I==="Filled"){N.moveTo(R,z);N.lineTo(R,E)}else{N.moveTo(R,E)}}}}N.fillStyle=this.prefs.overflow_color;if(Q||G){var S;if(I==="Histogram"||I==="Intensity"){S=C}else{R-=2;S=4}if(Q){N.fillRect(R,0,S,3)}if(G){N.fillRect(R,z-3,S,3)}}N.fillStyle=this.prefs.color}if(I==="Filled"){if(F){N.lineTo(R,U);N.lineTo(0,U)}N.fill()}else{N.stroke()}N.restore()};var o=function(B,D,y,A,C,z){n.call(this,B,D,y,A,C);this.alpha_generator=(z?z:new g())};o.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};u(o.prototype,{get_required_height:function(z){var y=y_scale=this.get_row_height(),A=this.mode;if(A==="no_detail"||A==="Squish"||A==="Pack"){y=z*y_scale}return y+Math.max(Math.round(y_scale/2),5)},draw:function(K,B,J,G){var E=this.data,H=this.view_start,L=this.view_end;K.save();K.fillStyle=this.prefs.block_color;K.textAlign="right";var O=this.view_end-this.view_start,N=B/O,A=this.get_row_height();for(var D=0,F=E.length;D<F;D++){var M=E[D],C=M[0],y=M[1],z=M[2],I=(G&&G[C]!==undefined?G[C]:null);if((y<L&&z>H)&&(this.mode=="Dense"||I!==null)){this.draw_element(K,this.mode,M,I,H,L,N,A,B)}}K.restore()},draw_element:function(E,A,G,C,B,D,F,z,y){console.log("WARNING: Unimplemented function.")}});var d=10,j=3,m=5,w=10,f=1,s=3,e=3,a=9,l=2,h="#ccc";var r=function(B,D,y,A,C,z){o.call(this,B,D,y,A,C,z)};u(r.prototype,o.prototype,{get_row_height:function(){var z=this.mode,y;if(z==="Dense"){y=d}else{if(z==="no_detail"){y=j}else{if(z==="Squish"){y=m}else{y=w}}}return y},draw_element:function(K,D,S,F,M,ac,ag,ah,y){var P=S[0],ae=S[1],W=S[2],N=S[3],X=Math.floor(Math.max(0,(ae-M)*ag)),L=Math.ceil(Math.min(y,Math.max(0,(W-M)*ag))),V=(D==="Dense"?0:(0+F))*ah,J,aa,O=null,ai=null,B=this.prefs.block_color,Z=this.prefs.label_color;K.globalAlpha=this.alpha_generator.gen_alpha(S);if(D=="Dense"){F=1}if(D==="no_detail"){K.fillStyle=B;K.fillRect(X,V+5,L-X,f)}else{var I=S[4],U=S[5],Y=S[6],C=S[7];if(U&&Y){O=Math.floor(Math.max(0,(U-M)*ag));ai=Math.ceil(Math.min(y,Math.max(0,(Y-M)*ag)))}var af,Q;if(D==="Squish"||D==="Dense"){af=1;Q=e}else{af=5;Q=a}if(!C){if(S.strand){if(S.strand==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand_inv")}else{if(S.strand==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand_inv")}}}else{K.fillStyle=B}K.fillRect(X,V,L-X,Q)}else{var H,R;if(D==="Squish"||D==="Dense"){K.fillStyle=h;H=V+Math.floor(e/2)+1;R=1}else{if(I){var H=V;var R=Q;if(I==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand")}else{if(I==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand")}}}else{K.fillStyle=h;H+=(e/2)+1;R=1}}K.fillRect(X,H,L-X,R);for(var ad=0,A=C.length;ad<A;ad++){var E=C[ad],z=Math.floor(Math.max(0,(E[0]-M)*ag)),T=Math.ceil(Math.min(y,Math.max((E[1]-M)*ag)));if(z>T){continue}K.fillStyle=B;K.fillRect(z,V+(Q-af)/2+1,T-z,af);if(O!==undefined&&Y>U&&!(z>ai||T<O)){var ab=Math.max(z,O),G=Math.min(T,ai);K.fillRect(ab,V+1,G-ab,Q);if(C.length==1&&D=="Pack"){if(I==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand_inv")}else{if(I==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand_inv")}}if(ab+14<G){ab+=2;G-=2}K.fillRect(ab,V+1,G-ab,Q)}}}}if(D==="Pack"&&ae>M){K.fillStyle=Z;if(M===0&&X-K.measureText(N).width<0){K.textAlign="left";K.fillText(N,L+l,V+8)}else{K.textAlign="right";K.fillText(N,X-l,V+8)}}}K.globalAlpha=1}});var b=function(B,D,y,A,C,z){o.call(this,B,D,y,A,C,z)};u(b.prototype,o.prototype,{draw_element:function(R,M,G,C,U,A,J,S,P){var G=data[i],I=G[0],Q=G[1],B=G[2],L=G[3],E=Math.floor(Math.max(0,(Q-U)*J)),H=Math.ceil(Math.min(P,Math.max(0,(B-U)*J))),D=(M==="Dense"?0:(0+C))*S,y,V,z=null,K=null;if(no_label){R.fillStyle=block_color;R.fillRect(E+left_offset,D+5,H-E,1)}else{var T=G[4],O=G[5],F=G[6];y=9;V=1;R.fillRect(E+left_offset,D,H-E,y);if(M!=="Dense"&&L!==undefined&&Q>U){R.fillStyle=label_color;if(U===0&&E-R.measureText(L).width<0){R.textAlign="left";R.fillText(L,H+2+left_offset,D+8)}else{R.textAlign="right";R.fillText(L,E-2+left_offset,D+8)}R.fillStyle=block_color}var N=T+" / "+O;if(Q>U&&R.measureText(N).width<(H-E)){R.fillStyle="white";R.textAlign="center";R.fillText(N,left_offset+E+(H-E)/2,D+8);R.fillStyle=block_color}}}});var t=function(C,E,y,B,D,z,A){o.call(this,C,E,y,B,D,z);this.ref_seq=A};t.prototype.default_prefs=u({},o.prototype.default_prefs,{show_insertions:false});u(t.prototype,o.prototype,{get_row_height:function(){var y,z=this.mode;if(z==="Dense"){y=d}else{if(z==="Squish"){y=m}else{y=w;if(this.prefs.show_insertions){y*=2}}}return y},draw_read:function(U,P,L,Z,A,T,I,F,E){U.textAlign="center";var S=this,z=[Z,A],O=0,V=0,R=0;ref_seq=this.ref_seq,char_width_px=U.canvas.manager.char_width_px;var ae=[];if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){R=Math.round(L/2)}if(!I){I=[[0,F.length]]}for(var M=0,X=I.length;M<X;M++){var J=I[M],B="MIDNSHP=X"[J[0]],N=J[1];if(B==="H"||B==="S"){O-=N}var G=T+O,ad=Math.floor(Math.max(0,(G-Z)*L)),H=Math.floor(Math.max(0,(G+N-Z)*L));if(ad===H){H+=1}switch(B){case"H":break;case"S":case"M":case"=":if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(R>0){U.fillStyle=this.prefs.block_color;U.fillRect(ad-R,E+1,H-ad,9);U.fillStyle=h;for(var ab=0,y=Q.length;ab<y;ab++){if(this.prefs.show_differences&&ref_seq){var K=ref_seq[G-Z+ab];if(!K||K.toLowerCase()===Q[ab].toLowerCase()){continue}}if(G+ab>=Z&&G+ab<=A){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac,E+9)}}}else{U.fillStyle=this.prefs.block_color;U.fillRect(ad,E+4,H-ad,e)}}V+=N;O+=N;break;case"N":U.fillStyle=h;U.fillRect(ad-R,E+5,H-ad,1);O+=N;break;case"D":U.fillStyle="red";U.fillRect(ad-R,E+4,H-ad,3);O+=N;break;case"P":break;case"I":var Y=ad-R;if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(this.prefs.show_insertions){var D=ad-(H-ad)/2;if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){U.fillStyle="yellow";U.fillRect(D-R,E-9,H-ad,9);ae[ae.length]={type:"triangle",data:[Y,E+4,5]};U.fillStyle=h;switch(seq_tile_overlap){case (OVERLAP_START):Q=Q.slice(Z-G);break;case (OVERLAP_END):Q=Q.slice(0,G-A);break;case (CONTAINED_BY):break;case (CONTAINS):Q=Q.slice(Z-G,G-A);break}for(var ab=0,y=Q.length;ab<y;ab++){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac-(H-ad)/2,E)}}else{U.fillStyle="yellow";U.fillRect(D,E+(this.mode!=="Dense"?2:5),H-ad,(P!=="Dense"?e:s))}}else{if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){ae[ae.length]={type:"text",data:[Q.length,Y,E+9]}}else{}}}V+=N;break;case"X":V+=N;break}}U.fillStyle="yellow";var aa,C,af;for(var W=0;W<ae.length;W++){aa=ae[W];C=aa.type;af=aa.data;if(C==="text"){U.save();U.font="bold "+U.font;U.fillText(af[0],af[1],af[2]);U.restore()}else{if(C=="triangle"){q(U,af[0],af[1],af[2])}}}},draw_element:function(R,M,E,B,U,z,I,S,P){var H=E[0],Q=E[1],A=E[2],J=E[3],D=Math.floor(Math.max(0,(Q-U)*I)),F=Math.ceil(Math.min(P,Math.max(0,(A-U)*I))),C=(M==="Dense"?0:(0+B))*S,V=this.prefs.block_color,G=this.prefs.label_color,O=0;if((M==="Pack"||this.mode==="Auto")&&I>R.canvas.manager.char_width_px){var O=Math.round(I/2)}R.fillStyle=V;if(E[5] instanceof Array){var N=Math.floor(Math.max(0,(E[4][0]-U)*I)),L=Math.ceil(Math.min(P,Math.max(0,(E[4][1]-U)*I))),K=Math.floor(Math.max(0,(E[5][0]-U)*I)),y=Math.ceil(Math.min(P,Math.max(0,(E[5][1]-U)*I)));if(E[4][1]>=U&&E[4][0]<=z&&E[4][2]){this.draw_read(R,M,I,U,z,E[4][0],E[4][2],E[4][3],C)}if(E[5][1]>=U&&E[5][0]<=z&&E[5][2]){this.draw_read(R,M,I,U,z,E[5][0],E[5][2],E[5][3],C)}if(K>L){R.fillStyle=h;p(R,L-O,C+5,K-O,C+5)}}else{R.fillStyle=V;this.draw_read(R,M,I,U,z,Q,E[4],E[5],C)}if(M==="Pack"&&Q>U){R.fillStyle=this.prefs.label_color;var T=1;if(T===0&&D-R.measureText(J).width<0){R.textAlign="left";R.fillText(J,F+l-O,C+8)}else{R.textAlign="right";R.fillText(J,D-l-O,C+8)}R.fillStyle=V}}});x.AlphaGenerator=g;x.SummaryTreePainter=v;x.LinePainter=c;x.LinkedFeaturePainter=r;x.ReadPainter=t;x.VariantPainter=b};(function(d){var c={};var b=function(e){return c[e]};var a=function(f,g){var e={};g(b,e);c[f]=e};a("class",class_module);a("slotting",slotting_module);a("painters",painters_module);a("trackster",trackster_module);for(key in c.trackster){d[key]=c.trackster[key]}})(window);
\ No newline at end of file
--- a/static/scripts/trackster.js Fri Sep 23 11:32:08 2011 -0400
+++ b/static/scripts/trackster.js Fri Sep 23 13:26:34 2011 -0400
@@ -142,18 +142,43 @@
// ---- Web UI specific utilities ----
+/**
+ * Dictionary of HTML element-JavaScript object relationships.
+ */
+// TODO: probably should separate moveable objects from containers.
+var html_elt_js_obj_dict = {};
+
+/**
+ * Designates an HTML as a container.
+ */
+var is_container = function(element, obj) {
+ html_elt_js_obj_dict[element.attr("id")] = obj;
+};
+
/**
* Make `element` moveable within parent and sibling elements by dragging `handle` (a selector).
+ * Function manages JS objects, containers as well.
+ *
+ * @param element HTML element to make moveable
+ * @param handle_class classname that denotes HTML element to be used as handle
+ * @param container_selector selector used to identify possible containers for this element
+ * @param element_js_obj JavaScript object associated with element; used
*/
-var moveable = function( element, handle_class, container_selector ) {
+var moveable = function(element, handle_class, container_selector, element_js_obj) {
// HACK: set default value for container selector.
container_selector = ".group";
var css_border_props = {};
+
+ // Register element with its object.
+ html_elt_js_obj_dict[element.attr("id")] = element_js_obj;
+
// Need to provide selector for handle, not class.
element.bind( "drag", { handle: "." + handle_class, relative: true }, function ( e, d ) {
+ var element = $(this);
var
parent = $(this).parent(),
children = parent.children(),
+ this_obj = html_elt_js_obj_dict[$(this).attr("id")],
child,
container,
top,
@@ -173,13 +198,19 @@
if (d.offsetY < top) {
// Moving above container.
$(this).insertBefore(container);
+ var cur_container = html_elt_js_obj_dict[container.attr("id")];
+ cur_container.remove_drawable(this_obj);
+ cur_container.container.add_drawable_before(this_obj, cur_container);
return;
}
else if (d.offsetY > bottom) {
// Moving below container.
$(this).insertAfter(container);
+ var cur_container = html_elt_js_obj_dict[container.attr("id")];
+ cur_container.remove_drawable(this_obj);
+ cur_container.container.add_drawable(this_obj);
return;
- }
+ }
}
// Handle dragging into container.
@@ -198,6 +229,9 @@
else {
child.find(".content-div").append(this);
}
+ // Update containers.
+ this_obj.container.remove_drawable(this_obj);
+ html_elt_js_obj_dict[child.attr("id")].add_drawable(this_obj);
return;
}
}
@@ -216,10 +250,15 @@
if ( i === children.length ) {
if ( this !== children.get(i - 1) ) {
parent.append(this);
+ // Update container.
+ html_elt_js_obj_dict[parent.attr("id")].move_drawable(this_obj, i);
}
}
else if ( this !== children.get(i) ) {
$(this).insertBefore( children.get(i) );
+ // Need to adjust insert position if moving down because move is changing
+ // indices of all list items.
+ html_elt_js_obj_dict[parent.attr("id")].move_drawable(this_obj, (d.deltaY > 0 ? i-1 : i) );
}
}).bind("dragstart", function() {
css_border_props["border-top"] = element.css("border-top");
@@ -523,15 +562,122 @@
});
/**
+ * Drawables hierarchy:
+ *
+ * Drawable
+ * --> DrawableCollection
+ * --> DrawableGroup
+ * --> View
+ * --> Track
+ */
+
+/**
+ * Base interface for all drawable objects.
+ */
+var Drawable = function(name, view, parent_element, container) {
+ this.name = name;
+ this.view = view;
+ this.parent_element = parent_element;
+ this.container = container;
+};
+
+Drawable.prototype.request_draw = function() {};
+Drawable.prototype.draw = function() {};
+
+/**
+ * A collection of drawable objects.
+ */
+var DrawableCollection = function(name, view, parent_element, container) {
+ Drawable.call(this, name, view, parent_element, container);
+
+ // Attribute init.
+ this.drawables = [];
+};
+extend(DrawableCollection.prototype, Drawable.prototype, {
+ to_json: function() {
+ // For now, just return list of drawables in collection.
+ var json_obj = [];
+ for (var i = 0; i < this.drawables.length; i++) {
+
+ }
+ },
+ /**
+ * Add a drawable to the end of the collection.
+ */
+ add_drawable: function(drawable) {
+ this.drawables.push(drawable);
+ drawable.container = this;
+ },
+ /**
+ * Add a drawable before another drawable.
+ */
+ add_drawable_before: function(drawable, other) {
+ var index = this.drawables.indexOf(other);
+ if (index != -1) {
+ this.drawables.splice(index, 0, drawable);
+ return true;
+ }
+ return false;
+ },
+ /**
+ * Tries to remove drawable from the collection. Returns true if drawable removed from
+ * collection, false otherwise.
+ */
+ remove_drawable: function(drawable) {
+ var index = this.drawables.indexOf(drawable);
+ if (index != -1) {
+ this.drawables.splice(index, 1);
+ drawable.container = null;
+ return true;
+ }
+ return false;
+ },
+ /**
+ * Move drawable to another location in collection.
+ */
+ move_drawable: function(drawable, new_position) {
+ var index = this.drawables.indexOf(drawable);
+ if (index != -1) {
+ // Remove from current position:
+ this.drawables.splice(index, 1);
+ // insert into new position:
+ this.drawables.splice(new_position, 0, drawable);
+ return true;
+ }
+ return false;
+ }
+});
+
+/**
+ * A group of drawables that are moveable, visible.
+ */
+var DrawableGroup = function(name, view, parent_element, container) {
+ DrawableCollection.call(this, name, view, parent_element, container);
+
+ this.drag_handle_class = "group-handle";
+
+ // HTML elements.
+ this.container_div = $("<div/>").addClass("group").appendTo(this.parent_element);
+ this.container_div.append($("<div/>").addClass(this.drag_handle_class));
+ this.name_div = $("<div/>").addClass("group-name").text(this.name).appendTo(this.container_div);
+ this.content_div = $("<div/>").addClass("content-div").appendTo(this.container_div);
+ is_container(this.container_div, this);
+};
+
+extend(DrawableGroup.prototype, DrawableCollection.prototype, Drawable.prototype);
+
+/**
* View object manages complete viz view, including tracks and user interactions.
*/
var View = function(container, title, vis_id, dbkey, callback) {
+ DrawableCollection.call(this);
this.container = container;
this.chrom = null;
this.vis_id = vis_id;
this.dbkey = dbkey;
this.title = title;
- this.tracks = [];
+ // Alias tracks to point at drawables. TODO: changes tracks to 'drawables' or something similar.
+ this.tracks = this.drawables;
this.label_tracks = [];
this.tracks_to_be_redrawn = [];
this.max_low = 0;
@@ -545,7 +691,7 @@
this.canvas_manager = new CanvasManager( container.get(0).ownerDocument );
this.reset();
};
-extend( View.prototype, {
+extend( View.prototype, DrawableCollection.prototype, {
init: function( callback ) {
// Create DOM elements
var parent_element = this.container,
@@ -559,9 +705,10 @@
// Label track fixed at top
this.top_labeltrack = $("<div/>").addClass("top-labeltrack").appendTo(this.top_container);
// Viewport for dragging tracks in center
- this.viewport_container = $("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);
+ this.viewport_container = $("<div/>").addClass("viewport-container").attr("id", "viewport-container").appendTo(this.content_div);
+ is_container(this.viewport_container, view);
// Introduction div shown when there are no tracks.
- this.intro_div = $("<div/>").addClass("intro").appendTo(this.viewport_container).hide();
+ this.intro_div = $("<div/>").addClass("intro");
var add_tracks_button = $("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function () {
add_tracks();
});
@@ -739,13 +886,13 @@
return jsonified_drawables;
},
- /** Show or hide intro div depending on view state. */
+ /** Add or remove intro div depending on view state. */
update_intro_div: function() {
if (this.num_tracks === 0) {
- this.intro_div.show();
+ this.intro_div.appendTo(this.viewport_container);
}
else {
- this.intro_div.hide();
+ this.intro_div.remove();
}
},
update_location: function(low, high) {
@@ -900,7 +1047,7 @@
this.tracks.push(track);
if (track.init) { track.init(); }
track.container_div.attr('id', 'track_' + track.track_id);
- moveable(track.container_div, track.drag_handle_class);
+ moveable(track.container_div, track.drag_handle_class, ".group", track);
this.track_id_counter += 1;
this.num_tracks += 1;
this.has_changes = true;
@@ -1155,12 +1302,20 @@
// Highlight value for inputs for easy replacement.
this.parent_div.find("input").click(function() { $(this).select() });
- // Add 'Go' button.
+ // Add buttons for running on dataset, region.
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() {
+ // Create group for track + new tracks and put track in group.
+ var
+ parent_elt = this.track.parent_element,
+ new_group = new DrawableCollection("New Group", parent_elt);
+ //this.track.view.add_track(new_group);
+
+
+ // Run tool to create new track.
tool.run_on_region();
});
run_on_dataset_button.click( function() {
@@ -1837,44 +1992,6 @@
};
/**
- * Base interface for all drawable objects.
- * TODO: Tracks should use this interface.
- */
-var Drawable = function(name, view) {
- this.name = name;
- this.view = view;
- this.parent_element = view.viewport_container;
-};
-
-Drawable.prototype.request_draw = function() {};
-Drawable.prototype.draw = function() {};
-
-/**
- * A collection of drawable objects.
- */
-var DrawableCollection = function(name, view) {
- Drawable.call(this, name, view);
-
- // Attribute init.
- this.members = [];
- this.drag_handle_class = "group-handle";
-
- // HTML elements.
- this.container_div = $("<div/>").addClass("group").appendTo(this.parent_element);
- this.container_div.append($("<div/>").addClass(this.drag_handle_class));
- this.name_div = $("<div/>").addClass("group-name").text(this.name).appendTo(this.container_div);
- this.content_div = $("<div/>").addClass("content-div").appendTo(this.container_div);
-};
-extend(DrawableCollection.prototype, Drawable.prototype, {
- request_draw: function(force, clear_after) {
-
- },
- draw: function() {
-
- }
-});
-
-/**
* Tracks are objects can be added to the View.
*
* Track object hierarchy:
@@ -1889,12 +2006,12 @@
* -------> VcfTrack
*/
var Track = function(name, view, parent_element, data_url, data_query_wait) {
+ // For now, track's container is always view.
+ Drawable.call(this, name, view, parent_element, view);
+
//
// Attribute init.
//
- this.name = name;
- this.view = view;
- this.parent_element = parent_element;
this.data_url = (data_url ? data_url : default_data_url);
this.data_url_extra_params = {}
this.data_query_wait = (data_query_wait ? data_query_wait : DEFAULT_DATA_QUERY_WAIT);
@@ -3179,7 +3296,7 @@
// Exports
exports.View = View;
-exports.DrawableCollection = DrawableCollection;
+exports.DrawableGroup = DrawableGroup;
exports.LineTrack = LineTrack;
exports.FeatureTrack = FeatureTrack;
exports.ReadTrack = ReadTrack;
--- a/templates/tracks/browser.mako Fri Sep 23 11:32:08 2011 -0400
+++ b/templates/tracks/browser.mako Fri Sep 23 13:26:34 2011 -0400
@@ -198,7 +198,7 @@
make_popupmenu( $("#viz-actions-button"), {
"Add Tracks": add_tracks,
"Add Group": function() {
- var group = new DrawableCollection("New Group", view);
+ var group = new DrawableGroup("New Group", view, view.viewport_container, view);
view.add_track(group);
},
"Save": function() {
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

23 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/915fd558d77b/
changeset: 915fd558d77b
user: greg
date: 2011-09-23 17:32:08
summary: Render an error message on the tool form when the loaded tool includes a dynamically generated select list that is either missing an entry in the tool_data_table_conf.xml file or is missing an index file.
affected #: 1 file (-1 bytes)
--- a/templates/tool_form.mako Fri Sep 23 11:29:45 2011 -0400
+++ b/templates/tool_form.mako Fri Sep 23 11:32:08 2011 -0400
@@ -247,15 +247,35 @@
<br/>
%endif
-## handle calculating the redict url for the special case where we have nginx proxy
-## upload and need to do url_for on the redirect portion of the tool action
<%
+ # Render an error message if a dynamically generated select list is missing a required
+ # index file or entry in the tool_data_table_conf.xml file.
+ from galaxy.tools.parameters.basic import SelectToolParameter
+ message = ""
+ for input_param in tool.input_params:
+ if isinstance( input_param, SelectToolParameter ) and input_param.is_dynamic:
+ # If the tool refers to .loc files or requires an entry in the
+ # tool_data_table_conf.xml, make sure all requirements exist.
+ options = input_param.dynamic_options or input_param.options
+ if options.missing_tool_data_table_name:
+ message = "Data table named '%s' is required by tool but not configured" % options.missing_tool_data_table_name
+ break
+ if options.missing_index_file:
+ message = "Index file named '%s' is required by tool but not availble" % options.missing_index_file
+ break
+
+ # Handle calculating the redirect url for the special case where we have nginx proxy
+ # upload and need to do url_for on the redirect portion of the tool action.
try:
tool_url = h.url_for(tool.action)
except AttributeError:
assert len(tool.action) == 2
tool_url = tool.action[0] + h.url_for(tool.action[1])
%>
+%if message:
+ <div class="errormessage">${message}</div>
+ <br/>
+%endif
<div class="toolForm" id="${tool.id}">
%if tool.has_multiple_pages:
<div class="toolFormTitle">${tool.name} (step ${tool_state.page+1} of ${tool.npages})</div>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

23 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/172a1891f751/
changeset: 172a1891f751
user: greg
date: 2011-09-23 17:29:45
summary: Fix for installing tools from a clones tool shed repository to a local Galaxy instance where tool includes a dynamically generated select list parmater that uses both an index file and a tool-data_table_conf.xml entry.
affected #: 1 file (-1 bytes)
--- a/lib/galaxy/web/base/controller.py Fri Sep 23 11:01:37 2011 -0400
+++ b/lib/galaxy/web/base/controller.py Fri Sep 23 11:29:45 2011 -0400
@@ -2456,7 +2456,7 @@
if error:
log.debug( exception_msg )
break
- elif options.missing_index_file:
+ if options.missing_index_file:
missing_head, missing_tail = os.path.split( options.missing_index_file )
# The repository must contain the required xxx.loc.sample file.
for sample_file in sample_files:
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: natefoo: BaseController -> BaseUIController fixes for webapps.
by Bitbucket 23 Sep '11
by Bitbucket 23 Sep '11
23 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/2675699dea93/
changeset: 2675699dea93
user: natefoo
date: 2011-09-23 17:01:37
summary: BaseController -> BaseUIController fixes for webapps.
affected #: 14 files (-1 bytes)
--- a/lib/galaxy/webapps/community/buildapp.py Fri Sep 23 10:38:27 2011 -0400
+++ b/lib/galaxy/webapps/community/buildapp.py Fri Sep 23 11:01:37 2011 -0400
@@ -20,12 +20,12 @@
log = logging.getLogger( __name__ )
-def add_controllers( webapp, app ):
+def add_ui_controllers( webapp, app ):
"""
Search for controllers in the 'galaxy.webapps.controllers' module and add
them to the webapp.
"""
- from galaxy.web.base.controller import BaseController
+ from galaxy.web.base.controller import BaseUIController
from galaxy.web.base.controller import ControllerUnavailable
import galaxy.webapps.community.controllers
controller_dir = galaxy.webapps.community.controllers.__path__[0]
@@ -39,8 +39,8 @@
# Look for a controller inside the modules
for key in dir( module ):
T = getattr( module, key )
- if isclass( T ) and T is not BaseController and issubclass( T, BaseController ):
- webapp.add_controller( name, T( app ) )
+ if isclass( T ) and T is not BaseUIController and issubclass( T, BaseUIController ):
+ webapp.add_ui_controller( name, T( app ) )
import galaxy.web.controllers
controller_dir = galaxy.web.controllers.__path__[0]
for fname in os.listdir( controller_dir ):
@@ -54,8 +54,8 @@
# Look for a controller inside the modules
for key in dir( module ):
T = getattr( module, key )
- if isclass( T ) and T is not BaseController and issubclass( T, BaseController ):
- webapp.add_controller( name, T( app ) )
+ if isclass( T ) and T is not BaseUIController and issubclass( T, BaseUIController ):
+ webapp.add_ui_controller( name, T( app ) )
def app_factory( global_conf, **kwargs ):
"""Return a wsgi application serving the root object"""
@@ -73,7 +73,7 @@
atexit.register( app.shutdown )
# Create the universe WSGI application
webapp = galaxy.web.framework.WebApplication( app, session_cookie='galaxycommunitysession' )
- add_controllers( webapp, app )
+ add_ui_controllers( webapp, app )
webapp.add_route( '/:controller/:action', action='index' )
webapp.add_route( '/:action', controller='repository', action='index' )
webapp.add_route( '/repos/*path_info', controller='hg', action='handle_request', path_info='/' )
--- a/lib/galaxy/webapps/community/controllers/admin.py Fri Sep 23 10:38:27 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/admin.py Fri Sep 23 11:01:37 2011 -0400
@@ -380,7 +380,7 @@
return trans.sa_session.query( self.model_class ) \
.join( model.Repository.table )
-class AdminController( BaseController, Admin ):
+class AdminController( BaseUIController, Admin ):
user_list_grid = UserListGrid()
role_list_grid = RoleListGrid()
--- a/lib/galaxy/webapps/community/controllers/hg.py Fri Sep 23 10:38:27 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/hg.py Fri Sep 23 11:01:37 2011 -0400
@@ -5,7 +5,7 @@
log = logging.getLogger(__name__)
-class HgController( BaseController ):
+class HgController( BaseUIController ):
@web.expose
def handle_request( self, trans, **kwd ):
# The os command that results in this method being called will look something like
--- a/lib/galaxy/webapps/community/controllers/repository.py Fri Sep 23 10:38:27 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/repository.py Fri Sep 23 11:01:37 2011 -0400
@@ -220,7 +220,7 @@
.join( model.RepositoryMetadata.table ) \
.join( model.User.table )
-class RepositoryController( BaseController, ItemRatings ):
+class RepositoryController( BaseUIController, ItemRatings ):
downloadable_repository_list_grid = DownloadableRepositoryListGrid()
repository_list_grid = RepositoryListGrid()
--- a/lib/galaxy/webapps/community/controllers/upload.py Fri Sep 23 10:38:27 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/upload.py Fri Sep 23 11:01:37 2011 -0400
@@ -14,7 +14,7 @@
class UploadError( Exception ):
pass
-class UploadController( BaseController ):
+class UploadController( BaseUIController ):
@web.expose
@web.require_login( 'upload', use_panels=True, webapp='community' )
def upload( self, trans, **kwd ):
@@ -313,4 +313,4 @@
message = "Uploaded archives cannot contain hgrc files."
return False, message
return True, ''
-
\ No newline at end of file
+
--- a/lib/galaxy/webapps/demo_sequencer/buildapp.py Fri Sep 23 10:38:27 2011 -0400
+++ b/lib/galaxy/webapps/demo_sequencer/buildapp.py Fri Sep 23 11:01:37 2011 -0400
@@ -18,12 +18,12 @@
import config
import galaxy.webapps.demo_sequencer.framework
-def add_controllers( webapp, app ):
+def add_ui_controllers( webapp, app ):
"""
Search for controllers in the 'galaxy.webapps.demo_sequencer.controllers'
directory and add them to the webapp.
"""
- from galaxy.web.base.controller import BaseController
+ from galaxy.web.base.controller import BaseUIController
from galaxy.web.base.controller import ControllerUnavailable
import galaxy.webapps.demo_sequencer.controllers
controller_dir = galaxy.webapps.demo_sequencer.controllers.__path__[0]
@@ -37,8 +37,8 @@
# Look for a controller inside the modules
for key in dir( module ):
T = getattr( module, key )
- if isclass( T ) and T is not BaseController and issubclass( T, BaseController ):
- webapp.add_controller( name, T( app ) )
+ if isclass( T ) and T is not BaseUIController and issubclass( T, BaseUIController ):
+ webapp.add_ui_controller( name, T( app ) )
def app_factory( global_conf, **kwargs ):
"""Return a wsgi application serving the root object"""
@@ -56,7 +56,7 @@
atexit.register( app.shutdown )
# Create the universe WSGI application
webapp = galaxy.webapps.demo_sequencer.framework.WebApplication( app, session_cookie='galaxydemo_sequencersession' )
- add_controllers( webapp, app )
+ add_ui_controllers( webapp, app )
# These two routes handle our simple needs at the moment
webapp.add_route( '/:controller/:action', action='index' )
webapp.add_route( '/:action', controller='common', action='index' )
--- a/lib/galaxy/webapps/demo_sequencer/controllers/common.py Fri Sep 23 10:38:27 2011 -0400
+++ b/lib/galaxy/webapps/demo_sequencer/controllers/common.py Fri Sep 23 11:01:37 2011 -0400
@@ -8,7 +8,7 @@
import logging
log = logging.getLogger( __name__ )
-class CommonController( BaseController ):
+class CommonController( BaseUIController ):
@web.expose
def index( self, trans, **kwd ):
redirect_action = util.restore_text( kwd.get( 'redirect_action', '' ) )
--- a/lib/galaxy/webapps/reports/buildapp.py Fri Sep 23 10:38:27 2011 -0400
+++ b/lib/galaxy/webapps/reports/buildapp.py Fri Sep 23 11:01:37 2011 -0400
@@ -20,12 +20,12 @@
import galaxy.model.mapping
import galaxy.web.framework
-def add_controllers( webapp, app ):
+def add_ui_controllers( webapp, app ):
"""
Search for controllers in the 'galaxy.webapps.controllers' module and add
them to the webapp.
"""
- from galaxy.web.base.controller import BaseController
+ from galaxy.web.base.controller import BaseUIController
from galaxy.web.base.controller import ControllerUnavailable
import galaxy.webapps.reports.controllers
controller_dir = galaxy.webapps.reports.controllers.__path__[0]
@@ -39,8 +39,8 @@
# Look for a controller inside the modules
for key in dir( module ):
T = getattr( module, key )
- if isclass( T ) and T is not BaseController and issubclass( T, BaseController ):
- webapp.add_controller( name, T( app ) )
+ if isclass( T ) and T is not BaseUIController and issubclass( T, BaseUIController ):
+ webapp.add_ui_controller( name, T( app ) )
def app_factory( global_conf, **kwargs ):
"""Return a wsgi application serving the root object"""
@@ -53,7 +53,7 @@
atexit.register( app.shutdown )
# Create the universe WSGI application
webapp = galaxy.web.framework.WebApplication( app, session_cookie='galaxyreportssession' )
- add_controllers( webapp, app )
+ add_ui_controllers( webapp, app )
# These two routes handle our simple needs at the moment
webapp.add_route( '/:controller/:action', controller="root", action='index' )
webapp.add_route( '/:action', controller='root', action='index' )
--- a/lib/galaxy/webapps/reports/controllers/jobs.py Fri Sep 23 10:38:27 2011 -0400
+++ b/lib/galaxy/webapps/reports/controllers/jobs.py Fri Sep 23 11:01:37 2011 -0400
@@ -117,7 +117,7 @@
.join( model.User ) \
.enable_eagerloads( False )
-class Jobs( BaseController ):
+class Jobs( BaseUIController ):
specified_date_list_grid = SpecifiedDateListGrid()
--- a/lib/galaxy/webapps/reports/controllers/root.py Fri Sep 23 10:38:27 2011 -0400
+++ b/lib/galaxy/webapps/reports/controllers/root.py Fri Sep 23 11:01:37 2011 -0400
@@ -2,7 +2,7 @@
import logging
log = logging.getLogger( __name__ )
-class Report( BaseController ):
+class Report( BaseUIController ):
@web.expose
def index( self, trans, **kwd ):
return trans.fill_template( '/webapps/reports/index.mako' )
--- a/lib/galaxy/webapps/reports/controllers/sample_tracking.py Fri Sep 23 10:38:27 2011 -0400
+++ b/lib/galaxy/webapps/reports/controllers/sample_tracking.py Fri Sep 23 11:01:37 2011 -0400
@@ -94,7 +94,7 @@
.join( model.User ) \
.enable_eagerloads( False )
-class SampleTracking( BaseController ):
+class SampleTracking( BaseUIController ):
specified_date_list_grid = SpecifiedDateListGrid()
--- a/lib/galaxy/webapps/reports/controllers/system.py Fri Sep 23 10:38:27 2011 -0400
+++ b/lib/galaxy/webapps/reports/controllers/system.py Fri Sep 23 11:01:37 2011 -0400
@@ -6,7 +6,7 @@
import logging
log = logging.getLogger( __name__ )
-class System( BaseController ):
+class System( BaseUIController ):
@web.expose
def index( self, trans, **kwd ):
params = util.Params( kwd )
--- a/lib/galaxy/webapps/reports/controllers/users.py Fri Sep 23 10:38:27 2011 -0400
+++ b/lib/galaxy/webapps/reports/controllers/users.py Fri Sep 23 11:01:37 2011 -0400
@@ -10,7 +10,7 @@
import logging
log = logging.getLogger( __name__ )
-class Users( BaseController ):
+class Users( BaseUIController ):
@web.expose
def registered_users( self, trans, **kwd ):
message = util.restore_text( kwd.get( 'message', '' ) )
--- a/lib/galaxy/webapps/reports/controllers/workflows.py Fri Sep 23 10:38:27 2011 -0400
+++ b/lib/galaxy/webapps/reports/controllers/workflows.py Fri Sep 23 11:01:37 2011 -0400
@@ -94,7 +94,7 @@
.join( model.User ) \
.enable_eagerloads( False )
-class Workflows( BaseController ):
+class Workflows( BaseUIController ):
specified_date_list_grid = SpecifiedDateListGrid()
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: dan: Fix for maf_utilities.build_maf_index_species_chromosomes() return values when a bad MAF is provided.
by Bitbucket 23 Sep '11
by Bitbucket 23 Sep '11
23 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/ef89e4d62007/
changeset: ef89e4d62007
user: dan
date: 2011-09-23 16:38:27
summary: Fix for maf_utilities.build_maf_index_species_chromosomes() return values when a bad MAF is provided.
affected #: 1 file (-1 bytes)
--- a/lib/galaxy/tools/util/maf_utilities.py Fri Sep 23 10:07:19 2011 -0400
+++ b/lib/galaxy/tools/util/maf_utilities.py Fri Sep 23 10:38:27 2011 -0400
@@ -227,7 +227,7 @@
except Exception, e:
#most likely a bad MAF
log.debug( 'Building MAF index on %s failed: %s' % ( filename, e ) )
- return ( None, [], {} )
+ return ( None, [], {}, 0 )
return ( indexes, species, species_chromosomes, blocks )
#builds and returns ( index, index_filename ) for specified maf_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 changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/651a627ec387/
changeset: 651a627ec387
user: greg
date: 2011-09-23 16:07:19
summary: Replace the online form approach to adding new entries into the tool_data_table_conf.xml file by requiring a tool shed user to upload a tool_data_table_conf.xml.sample file that includes all entries required by tools in the repository. Steamline the local Galaxy tool install process for tools that include dynamically generated select lists so that all of this occurs behind the scene.
affected #: 6 files (-1 bytes)
--- a/lib/galaxy/web/base/controller.py Fri Sep 23 10:01:18 2011 -0400
+++ b/lib/galaxy/web/base/controller.py Fri Sep 23 10:07:19 2011 -0400
@@ -2417,6 +2417,8 @@
if returncode == 0:
# The repository_tools_tups list contains tuples of ( relative_path_to_tool_config, tool ) pairs
repository_tools_tups = []
+ # The sample_files list contains all files whose name ends in .sample
+ sample_files = []
for root, dirs, files in os.walk( repo_files_dir ):
if not root.find( '.hg' ) >= 0 and not root.find( 'hgrc' ) >= 0:
if '.hg' in dirs:
@@ -2426,6 +2428,10 @@
if 'hgrc' in files:
# Don't include hgrc files in commit.
files.remove( 'hgrc' )
+ # Find all special .sample files first.
+ for name in files:
+ if name.endswith( '.sample' ):
+ sample_files.append( os.path.abspath( os.path.join( root, name ) ) )
for name in files:
# Find all tool configs.
if name.endswith( '.xml' ):
@@ -2434,6 +2440,30 @@
try:
repository_tool = trans.app.toolbox.load_tool( full_path )
if repository_tool:
+ # Check all of the tool's input parameters, looking for any that are dynamically
+ # generated using external data files to make sure the files exist.
+ for input_param in repository_tool.input_params:
+ if isinstance( input_param, tools.parameters.basic.SelectToolParameter ) and input_param.is_dynamic:
+ # If the tool refers to .loc files or requires an entry in the
+ # tool_data_table_conf.xml, make sure all requirements exist.
+ options = input_param.dynamic_options or input_param.options
+ if options.missing_tool_data_table_name:
+ # The repository must contain a tool_data_table_conf.xml.sample file.
+ for sample_file in sample_files:
+ head, tail = os.path.split( sample_file )
+ if tail == 'tool_data_table_conf.xml.sample':
+ error, correction_msg = handle_sample_tool_data_table_conf_file( trans, sample_file )
+ if error:
+ log.debug( exception_msg )
+ break
+ elif options.missing_index_file:
+ missing_head, missing_tail = os.path.split( options.missing_index_file )
+ # The repository must contain the required xxx.loc.sample file.
+ for sample_file in sample_files:
+ sample_head, sample_tail = os.path.split( sample_file )
+ if sample_tail == '%s.sample' % missing_tail:
+ copy_sample_loc_file( trans, sample_file )
+ break
# At this point, we need to lstrip tool_path from relative_path.
tup_path = relative_path.replace( tool_path, '' ).lstrip( '/' )
repository_tools_tups.append( ( tup_path, repository_tool ) )
@@ -2611,6 +2641,7 @@
"""
Write an in-memory tool panel section so we can load it into the tool panel and then
append it to the appropriate shed tool config.
+ TODO: re-write using ElementTree.
"""
tmp_url = self.__clean_repository_clone_url( repository_clone_url )
section_str = ''
@@ -2632,9 +2663,7 @@
## ---- Utility methods -------------------------------------------------------
def build_shed_tool_conf_select_field( trans ):
- """
- Build a SelectField whose options are the keys in trans.app.toolbox.shed_tool_confs.
- """
+ """Build a SelectField whose options are the keys in trans.app.toolbox.shed_tool_confs."""
options = []
for shed_tool_conf_filename, tool_path in trans.app.toolbox.shed_tool_confs.items():
options.append( ( shed_tool_conf_filename.lstrip( './' ), shed_tool_conf_filename ) )
@@ -2643,9 +2672,7 @@
select_field.add_option( option_tup[0], option_tup[1] )
return select_field
def build_tool_panel_section_select_field( trans ):
- """
- Build a SelectField whose options are the sections of the current in-memory toolbox.
- """
+ """Build a SelectField whose options are the sections of the current in-memory toolbox."""
options = []
for k, tool_section in trans.app.toolbox.tool_panel.items():
options.append( ( tool_section.name, tool_section.id ) )
@@ -2653,6 +2680,14 @@
for option_tup in options:
select_field.add_option( option_tup[0], option_tup[1] )
return select_field
+def copy_sample_loc_file( trans, filename ):
+ """Copy xxx.loc.sample to ~/tool-data/xxx.loc"""
+ head, sample_loc_file = os.path.split( filename )
+ loc_file = sample_loc_file.rstrip( '.sample' )
+ tool_data_path = os.path.abspath( trans.app.config.tool_data_path )
+ if not ( os.path.exists( os.path.join( tool_data_path, loc_file ) ) or os.path.exists( os.path.join( tool_data_path, sample_loc_file ) ) ):
+ shutil.copy( os.path.abspath( filename ), os.path.join( tool_data_path, sample_loc_file ) )
+ shutil.copy( os.path.abspath( filename ), os.path.join( tool_data_path, loc_file ) )
def get_user( trans, id ):
"""Get a User from the database by id."""
# Load user from database
@@ -2683,3 +2718,45 @@
id = trans.security.decode_id( id )
quota = trans.sa_session.query( trans.model.Quota ).get( id )
return quota
+def handle_sample_tool_data_table_conf_file( trans, filename ):
+ """
+ Parse the incoming filename and add new entries to the in-memory
+ trans.app.tool_data_tables dictionary as well as appending them
+ to the shed's tool_data_table_conf.xml file on disk.
+ """
+ # Parse the incoming file and add new entries to the in-memory
+ # trans.app.tool_data_tables dictionary.
+ error = False
+ message = ''
+ try:
+ new_table_elems = trans.app.tool_data_tables.add_new_entries_from_config_file( filename )
+ except Exception, e:
+ message = str( e )
+ error = True
+ if not error:
+ # Add an entry to the end of the tool_data_table_conf.xml file.
+ tdt_config = "%s/tool_data_table_conf.xml" % trans.app.config.root
+ if os.path.exists( tdt_config ):
+ # Make a backup of the file since we're going to be changing it.
+ today = date.today()
+ backup_date = today.strftime( "%Y_%m_%d" )
+ tdt_config_copy = '%s/tool_data_table_conf.xml_%s_backup' % ( trans.app.config.root, backup_date )
+ shutil.copy( os.path.abspath( tdt_config ), os.path.abspath( tdt_config_copy ) )
+ # Write each line of the tool_data_table_conf.xml file, except the last line to a temp file.
+ fh = tempfile.NamedTemporaryFile( 'wb' )
+ tmp_filename = fh.name
+ fh.close()
+ new_tdt_config = open( tmp_filename, 'wb' )
+ for i, line in enumerate( open( tdt_config, 'rb' ) ):
+ if line.find( '</tables>' ) >= 0:
+ for new_table_elem in new_table_elems:
+ new_tdt_config.write( ' %s\n' % util.xml_to_string( new_table_elem ).rstrip( '\n' ) )
+ new_tdt_config.write( '</tables>' )
+ else:
+ new_tdt_config.write( line )
+ new_tdt_config.close()
+ shutil.move( tmp_filename, os.path.abspath( tdt_config ) )
+ else:
+ message = "The required file named tool_data_table_conf.xml does not exist in the Galaxy install directory."
+ error = True
+ return error, message
--- a/lib/galaxy/webapps/community/controllers/common.py Fri Sep 23 10:01:18 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/common.py Fri Sep 23 10:07:19 2011 -0400
@@ -163,12 +163,59 @@
repository.name,
tool.id,
tool.version )
+def check_tool_input_params( trans, name, tool, sample_files, invalid_files ):
+ """
+ Check all of the tool's input parameters, looking for any that are dynamically generated
+ using external data files to make sure the files exist.
+ """
+ can_set_metadata = True
+ correction_msg = ''
+ for input_param in tool.input_params:
+ if isinstance( input_param, galaxy.tools.parameters.basic.SelectToolParameter ) and input_param.is_dynamic:
+ # If the tool refers to .loc files or requires an entry in the
+ # tool_data_table_conf.xml, make sure all requirements exist.
+ options = input_param.dynamic_options or input_param.options
+ if options.missing_tool_data_table_name:
+ # See if the repository contains a tool_data_table_conf.xml.sample file.
+ sample_found = False
+ for sample_file in sample_files:
+ head, tail = os.path.split( sample_file )
+ if tail == 'tool_data_table_conf.xml.sample':
+ sample_found = True
+ error, correction_msg = handle_sample_tool_data_table_conf_file( trans, sample_file )
+ if error:
+ can_set_metadata = False
+ invalid_files.append( ( tail, correction_msg ) )
+ break
+ if not sample_found:
+ can_set_metadata = False
+ correction_msg = "This file requires an entry in the tool_data_table_conf.xml file. "
+ correction_msg += "Upload a file named tool_data_table_conf.xml.sample to the repository "
+ correction_msg += "that includes the required entry to resolve this issue.<br/>"
+ invalid_files.append( ( name, correction_msg ) )
+ elif options.missing_index_file:
+ missing_head, missing_tail = os.path.split( options.missing_index_file )
+ # See if the repository contains the required xxx.loc.sample file.
+ sample_found = False
+ for sample_file in sample_files:
+ sample_head, sample_tail = os.path.split( sample_file )
+ if sample_tail == '%s.sample' % missing_tail:
+ copy_sample_loc_file( trans, sample_file )
+ sample_found = True
+ break
+ if not sample_found:
+ can_set_metadata = False
+ correction_msg = "This file refers to a missing file <b>%s</b>. " % str( options.missing_index_file )
+ correction_msg += "Upload a file named <b>%s.sample</b> to the repository to correct this error." % str( missing_tail )
+ invalid_files.append( ( name, correction_msg ) )
+ return can_set_metadata, invalid_files
def generate_tool_metadata( trans, id, changeset_revision, tool_config, tool, metadata_dict ):
"""
Update the received metadata_dict with changes that have been
applied to the received tool.
"""
repository = get_repository( trans, id )
+ # Handle tool.requirements.
tool_requirements = []
for tr in tool.requirements:
name=tr.name
@@ -187,6 +234,7 @@
fabfile=fabfile,
method=method )
tool_requirements.append( requirement_dict )
+ # Handle tool.tests.
tool_tests = []
if tool.tests:
for ttb in tool.tests:
@@ -258,6 +306,7 @@
repo_dir = repository.repo_path
repo = hg.repository( get_configured_ui(), repo_dir )
invalid_files = []
+ sample_files = []
ctx = get_changectx_for_changeset( trans, repo, changeset_revision )
if ctx is not None:
metadata_dict = {}
@@ -271,6 +320,10 @@
if 'hgrc' in files:
# Don't include hgrc files in commit.
files.remove( 'hgrc' )
+ # Find all special .sample files first.
+ for name in files:
+ if name.endswith( '.sample' ):
+ sample_files.append( os.path.abspath( os.path.join( root, name ) ) )
for name in files:
# Find all tool configs.
if name.endswith( '.xml' ):
@@ -278,9 +331,11 @@
full_path = os.path.abspath( os.path.join( root, name ) )
tool = load_tool( trans, full_path )
if tool is not None:
- # Update the list metadata dictionaries for tools in metadata_dict.
- tool_config = os.path.join( root, name )
- metadata_dict = generate_tool_metadata( trans, id, changeset_revision, tool_config, tool, metadata_dict )
+ can_set_metadata, invalid_files = check_tool_input_params( trans, name, tool, sample_files, invalid_files )
+ if can_set_metadata:
+ # Update the list of metadata dictionaries for tools in metadata_dict.
+ tool_config = os.path.join( root, name )
+ metadata_dict = generate_tool_metadata( trans, id, changeset_revision, tool_config, tool, metadata_dict )
except Exception, e:
invalid_files.append( ( name, str( e ) ) )
# Find all exported workflows
@@ -297,10 +352,14 @@
except Exception, e:
invalid_files.append( ( name, str( e ) ) )
else:
+ # Find all special .sample files first.
+ for filename in ctx:
+ if filename.endswith( '.sample' ):
+ sample_files.append( os.path.abspath( os.path.join( root, filename ) ) )
# Get all tool config file names from the hgweb url, something like:
# /repos/test/convert_chars1/file/e58dcf0026c7/convert_characters.xml
for filename in ctx:
- # Find all tool configs - should not have to update metadata for workflows.
+ # Find all tool configs - should not have to update metadata for workflows for now.
if filename.endswith( '.xml' ):
fctx = ctx[ filename ]
# Write the contents of the old tool config to a temporary file.
@@ -313,12 +372,14 @@
try:
tool = load_tool( trans, tmp_filename )
if tool is not None:
- # Update the list metadata dictionaries for tools in metadata_dict. Note that filename
- # here is the relative path to the config file within the change set context, something
- # like filtering.xml, but when the change set was the repository tip, the value was
- # something like database/community_files/000/repo_1/filtering.xml. This shouldn't break
- # anything, but may result in a bit of confusion when maintaining the code / data over time.
- metadata_dict = generate_tool_metadata( trans, id, changeset_revision, filename, tool, metadata_dict )
+ can_set_metadata, invalid_files = check_tool_input_params( trans, filename, tool, sample_files, invalid_files )
+ if can_set_metadata:
+ # Update the list of metadata dictionaries for tools in metadata_dict. Note that filename
+ # here is the relative path to the config file within the change set context, something
+ # like filtering.xml, but when the change set was the repository tip, the value was
+ # something like database/community_files/000/repo_1/filtering.xml. This shouldn't break
+ # anything, but may result in a bit of confusion when maintaining the code / data over time.
+ metadata_dict = generate_tool_metadata( trans, id, changeset_revision, filename, tool, metadata_dict )
except Exception, e:
invalid_files.append( ( name, str( e ) ) )
try:
@@ -346,49 +407,26 @@
trans.sa_session.add( repository_metadata )
trans.sa_session.flush()
else:
- message = "Changeset revision '%s' includes no tools or exported workflows for which metadata can be set." % str( changeset_revision )
+ message = "Change set revision '%s' includes no tools or exported workflows for which metadata can be set." % str( changeset_revision )
status = "error"
else:
# change_set is None
- message = "Repository does not include changeset revision '%s'." % str( changeset_revision )
+ message = "Repository does not include change set revision '%s'." % str( changeset_revision )
status = 'error'
if invalid_files:
if metadata_dict:
message = "Metadata was defined for some items in change set revision '%s'. " % str( changeset_revision )
- message += "If the following files are Galaxy tool configs or exported Galaxy workflows, correct the problems and reset metadata.<br/>"
+ message += "Correct the following problems if necessary and reset metadata.<br/>"
else:
message = "Metadata cannot be defined for change set revision '%s'. Correct the following problems and reset metadata.<br/>" % str( changeset_revision )
for itc_tup in invalid_files:
- tool_file = itc_tup[0]
- exception_msg = itc_tup[1]
+ tool_file, exception_msg = itc_tup
if exception_msg.find( 'No such file or directory' ) >= 0:
exception_items = exception_msg.split()
missing_file_items = exception_items[7].split( '/' )
missing_file = missing_file_items[-1].rstrip( '\'' )
correction_msg = "This file refers to a missing file <b>%s</b>. " % str( missing_file )
- if exception_msg.find( '.loc' ) >= 0:
- # Handle the special case where a tool depends on a missing xxx.loc file by telliing
- # the user to upload xxx.loc.sample to the repository so that it can be copied to
- # ~/tool-data/xxx.loc. In this case, exception_msg will look something like:
- # [Errno 2] No such file or directory: '/Users/gvk/central/tool-data/blast2go.loc'
- sample_loc_file = '%s.sample' % str( missing_file )
- correction_msg += "Upload a file named <b>%s</b> to the repository to correct this error." % sample_loc_file
- else:
- correction_msg += "Upload a file named <b>%s</b> to the repository to correct this error." % missing_file
- elif exception_msg.find( 'Data table named' ) >= 0:
- # Handle the special case where the tool requires an entry in the tool_data_table.conf file.
- # In this case, exception_msg will look something like:
- # Data table named 'tmap_indexes' is required by tool but not configured
- exception_items = exception_msg.split()
- name_attr = exception_items[3].lstrip( '\'' ).rstrip( '\'' )
- message += "<b>%s</b> - This tool requires an entry in the tool_data_table_conf.xml file. " % tool_file
- message += "Complete and <b>Save</b> the form below to resolve this issue.<br/>"
- return trans.response.send_redirect( web.url_for( controller='repository',
- action='add_tool_data_table_entry',
- name_attr=name_attr,
- repository_id=id,
- message=message,
- status='error' ) )
+ correction_msg += "Upload a file named <b>%s</b> to the repository to correct this error." % missing_file
else:
correction_msg = exception_msg
message += "<b>%s</b> - %s<br/>" % ( tool_file, correction_msg )
@@ -410,14 +448,6 @@
if repository_metadata:
return repository_metadata.malicious
return False
-def copy_sample_loc_file( trans, filename ):
- """Copy xxx.loc.sample to ~/tool-data/xxx.loc"""
- sample_loc_file = os.path.split( filename )[1]
- loc_file = os.path.split( filename )[1].rstrip( '.sample' )
- tool_data_path = os.path.abspath( trans.app.config.tool_data_path )
- if not ( os.path.exists( os.path.join( tool_data_path, loc_file ) ) or os.path.exists( os.path.join( tool_data_path, sample_loc_file ) ) ):
- shutil.copy( os.path.abspath( filename ), os.path.join( tool_data_path, sample_loc_file ) )
- shutil.copy( os.path.abspath( filename ), os.path.join( tool_data_path, loc_file ) )
def get_configured_ui():
# Configure any desired ui settings.
_ui = ui.ui()
--- a/lib/galaxy/webapps/community/controllers/repository.py Fri Sep 23 10:01:18 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/repository.py Fri Sep 23 10:07:19 2011 -0400
@@ -1049,6 +1049,7 @@
message=message,
status=status )
@web.expose
+ @web.require_login( "set email alerts" )
def set_email_alerts( self, trans, **kwd ):
# Set email alerts for selected repositories
params = util.Params( kwd )
@@ -1113,98 +1114,6 @@
message=message,
status=status ) )
@web.expose
- def add_tool_data_table_entry( self, trans, name_attr, repository_id, **kwd ):
- params = util.Params( kwd )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- comment_char = util.restore_text( params.get( 'comment_char', '#' ) )
- loc_filename = util.restore_text( params.get( 'loc_filename', '' ) )
- repository = get_repository( trans, repository_id )
- repo = hg.repository( get_configured_ui(), repository.repo_path )
- column_fields = self.__get_column_fields( **kwd )
- if params.get( 'add_field_button', False ):
- # Add a field
- field_index = len( column_fields ) + 1
- field_tup = ( '%i_field_name' % field_index, '' )
- column_fields.append( field_tup )
- elif params.get( 'remove_button', False ):
- # Delete a field - find the index of the field to be removed from the remove button label
- index = int( kwd[ 'remove_button' ].split( ' ' )[2] ) - 1
- tup_to_remove = column_fields[ index ]
- column_fields.remove( tup_to_remove )
- # Re-number field tups
- new_column_fields = []
- for field_index, old_field_tup in enumerate( column_fields ):
- name = '%i_field_name' % ( field_index + 1 )
- value = old_field_tup[1]
- new_column_fields.append( ( name, value ) )
- column_fields = new_column_fields
- elif params.get( 'add_tool_data_table_entry_button', False ):
- # Add an entry to the end of the tool_data_table_conf.xml file
- tdt_config = "%s/tool_data_table_conf.xml" % trans.app.config.root
- if os.path.exists( tdt_config ):
- # Make a backup of the file since we're going to be changing it.
- today = date.today()
- backup_date = today.strftime( "%Y_%m_%d" )
- tdt_config_copy = '%s/tool_data_table_conf.xml_%s_backup' % ( trans.app.config.root, backup_date )
- shutil.copy( os.path.abspath( tdt_config ), os.path.abspath( tdt_config_copy ) )
- # Generate the string of column names
- column_names = ', '.join( [ column_tup[1] for column_tup in column_fields ] )
- # Write each line of the tool_data_table_conf.xml file, except the last line to a temp file.
- fh = tempfile.NamedTemporaryFile( 'wb' )
- tmp_filename = fh.name
- fh.close()
- new_tdt_config = open( tmp_filename, 'wb' )
- for i, line in enumerate( open( tdt_config, 'rb' ) ):
- if line.startswith( '</tables>' ):
- break
- new_tdt_config.write( line )
- new_tdt_config.write( ' <!-- Location of %s files -->\n' % name_attr )
- new_tdt_config.write( ' <table name="%s" comment_char="%s">\n' % ( name_attr, comment_char ) )
- new_tdt_config.write( ' <columns>%s</columns>\n' % column_names )
- new_tdt_config.write( ' <file path="tool-data/%s" />\n' % loc_filename )
- new_tdt_config.write( ' </table>\n' )
- # Now write the last line of the file
- new_tdt_config.write( '</tables>\n' )
- new_tdt_config.close()
- shutil.move( tmp_filename, os.path.abspath( tdt_config ) )
- # Reload the tool_data_table_conf entries
- trans.app.tool_data_tables = galaxy.tools.data.ToolDataTableManager( trans.app.config.tool_data_table_config_path )
- message = "The new entry has been added to the tool_data_table_conf.xml file, so click the <b>Reset metadata</b> button below."
- return trans.response.send_redirect( web.url_for( controller='repository',
- action='manage_repository',
- id=repository_id,
- message=message,
- status=status ) )
- is_malicious = change_set_is_malicious( trans, repository_id, repository.tip )
- return trans.fill_template( '/webapps/community/repository/add_tool_data_table_entry.mako',
- name_attr=name_attr,
- repository=repository,
- comment_char=comment_char,
- loc_filename=loc_filename,
- column_fields=column_fields,
- is_malicious=is_malicious,
- message=message,
- status=status )
- def __get_column_fields( self, **kwd ):
- '''
- Return a dictionary of the user-entered form fields representing columns
- in the location file.
- '''
- params = util.Params( kwd )
- column_fields = []
- index = 0
- while True:
- name = '%i_field_name' % ( index + 1 )
- if kwd.has_key( name ):
- value = util.restore_text( params.get( name, '' ) )
- field_tup = ( name, value )
- index += 1
- column_fields.append( field_tup )
- else:
- break
- return column_fields
- @web.expose
def display_tool( self, trans, repository_id, tool_config, changeset_revision, **kwd ):
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
@@ -1284,6 +1193,7 @@
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
+ display_for_install = util.string_as_bool( params.get( 'display_for_install', False ) )
repository = get_repository( trans, repository_id )
metadata = {}
tool = None
@@ -1312,6 +1222,7 @@
revision_label=revision_label,
changeset_revision_select_field=changeset_revision_select_field,
is_malicious=is_malicious,
+ display_for_install=display_for_install,
message=message,
status=status )
@web.expose
--- a/lib/galaxy/webapps/community/controllers/upload.py Fri Sep 23 10:01:18 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/upload.py Fri Sep 23 10:07:19 2011 -0400
@@ -95,6 +95,14 @@
# exception. If this happens, we'll try the following.
repo.dirstate.write()
repo.commit( user=trans.user.username, text=commit_message )
+ if full_path.endswith( 'tool_data_table_conf.xml.sample' ):
+ # Handle the special case where a tool_data_table_conf.xml.sample
+ # file is being uploaded by parsing the file and adding new entries
+ # to the in-memory trans.app.tool_data_tables dictionary as well as
+ # appending them to the shed's tool_data_table_conf.xml file on disk.
+ error, error_message = handle_sample_tool_data_table_conf_file( trans, full_path )
+ if error:
+ message = '%s<br/>%s' % ( message, error_message )
if full_path.endswith( '.loc.sample' ):
# Handle the special case where a xxx.loc.sample file is
# being uploaded by copying it to ~/tool-data/xxx.loc.
@@ -208,6 +216,14 @@
pass
for filename_in_archive in filenames_in_archive:
commands.add( repo.ui, repo, filename_in_archive )
+ if filename_in_archive.endswith( 'tool_data_table_conf.xml.sample' ):
+ # Handle the special case where a tool_data_table_conf.xml.sample
+ # file is being uploaded by parsing the file and adding new entries
+ # to the in-memory trans.app.tool_data_tables dictionary as well as
+ # appending them to the shed's tool_data_table_conf.xml file on disk.
+ error, message = handle_sample_tool_data_table_conf_file( trans, filename_in_archive )
+ if error:
+ return False, message, files_to_remove
if filename_in_archive.endswith( '.loc.sample' ):
# Handle the special case where a xxx.loc.sample file is
# being uploaded by copying it to ~/tool-data/xxx.loc.
--- a/templates/webapps/community/repository/add_tool_data_table_entry.mako Fri Sep 23 10:01:18 2011 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-<%inherit file="/base.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-
-<%
- from galaxy.web.form_builder import TextField
- is_new = repository.is_new
- can_contact_owner = trans.user and trans.user != repository.user
- can_push = trans.app.security_agent.can_push( trans.user, repository )
- can_upload = can_push
- can_download = not is_new and ( not is_malicious or can_push )
- can_browse_contents = not is_new
- can_set_metadata = not is_new
- can_rate = not is_new and trans.user and repository.user != trans.user
- can_view_change_log = not is_new
- if can_push:
- browse_label = 'Browse or delete repository files'
- else:
- browse_label = 'Browse repository files'
-%>
-
-<%def name="javascripts()">
- ${parent.javascripts()}
- <script type="text/javascript">
- $(function(){
- $("input:text:first").focus();
- })
- </script>
-</%def>
-
-<br/><br/>
-<ul class="manage-table-actions">
- %if is_new and can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
- %else:
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_rate:
- <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label}</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ), webapp='community' )}">Contact repository owner</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
- %endif
-</ul>
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-<%def name="render_field( index, field_tup )">
- <h4 class="msg_head">
- <div class="form-row">Column ${index + 1}</div>
- </h4>
- <div class="msg_body2">
- <div class="repeat-group-item">
- <div class="form-row">
- <% column_field = TextField( field_tup[0], 40, field_tup[1] ) %>
- ${column_field.get_html()}
- <div class="toolParamHelp" style="clear: both;">
- Enter the name of the location file column (e.g., value, dbkey, name, path, etc). See the tool_data_table_conf.xml file for examples.
- </div>
- </div>
- <div class="form-row">
- <input type="submit" name="remove_button" value="Remove field ${index + 1}"/>
- </div>
- </div>
- </div>
-</%def>
-
-<div class="toolForm">
- <div class="toolFormTitle">Add tool data table entry</div>
- <div class="toolFormBody">
- <form name="add_tool_data_table_entry" id="add_tool_data_table_entry" action="${h.url_for( controller='repository', action='add_tool_data_table_entry', name_attr=name_attr, repository_id=trans.security.encode_id( repository.id ) )}" method="post" >
- <div class="form-row">
- <label>Table name:</label>
- ${name_attr}
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Comment lines begin with:</label>
- <input name="comment_char" type="textfield" value="${comment_char}" size="8"/>
- <div class="toolParamHelp" style="clear: both;">
- Enter the character that designates comments lines in the location file (default is #).
- </div>
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Location file name:</label>
- <input name="loc_filename" type="textfield" value="${loc_filename}" size="80"/>
- <div class="toolParamHelp" style="clear: both;">
- Enter the name of the location file (e.g., bwa_index.loc).
- </div>
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <label>Location file columns:</label>
- </div>
- %for ctr, field_tup in enumerate( column_fields ):
- ${render_field( ctr, field_tup )}
- %endfor
- <div class="form-row">
- <input type="submit" name="add_field_button" value="Add field"/>
- </div>
- <div class="form-row">
- <input type="submit" name="add_tool_data_table_entry_button" value="Save"/>
- </div>
- </form>
- </div>
-</div>
--- a/templates/webapps/community/repository/view_tool_metadata.mako Fri Sep 23 10:01:18 2011 -0400
+++ b/templates/webapps/community/repository/view_tool_metadata.mako Fri Sep 23 10:07:19 2011 -0400
@@ -33,34 +33,38 @@
<br/><br/><ul class="manage-table-actions">
- %if is_new:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
+ %if display_for_install:
+ <a class="action-button" href="${h.url_for( controller='repository', action='install_repository_revision', repository_id=trans.security.encode_id( repository.id ), webapp='community', changeset_revision=changeset_revision )}">Install to local Galaxy</a>
%else:
- <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
- <div popupmenu="repository-${repository.id}-popup">
- %if can_manage:
- <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Manage repository</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View repository</a>
- %endif
- %if can_upload:
- <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
- %endif
- %if can_view_change_log:
- <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
- %endif
- %if can_browse_contents:
- <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label}</a>
- %endif
- %if can_contact_owner:
- <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ), webapp='community' )}">Contact repository owner</a>
- %endif
- %if can_download:
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz' )}">Download as a .tar.gz file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2' )}">Download as a .tar.bz2 file</a>
- <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip' )}">Download as a zip file</a>
- %endif
- </div>
+ %if is_new:
+ <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
+ %else:
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ %if can_manage:
+ <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">Manage repository</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision )}">View repository</a>
+ %endif
+ %if can_upload:
+ <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
+ %endif
+ %if can_view_change_log:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ) )}">View change log</a>
+ %endif
+ %if can_browse_contents:
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ) )}">${browse_label}</a>
+ %endif
+ %if can_contact_owner:
+ <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ), webapp='community' )}">Contact repository owner</a>
+ %endif
+ %if can_download:
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz' )}">Download as a .tar.gz file</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2' )}">Download as a .tar.bz2 file</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip' )}">Download as a zip file</a>
+ %endif
+ </div>
+ %endif
%endif
</ul>
@@ -72,7 +76,7 @@
<div class="toolFormTitle">Repository revision</div><div class="toolFormBody">
%if len( changeset_revision_select_field.options ) > 1:
- <form name="change_revision" id="change_revision" action="${h.url_for( controller='repository', action='view_tool_metadata', repository_id=trans.security.encode_id( repository.id ), tool_id=metadata[ 'id' ] )}" method="post" >
+ <form name="change_revision" id="change_revision" action="${h.url_for( controller='repository', action='view_tool_metadata', repository_id=trans.security.encode_id( repository.id ), tool_id=metadata[ 'id' ], display_for_install=display_for_install )}" method="post" ><div class="form-row"><%
if changeset_revision == repository.tip:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/898f4f57223d/
changeset: 898f4f57223d
user: greg
date: 2011-09-23 16:01:18
summary: Add 2 new attributes to dynamically generated select lists; "missing_tool_data_table_name" will include a value (e.g., tmap_indexes) if the select list requires a missing entry in the tool_data_table_conf.xml file, and "missing_index_file" will include a value (e.g., tmap_indexes.loc) if the select list requires a missing index file. Tools that used to not load in index files were missing will now load, although they will not properly execute. Work remaining is for a check to be performed against these new "missing" attributes and a message displayed on the tool form - not quite sure if this should be a validator or not...
Define a list in the Tool class to keep track of all input parameters (tool.input_params). These differ from the inputs dictionary (tool.inputs) in that inputs can be page elements like conditionals, but input_params are basic parameters like SelectField objects. This enables us to more easily ensure that parameter dependencies like index files or tool_data_table_conf.xml entries exist.
Add the ability to append new entries into the tool_data_table_conf.xml file in real time and add the same entries into the in-memory tool_data_tables dictionary.
affected #: 4 files (-1 bytes)
--- a/lib/galaxy/tools/__init__.py Fri Sep 23 09:36:57 2011 -0400
+++ b/lib/galaxy/tools/__init__.py Fri Sep 23 10:01:18 2011 -0400
@@ -360,13 +360,18 @@
tool_type = 'default'
def __init__( self, config_file, root, app, guid=None ):
- """
- Load a tool from the config named by `config_file`
- """
+ """Load a tool from the config named by `config_file`"""
# Determine the full path of the directory where the tool config is
self.config_file = config_file
self.tool_dir = os.path.dirname( config_file )
self.app = app
+ # Define a place to keep track of all input parameters. These
+ # differ from the inputs dictionary in that inputs can be page
+ # elements like conditionals, but input_params are basic form
+ # parameters like SelectField objects. This enables us to more
+ # easily ensure that parameter dependencies like index files or
+ # tool_data_table_conf.xml entries exist.
+ self.input_params = []
# Parse XML element containing configuration
self.parse( root, guid=guid )
@@ -698,7 +703,6 @@
name = attrib.pop( 'name', None )
if name is None:
raise Exception( "Test output does not have a 'name'" )
-
assert_elem = output_elem.find("assert_contents")
assert_list = None
# Trying to keep testing patch as localized as
@@ -713,13 +717,10 @@
for child_elem in child_elems:
converted_children.append( convert_elem(child_elem) )
return {"tag" : tag, "attributes" : attributes, "children" : converted_children}
-
if assert_elem is not None:
assert_list = []
for assert_child in list(assert_elem):
assert_list.append(convert_elem(assert_child))
-
-
file = attrib.pop( 'file', None )
# File no longer required if an list of assertions was present.
if assert_list is None and file is None:
@@ -734,8 +735,6 @@
attributes['sort'] = util.string_as_bool( attrib.pop( 'sort', False ) )
attributes['extra_files'] = []
attributes['assert_list'] = assert_list
-
-
if 'ftype' in attrib:
attributes['ftype'] = attrib['ftype']
for extra in output_elem.findall( 'extra_files' ):
@@ -862,6 +861,7 @@
rval[param.name] = param
if hasattr( param, 'data_ref' ):
param.ref_input = context[ param.data_ref ]
+ self.input_params.append( param )
return rval
def parse_param_elem( self, input_elem, enctypes, context ):
--- a/lib/galaxy/tools/data/__init__.py Fri Sep 23 09:36:57 2011 -0400
+++ b/lib/galaxy/tools/data/__init__.py Fri Sep 23 10:01:18 2011 -0400
@@ -12,34 +12,64 @@
log = logging.getLogger( __name__ )
class ToolDataTableManager( object ):
- """
- Manages a collection of tool data tables
- """
-
+ """Manages a collection of tool data tables"""
def __init__( self, config_filename=None ):
self.data_tables = {}
if config_filename:
- self.add_from_config_file( config_filename )
-
+ self.load_from_config_file( config_filename )
def __getitem__( self, key ):
return self.data_tables.__getitem__( key )
-
def __contains__( self, key ):
return self.data_tables.__contains__( key )
-
- def add_from_config_file( self, config_filename ):
+ def load_from_config_file( self, config_filename ):
tree = util.parse_xml( config_filename )
root = tree.getroot()
+ table_elems = []
for table_elem in root.findall( 'table' ):
type = table_elem.get( 'type', 'tabular' )
assert type in tool_data_table_types, "Unknown data table type '%s'" % type
+ table_elems.append( table_elem )
table = tool_data_table_types[ type ]( table_elem )
- self.data_tables[ table.name ] = table
- log.debug( "Loaded tool data table '%s", table.name )
+ if table.name not in self.data_tables:
+ self.data_tables[ table.name ] = table
+ log.debug( "Loaded tool data table '%s", table.name )
+ return table_elems
+ def add_new_entries_from_config_file( self, config_filename ):
+ """
+ We have 2 cases to handle, files whose root tag is <tables>, for example:
+ <tables>
+ <!-- Location of Tmap files -->
+ <table name="tmap_indexes" comment_char="#">
+ <columns>value, dbkey, name, path</columns>
+ <file path="tool-data/tmap_index.loc" />
+ </table>
+ </tables>
+ and files whose root tag is <table>, for example:
+ <!-- Location of Tmap files -->
+ <table name="tmap_indexes" comment_char="#">
+ <columns>value, dbkey, name, path</columns>
+ <file path="tool-data/tmap_index.loc" />
+ </table>
+ """
+ tree = util.parse_xml( config_filename )
+ root = tree.getroot()
+ if root.tag == 'tables':
+ table_elems = self.load_from_config_file( config_filename )
+ else:
+ table_elems = []
+ type = root.get( 'type', 'tabular' )
+ assert type in tool_data_table_types, "Unknown data table type '%s'" % type
+ table_elems.append( root )
+ table = tool_data_table_types[ type ]( root )
+ if table.name not in self.data_tables:
+ self.data_tables[ table.name ] = table
+ log.debug( "Loaded tool data table '%s", table.name )
+ return table_elems
class ToolDataTable( object ):
def __init__( self, config_element ):
self.name = config_element.get( 'name' )
+ self.missing_index_file = None
class TabularToolDataTable( ToolDataTable ):
"""
@@ -58,7 +88,6 @@
def __init__( self, config_element ):
super( TabularToolDataTable, self ).__init__( config_element )
self.configure_and_load( config_element )
-
def configure_and_load( self, config_element ):
"""
Configure and load table from an XML element.
@@ -71,15 +100,14 @@
all_rows = []
for file_element in config_element.findall( 'file' ):
filename = file_element.get( 'path' )
- if not os.path.exists( filename ):
+ if os.path.exists( filename ):
+ all_rows.extend( self.parse_file_fields( open( filename ) ) )
+ else:
+ self.missing_index_file = filename
log.warn( "Cannot find index file '%s' for tool data table '%s'" % ( filename, self.name ) )
- else:
- all_rows.extend( self.parse_file_fields( open( filename ) ) )
self.data = all_rows
-
def get_fields( self ):
return self.data
-
def parse_column_spec( self, config_element ):
"""
Parse column definitions, which can either be a set of 'column' elements
@@ -109,7 +137,6 @@
assert 'value' in self.columns, "Required 'value' column missing from column def"
if 'name' not in self.columns:
self.columns['name'] = self.columns['value']
-
def parse_file_fields( self, reader ):
"""
Parse separated lines from file and return a list of tuples.
--- a/lib/galaxy/tools/parameters/dynamic_options.py Fri Sep 23 09:36:57 2011 -0400
+++ b/lib/galaxy/tools/parameters/dynamic_options.py Fri Sep 23 10:01:18 2011 -0400
@@ -399,23 +399,29 @@
self.separator = elem.get( 'separator', '\t' )
self.line_startswith = elem.get( 'startswith', None )
data_file = elem.get( 'from_file', None )
+ self.missing_index_file = None
dataset_file = elem.get( 'from_dataset', None )
from_parameter = elem.get( 'from_parameter', None )
tool_data_table_name = elem.get( 'from_data_table', None )
-
# Options are defined from a data table loaded by the app
self.tool_data_table = None
+ self.missing_tool_data_table_name = None
if tool_data_table_name:
app = tool_param.tool.app
- assert tool_data_table_name in app.tool_data_tables, \
- "Data table named '%s' is required by tool but not configured" % tool_data_table_name
- self.tool_data_table = app.tool_data_tables[ tool_data_table_name ]
- # Column definitions are optional, but if provided override those from the table
- if elem.find( "column" ) is not None:
- self.parse_column_definitions( elem )
+ if tool_data_table_name in app.tool_data_tables:
+ self.tool_data_table = app.tool_data_tables[ tool_data_table_name ]
+ # Set self.missing_index_file if the index file to
+ # which the tool_data_table refers does not exist.
+ if self.tool_data_table.missing_index_file:
+ self.missing_index_file = self.tool_data_table.missing_index_file
+ # Column definitions are optional, but if provided override those from the table
+ if elem.find( "column" ) is not None:
+ self.parse_column_definitions( elem )
+ else:
+ self.columns = self.tool_data_table.columns
else:
- self.columns = self.tool_data_table.columns
-
+ self.missing_tool_data_table_name = tool_data_table_name
+ log.warn( "Data table named '%s' is required by tool but not configured" % tool_data_table_name )
# Options are defined by parsing tabular text data from an data file
# on disk, a dataset, or the value of another parameter
elif data_file is not None or dataset_file is not None or from_parameter is not None:
@@ -423,8 +429,11 @@
if data_file is not None:
data_file = data_file.strip()
if not os.path.isabs( data_file ):
- data_file = os.path.join( self.tool_param.tool.app.config.tool_data_path, data_file )
- self.file_fields = self.parse_file_fields( open( data_file ) )
+ full_path = os.path.join( self.tool_param.tool.app.config.tool_data_path, data_file )
+ if os.path.exists( full_path ):
+ self.file_fields = self.parse_file_fields( open( full_path ) )
+ else:
+ self.missing_index_file = data_file
elif dataset_file is not None:
self.dataset_ref_name = dataset_file
self.has_dataset_dependencies = True
--- a/lib/galaxy/tools/parameters/output.py Fri Sep 23 09:36:57 2011 -0400
+++ b/lib/galaxy/tools/parameters/output.py Fri Sep 23 10:01:18 2011 -0400
@@ -206,13 +206,16 @@
super( FromDataTableOutputActionOption, self ).__init__( parent, elem )
self.name = elem.get( 'name', None )
assert self.name is not None, "Required 'name' attribute missing from FromDataTableOutputActionOption"
- assert self.name in self.tool.app.tool_data_tables, "Data table named '%s' is required by tool but not configured" % self.name
- self.options = self.tool.app.tool_data_tables[ self.name ].get_fields()
- self.column = elem.get( 'column', None )
- assert self.column is not None, "Required 'column' attribute missing from FromDataTableOutputActionOption"
- self.column = int( self.column )
- self.offset = elem.get( 'offset', -1 )
- self.offset = int( self.offset )
+ self.missing_tool_data_table_name = None
+ if self.name in self.tool.app.tool_data_tables:
+ self.options = self.tool.app.tool_data_tables[ self.name ].get_fields()
+ self.column = elem.get( 'column', None )
+ assert self.column is not None, "Required 'column' attribute missing from FromDataTableOutputActionOption"
+ self.column = int( self.column )
+ self.offset = elem.get( 'offset', -1 )
+ self.offset = int( self.offset )
+ else:
+ self.missing_tool_data_table_name = self.name
def get_value( self, other_values ):
options = self.options
for filter in self.filters:
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: dan: MAF stats tool will now skip intervals with length less 1.
by Bitbucket 23 Sep '11
by Bitbucket 23 Sep '11
23 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/c3680f58e97d/
changeset: c3680f58e97d
user: dan
date: 2011-09-23 15:36:57
summary: MAF stats tool will now skip intervals with length less 1.
affected #: 1 file (-1 bytes)
--- a/tools/maf/maf_stats.py Fri Sep 23 08:39:53 2011 -0400
+++ b/tools/maf/maf_stats.py Fri Sep 23 09:36:57 2011 -0400
@@ -55,12 +55,16 @@
out = open(output_filename, 'w')
num_region = None
+ num_bad_region = 0
species_summary = {}
total_length = 0
#loop through interval file
for num_region, region in enumerate( bx.intervals.io.NiceReaderWrapper( open( input_interval_filename, 'r' ), chrom_col = chr_col, start_col = start_col, end_col = end_col, fix_strand = True, return_header = False, return_comments = False ) ):
src = "%s.%s" % ( dbkey, region.chrom )
region_length = region.end - region.start
+ if region_length < 1:
+ num_bad_region += 1
+ continue
total_length += region_length
coverage = { dbkey: BitSet( region_length ) }
@@ -99,6 +103,8 @@
out.close()
if num_region is not None:
print "%i regions were processed with a total length of %i." % ( num_region + 1, total_length )
+ if num_bad_region:
+ print "%i regions were invalid." % ( num_bad_region )
maf_utilities.remove_temp_index_file( index_filename )
if __name__ == "__main__": __main__()
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: natefoo: This is what I get for making one "inconsequential" change after running the tests. =/
by Bitbucket 23 Sep '11
by Bitbucket 23 Sep '11
23 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/070ac69b2283/
changeset: 070ac69b2283
user: natefoo
date: 2011-09-23 14:39:53
summary: This is what I get for making one "inconsequential" change after running the tests. =/
affected #: 1 file (-1 bytes)
--- a/lib/galaxy/web/base/controller.py Thu Sep 22 17:13:53 2011 -0400
+++ b/lib/galaxy/web/base/controller.py Fri Sep 23 08:39:53 2011 -0400
@@ -44,35 +44,35 @@
def get_class( self, class_name ):
""" Returns the class object that a string denotes. Without this method, we'd have to do eval(<class_name>). """
if class_name == 'History':
- item_class = trans.model.History
+ item_class = self.app.model.History
elif class_name == 'HistoryDatasetAssociation':
- item_class = trans.model.HistoryDatasetAssociation
+ item_class = self.app.model.HistoryDatasetAssociation
elif class_name == 'Page':
- item_class = trans.model.Page
+ item_class = self.app.model.Page
elif class_name == 'StoredWorkflow':
- item_class = trans.model.StoredWorkflow
+ item_class = self.app.model.StoredWorkflow
elif class_name == 'Visualization':
- item_class = trans.model.Visualization
+ item_class = self.app.model.Visualization
elif class_name == 'Tool':
- item_class = trans.model.Tool
+ item_class = self.app.model.Tool
elif class_name == 'Job':
- item_class = trans.model.Job
+ item_class = self.app.model.Job
elif class_name == 'User':
- item_class = trans.model.User
+ item_class = self.app.model.User
elif class_name == 'Group':
- item_class = trans.model.Group
+ item_class = self.app.model.Group
elif class_name == 'Role':
- item_class = trans.model.Role
+ item_class = self.app.model.Role
elif class_name == 'Quota':
- item_class = trans.model.Quota
+ item_class = self.app.model.Quota
elif class_name == 'Library':
- item_class = trans.model.Library
+ item_class = self.app.model.Library
elif class_name == 'LibraryFolder':
- item_class = trans.model.LibraryFolder
+ item_class = self.app.model.LibraryFolder
elif class_name == 'LibraryDatasetDatasetAssociation':
- item_class = trans.model.LibraryDatasetDatasetAssociation
+ item_class = self.app.model.LibraryDatasetDatasetAssociation
elif class_name == 'LibraryDataset':
- item_class = trans.model.LibraryDataset
+ item_class = self.app.model.LibraryDataset
else:
item_class = None
return item_class
@@ -90,7 +90,8 @@
item = trans.sa_session.query( item_class ).get( decoded_id )
assert item is not None
except:
- raise MessageException( "Invalid %s id ( %s ) specified" % ( class_name, display_id ), type="error" )
+ log.exception( "Invalid %s id ( %s ) specified" % ( class_name, id ) )
+ raise MessageException( "Invalid %s id ( %s ) specified" % ( class_name, id ), type="error" )
if check_ownership or check_accessible:
self.security_check( trans, item, check_ownership, check_accessible, encoded_id )
if deleted == True and not item.deleted:
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: natefoo: Abstraction for web methods, implemented for the Quota operations and the
by Bitbucket 22 Sep '11
by Bitbucket 22 Sep '11
22 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/61cf27e60560/
changeset: 61cf27e60560
user: natefoo
date: 2011-09-22 23:13:53
summary: Abstraction for web methods, implemented for the Quota operations and the
framework is there for everything else now. Works like this:
* If your form/API params are the same across all forms for a model object
(e.g. all Quota operations), they should be placed in mixins in
galaxy.web.params and can be used universally by both the UI and API.
* Validating params and performing the requestion actions go in mixins in
galaxy.actions. These return a value upon success or raise a
MessageException upon failure.
* Fetching objects with checks relevant to the web methods can be done via
BaseController.get_object and its wrappers (see other helpers in the
Mixins in galaxy.web.base.controller as well).
* This leaves UI controller methods to just handle the stuff related to
filling in web forms.
* The API methods should be making use of paste.httpexceptions.* for
handling error conditions. Also, I think it'd be best to generally
return an item's API value from most methods and include the "message" as
an entry in the return dict rather than just by itself as a string.
None of this is required, but it would be great to convert the existing stuff
to this new model.
galaxy.exceptions is a collection point for all custom exceptions.
The User API now returns current disk usage with a User's detailed information.
Exceptions in the API are now logged by the expose_api decorator and hidden
from the client.
affected #: 56 files (-1 bytes)
--- a/lib/galaxy/model/__init__.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/model/__init__.py Thu Sep 22 17:13:53 2011 -0400
@@ -47,7 +47,7 @@
class User( object, APIItem ):
api_collection_visible_keys = ( 'id', 'email' )
- api_element_visible_keys = ( 'id', 'email', 'username' )
+ api_element_visible_keys = ( 'id', 'email', 'username', 'total_disk_usage', 'nice_total_disk_usage' )
def __init__( self, email=None, password=None ):
self.email = email
self.password = password
@@ -82,6 +82,9 @@
def set_disk_usage( self, bytes ):
self.disk_usage = bytes
total_disk_usage = property( get_disk_usage, set_disk_usage )
+ @property
+ def nice_total_disk_usage( self ):
+ return self.get_disk_usage( nice_size=True )
def calculate_disk_usage( self ):
dataset_ids = []
total = 0
--- a/lib/galaxy/quota/__init__.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/quota/__init__.py Thu Sep 22 17:13:53 2011 -0400
@@ -33,6 +33,8 @@
return usage
def get_percent( self, trans=None, user=False, history=False, usage=False, quota=False ):
return None
+ def get_user_quotas( self, user ):
+ return []
class QuotaAgent( NoQuotaAgent ):
"""Class that handles galaxy quotas"""
@@ -150,3 +152,20 @@
gqa = self.model.GroupQuotaAssociation( group, quota )
self.sa_session.add( gqa )
self.sa_session.flush()
+ def get_user_quotas( self, user ):
+ rval = []
+ if not user:
+ dqa = self.sa_session.query( self.model.DefaultQuotaAssociation ) \
+ .filter( self.model.DefaultQuotaAssociation.table.c.type==self.model.DefaultQuotaAssociation.types.UNREGISTERED ).first()
+ if dqa:
+ rval.append( dqa.quota )
+ else:
+ dqa = self.sa_session.query( self.model.DefaultQuotaAssociation ) \
+ .filter( self.model.DefaultQuotaAssociation.table.c.type==self.model.DefaultQuotaAssociation.types.REGISTERED ).first()
+ if dqa:
+ rval.append( dqa.quota )
+ for uqa in user.quotas:
+ rval.append( uqa.quota )
+ for gqa in [ uga.group for uga in user.groups ]:
+ rval.append( gqa.quota )
+ return rval
--- a/lib/galaxy/util/__init__.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/util/__init__.py Thu Sep 22 17:13:53 2011 -0400
@@ -179,7 +179,7 @@
return default
return out
-class Params:
+class Params( object ):
"""
Stores and 'sanitizes' parameters. Alphanumeric characters and the
non-alphanumeric ones that are deemed safe are let to pass through (see L{valid_chars}).
--- a/lib/galaxy/web/api/forms.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/api/forms.py Thu Sep 22 17:13:53 2011 -0400
@@ -2,14 +2,14 @@
API operations on FormDefinition objects.
"""
import logging
-from galaxy.web.base.controller import BaseController, url_for
+from galaxy.web.base.controller import BaseAPIController, url_for
from galaxy import web
from galaxy.forms.forms import form_factory
from elementtree.ElementTree import XML
log = logging.getLogger( __name__ )
-class FormDefinitionAPIController( BaseController ):
+class FormDefinitionAPIController( BaseAPIController ):
@web.expose_api
def index( self, trans, **kwd ):
--- a/lib/galaxy/web/api/histories.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/api/histories.py Thu Sep 22 17:13:53 2011 -0400
@@ -9,22 +9,23 @@
from galaxy.model.orm import *
import galaxy.datatypes
from galaxy.util.bunch import Bunch
-from galaxy.web.api.util import *
log = logging.getLogger( __name__ )
-class HistoriesController( BaseController ):
+class HistoriesController( BaseAPIController, UsesHistory ):
@web.expose_api
- def index( self, trans, **kwd ):
+ def index( self, trans, deleted='False', **kwd ):
"""
GET /api/histories
+ GET /api/histories/deleted
Displays a collection (list) of histories.
"""
rval = []
+ deleted = util.string_as_bool( deleted )
- try:
- query = trans.sa_session.query( trans.app.model.History ).filter_by( user=trans.user, deleted=False ).order_by(
+ try:
+ query = trans.sa_session.query( trans.app.model.History ).filter_by( user=trans.user, deleted=deleted ).order_by(
desc(trans.app.model.History.table.c.update_time)).all()
except Exception, e:
rval = "Error in history API"
@@ -44,13 +45,15 @@
return rval
@web.expose_api
- def show( self, trans, id, **kwd ):
+ def show( self, trans, id, deleted='False', **kwd ):
"""
GET /api/histories/{encoded_history_id}
+ GET /api/histories/deleted/{encoded_history_id}
Displays information about a history.
"""
history_id = id
params = util.Params( kwd )
+ deleted = util.string_as_bool( deleted )
def traverse( datasets ):
rval = {}
@@ -64,7 +67,7 @@
return rval
try:
- history = get_history_for_access( trans, history_id )
+ history = self.get_history( trans, history_id, check_ownership=True, check_accessible=True, deleted=deleted )
except Exception, e:
return str( e )
@@ -124,7 +127,7 @@
purge = util.string_as_bool( kwd['payload'].get( 'purge', False ) )
try:
- history = get_history_for_modification( trans, history_id )
+ history = self.get_history( trans, history_id, check_ownership=True, check_accessible=False, deleted=True )
except Exception, e:
return str( e )
@@ -146,3 +149,15 @@
trans.sa_session.flush()
return 'OK'
+
+ @web.expose_api
+ def undelete( self, trans, id, **kwd ):
+ """
+ POST /api/histories/deleted/{encoded_quota_id}/undelete
+ Undeletes a quota
+ """
+ history = self.get_history( trans, history_id, check_ownership=True, check_accessible=False, deleted=True )
+ history.deleted = False
+ trans.sa_session.add( history )
+ trans.sa_session.flush()
+ return 'OK'
--- a/lib/galaxy/web/api/history_contents.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/api/history_contents.py Thu Sep 22 17:13:53 2011 -0400
@@ -7,7 +7,6 @@
from galaxy.web.base.controller import *
from galaxy.util.sanitize_html import sanitize_html
from galaxy.model.orm import *
-from galaxy.web.api.util import *
import pkg_resources
pkg_resources.require( "Routes" )
@@ -15,7 +14,7 @@
log = logging.getLogger( __name__ )
-class HistoryContentsController( BaseController ):
+class HistoryContentsController( BaseAPIController, UsesHistoryDatasetAssociation, UsesHistory ):
@web.expose_api
def index( self, trans, history_id, **kwd ):
@@ -24,7 +23,7 @@
Displays a collection (list) of history contents
"""
try:
- history = get_history_for_access( trans, history_id )
+ history = self.get_history( trans, history_id, check_ownership=True, check_accessible=True )
except Exception, e:
return str( e )
@@ -51,7 +50,7 @@
"""
content_id = id
try:
- content = get_history_content_for_access( trans, content_id )
+ content = self.get_history_dataset_association( trans, content_id, check_ownership=True, check_accessible=True )
except Exception, e:
return str( e )
try:
@@ -63,7 +62,7 @@
# http://routes.groovie.org/generating.html
# url_for is being phased out, so new applications should use url
item['download_url'] = url(controller='dataset', action='display', dataset_id=trans.security.encode_id(content.id), to_ext=content.ext)
- item = encode_all_ids( trans, item )
+ item = self.encode_all_ids( trans, item )
except Exception, e:
item = "Error in history API at listing dataset"
log.error( item + ": %s" % str(e) )
@@ -80,7 +79,7 @@
from_ld_id = payload.get( 'from_ld_id', None )
try:
- history = get_history_for_modification( trans, history_id )
+ history = self.get_history( trans, history_id, check_ownership=True, check_accessible=False )
except Exception, e:
return str( e )
--- a/lib/galaxy/web/api/libraries.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/api/libraries.py Thu Sep 22 17:13:53 2011 -0400
@@ -10,7 +10,7 @@
log = logging.getLogger( __name__ )
-class LibrariesController( BaseController ):
+class LibrariesController( BaseAPIController ):
@web.expose_api
def index( self, trans, **kwd ):
--- a/lib/galaxy/web/api/library_contents.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/api/library_contents.py Thu Sep 22 17:13:53 2011 -0400
@@ -7,11 +7,10 @@
from galaxy.web.base.controller import *
from galaxy.util.sanitize_html import sanitize_html
from galaxy.model.orm import *
-from galaxy.web.api.util import *
log = logging.getLogger( __name__ )
-class LibraryContentsController( BaseController ):
+class LibraryContentsController( BaseAPIController, UsesLibrary, UsesLibraryItems ):
@web.expose_api
def index( self, trans, library_id, **kwd ):
@@ -74,12 +73,12 @@
GET /api/libraries/{encoded_library_id}/contents/{encoded_content_id}
Displays information about a library content (file or folder).
"""
- content_id = id
- try:
- content = get_library_content_for_access( trans, content_id )
- except Exception, e:
- return str( e )
- return encode_all_ids( trans, content.get_api_value( view='element' ) )
+ class_name, content_id = self.__decode_library_content_id( trans, id )
+ if class_name == 'LibraryFolder':
+ content = self.get_library_folder( trans, content_id, check_ownership=False, check_accessibility=True )
+ else:
+ content = self.get_library_dataset( trans, content_id, check_ownership=False, check_accessibility=True )
+ return self.encode_all_ids( trans, content.get_api_value( view='element' ) )
@web.expose_api
def create( self, trans, library_id, payload, **kwd ):
@@ -102,8 +101,8 @@
else:
folder_id = payload.pop( 'folder_id' )
try:
- # _for_modification is not necessary, that security happens in the library_common controller.
- parent = get_library_folder_for_access( trans, library_id, folder_id )
+ # security is checked in the downstream controller
+ parent = self.get_library_folder( trans, folder_id, check_ownership=False, check_accessibility=False )
except Exception, e:
return str( e )
# The rest of the security happens in the library_common controller.
@@ -128,3 +127,11 @@
name = v.name,
url = url_for( 'library_content', library_id=library_id, id=encoded_id ) ) )
return rval
+
+ def __decode_library_content_id( self, trans, content_id ):
+ if ( len( content_id ) % 16 == 0 ):
+ return 'LibraryDataset', content_id
+ elif ( content_id.startswith( 'F' ) ):
+ return 'LibraryFolder', content_id[1:]
+ else:
+ raise HTTPBadRequest( 'Malformed library content id ( %s ) specified, unable to decode.' % str( content_id ) )
--- a/lib/galaxy/web/api/permissions.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/api/permissions.py Thu Sep 22 17:13:53 2011 -0400
@@ -10,7 +10,7 @@
log = logging.getLogger( __name__ )
-class PermissionsController( BaseController ):
+class PermissionsController( BaseAPIController ):
# Method not ideally named
@web.expose_api
--- a/lib/galaxy/web/api/quotas.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/api/quotas.py Thu Sep 22 17:13:53 2011 -0400
@@ -2,24 +2,29 @@
API operations on Quota objects.
"""
import logging
-from galaxy.web.base.controller import BaseController, url_for
+from galaxy.web.base.controller import BaseAPIController, Admin, UsesQuota, url_for
from galaxy import web, util
from elementtree.ElementTree import XML
-from galaxy.web.api.util import *
+
+from galaxy.web.params import QuotaParamParser
+from galaxy.actions.admin import AdminActions
+
+from paste.httpexceptions import HTTPBadRequest
+from galaxy.exceptions import *
log = logging.getLogger( __name__ )
-class QuotaAPIController( BaseController ):
+class QuotaAPIController( BaseAPIController, Admin, AdminActions, UsesQuota, QuotaParamParser ):
@web.expose_api
@web.require_admin
- def index( self, trans, deleted=False, **kwd ):
+ def index( self, trans, deleted='False', **kwd ):
"""
GET /api/quotas
GET /api/quotas/deleted
Displays a collection (list) of quotas.
"""
- #return str( trans.webapp.api_mapper )
rval = []
+ deleted = util.string_as_bool( deleted )
query = trans.sa_session.query( trans.app.model.Quota )
if deleted:
route = 'deleted_quota'
@@ -36,16 +41,13 @@
@web.expose_api
@web.require_admin
- def show( self, trans, id, deleted=False, **kwd ):
+ def show( self, trans, id, deleted='False', **kwd ):
"""
GET /api/quotas/{encoded_quota_id}
GET /api/quotas/deleted/{encoded_quota_id}
Displays information about a quota.
"""
- try:
- quota = get_quota_for_access( trans, id, deleted=deleted )
- except BadRequestException, e:
- return str( e )
+ quota = self.get_quota( trans, id, deleted=util.string_as_bool( deleted ) )
return quota.get_api_value( view='element', value_mapper={ 'id': trans.security.encode_id } )
@web.expose_api
@@ -56,20 +58,18 @@
Creates a new quota.
"""
try:
- self._validate_in_users_and_groups( trans, payload )
+ self.validate_in_users_and_groups( trans, payload )
except Exception, e:
- trans.response.status = 400
- return str( e )
-
- status, result = trans.webapp.controllers['admin'].create_quota( trans, cntrller='api', **payload )
- if status != 200 or type( result ) != trans.app.model.Quota:
- trans.response.status = status
- return str( result )
- else:
- encoded_id = trans.security.encode_id( result.id )
- return dict( id = encoded_id,
- name = result.name,
- url = url_for( 'quotas', id=encoded_id ) )
+ raise HTTPBadRequest( detail=str( e ) )
+ params = self.get_quota_params( payload )
+ try:
+ quota, message = self._create_quota( params )
+ except ActionInputError, e:
+ raise HTTPBadRequest( detail=str( e ) )
+ item = quota.get_api_value( value_mapper={ 'id': trans.security.encode_id } )
+ item['url'] = url_for( 'quota', id=trans.security.encode_id( quota.id ) )
+ item['message'] = message
+ return item
@web.expose_api
@web.require_admin
@@ -79,32 +79,34 @@
Modifies a quota.
"""
try:
- self._validate_in_users_and_groups( trans, payload )
- quota = get_quota_for_access( trans, id, deleted=False ) # deleted quotas are not technically members of this collection
+ self.validate_in_users_and_groups( trans, payload )
except Exception, e:
- trans.response.status = 400
- return str( e )
- # TODO: Doing it this way makes the update non-atomic if a method fails after an earlier one has succeeded.
+ raise HTTPBadRequest( detail=str( e ) )
+
+ quota = self.get_quota( trans, id, deleted=False )
+
+ # FIXME: Doing it this way makes the update non-atomic if a method fails after an earlier one has succeeded.
payload['id'] = id
+ params = self.get_quota_params( payload )
methods = []
if payload.get( 'name', None ) or payload.get( 'description', None ):
- methods.append( trans.webapp.controllers['admin'].rename_quota )
+ methods.append( self._rename_quota )
if payload.get( 'amount', None ):
- methods.append( trans.webapp.controllers['admin'].edit_quota )
+ methods.append( self._edit_quota )
if payload.get( 'default', None ) == 'no':
- methods.append( trans.webapp.controllers['admin'].unset_quota_default )
+ methods.append( self._unset_quota_default )
elif payload.get( 'default', None ):
- methods.append( trans.webapp.controllers['admin'].set_quota_default )
+ methods.append( self._set_quota_default )
if payload.get( 'in_users', None ) or payload.get( 'in_groups', None ):
- methods.append( trans.webapp.controllers['admin'].manage_users_and_groups_for_quota )
+ methods.append( self._manage_users_and_groups_for_quota )
messages = []
for method in methods:
- status, result = method( trans, cntrller='api', **payload )
- if status != 200:
- trans.response.status = status
- return str( result )
- messages.append( result )
+ try:
+ message = method( quota, params )
+ except ActionInputError, e:
+ raise HTTPBadRequest( detail=str( e ) )
+ messages.append( message )
return '; '.join( messages )
@web.expose_api
@@ -114,27 +116,20 @@
DELETE /api/quotas/{encoded_quota_id}
Deletes a quota
"""
- try:
- get_quota_for_access( trans, id, deleted=False ) # deleted quotas are not technically members of this collection
- except BadRequestException, e:
- return str( e )
+ quota = self.get_quota( trans, id, deleted=False ) # deleted quotas are not technically members of this collection
+
# a request body is optional here
payload = kwd.get( 'payload', {} )
payload['id'] = id
+ params = self.get_quota_params( payload )
- status, result = trans.webapp.controllers['admin'].mark_quota_deleted( trans, cntrller='api', **payload )
- if status != 200:
- trans.response.status = status
- return str( result )
- rval = result
-
- if util.string_as_bool( payload.get( 'purge', False ) ):
- status, result = trans.webapp.controllers['admin'].purge_quota( trans, cntrller='api', **payload )
- if status != 200:
- trans.response.status = status
- return str( result )
- rval += '; %s' % result
- return rval
+ try:
+ message = self._mark_quota_deleted( quota, params )
+ if util.string_as_bool( payload.get( 'purge', False ) ):
+ message += self._purge_quota( quota, params )
+ except ActionInputError, e:
+ raise HTTPBadRequest( detail=str( e ) )
+ return message
@web.expose_api
@web.require_admin
@@ -143,39 +138,9 @@
POST /api/quotas/deleted/{encoded_quota_id}/undelete
Undeletes a quota
"""
- status, result = trans.webapp.controllers['admin'].undelete_quota( trans, cntrller='api', id=id )
- if status != 200:
- trans.response.status = status
- return str( result )
- return result
-
- def _validate_in_users_and_groups( self, trans, payload ):
- """
- For convenience, in_users and in_groups can be encoded IDs or emails/group names
- """
- def get_id( item, model_class, column ):
- try:
- return trans.security.decode_id( item )
- except:
- pass # maybe an email/group name
- # this will raise if the item is invalid
- return trans.sa_session.query( model_class ).filter( column == item ).first().id
- new_in_users = []
- new_in_groups = []
- invalid = []
- for item in util.listify( payload.get( 'in_users', [] ) ):
- try:
- new_in_users.append( get_id( item, trans.app.model.User, trans.app.model.User.table.c.email ) )
- except:
- invalid.append( item )
- for item in util.listify( payload.get( 'in_groups', [] ) ):
- try:
- new_in_groups.append( get_id( item, trans.app.model.Group, trans.app.model.Group.table.c.name ) )
- except:
- invalid.append( item )
- if invalid:
- msg = "The following value(s) for associated users and/or groups could not be parsed: %s." % ', '.join( invalid )
- msg += " Valid values are email addresses of users, names of groups, or IDs of both."
- raise Exception( msg )
- payload['in_users'] = map( str, new_in_users )
- payload['in_groups'] = map( str, new_in_groups )
+ quota = self.get_quota( trans, id, deleted=True )
+ params = self.get_quota_params( payload )
+ try:
+ return self._undelete_quota( quota, params )
+ except ActionInputError, e:
+ raise HTTPBadRequest( detail=str( e ) )
--- a/lib/galaxy/web/api/request_types.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/api/request_types.py Thu Sep 22 17:13:53 2011 -0400
@@ -2,7 +2,7 @@
API operations on RequestType objects.
"""
import logging
-from galaxy.web.base.controller import BaseController, url_for
+from galaxy.web.base.controller import BaseAPIController, url_for
from galaxy import web
from galaxy.sample_tracking.request_types import request_type_factory
from elementtree.ElementTree import XML
@@ -10,7 +10,7 @@
log = logging.getLogger( __name__ )
-class RequestTypeAPIController( BaseController ):
+class RequestTypeAPIController( BaseAPIController ):
@web.expose_api
def index( self, trans, **kwd ):
"""
--- a/lib/galaxy/web/api/requests.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/api/requests.py Thu Sep 22 17:13:53 2011 -0400
@@ -11,7 +11,7 @@
log = logging.getLogger( __name__ )
-class RequestsAPIController( BaseController ):
+class RequestsAPIController( BaseAPIController ):
update_types = Bunch( REQUEST = 'request_state' )
update_type_values = [v[1] for v in update_types.items()]
@web.expose_api
--- a/lib/galaxy/web/api/roles.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/api/roles.py Thu Sep 22 17:13:53 2011 -0400
@@ -2,13 +2,13 @@
API operations on Role objects.
"""
import logging
-from galaxy.web.base.controller import BaseController, url_for
+from galaxy.web.base.controller import BaseAPIController, url_for
from galaxy import web
from elementtree.ElementTree import XML
log = logging.getLogger( __name__ )
-class RoleAPIController( BaseController ):
+class RoleAPIController( BaseAPIController ):
@web.expose_api
def index( self, trans, **kwd ):
"""
--- a/lib/galaxy/web/api/samples.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/api/samples.py Thu Sep 22 17:13:53 2011 -0400
@@ -9,7 +9,7 @@
log = logging.getLogger( __name__ )
-class SamplesAPIController( BaseController ):
+class SamplesAPIController( BaseAPIController ):
update_types = Bunch( SAMPLE = [ 'sample_state', 'run_details' ],
SAMPLE_DATASET = [ 'sample_dataset_transfer_status' ] )
update_type_values = []
--- a/lib/galaxy/web/api/users.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/api/users.py Thu Sep 22 17:13:53 2011 -0400
@@ -2,59 +2,79 @@
API operations on User objects.
"""
import logging
-from galaxy.web.base.controller import BaseController, url_for
-from galaxy import web
+from galaxy.web.base.controller import BaseAPIController, url_for
+from galaxy import web, util
from elementtree.ElementTree import XML
+from paste.httpexceptions import *
log = logging.getLogger( __name__ )
-class UserAPIController( BaseController ):
+class UserAPIController( BaseAPIController ):
@web.expose_api
- def index( self, trans, **kwd ):
+ def index( self, trans, deleted='False', **kwd ):
"""
GET /api/users
+ GET /api/users/deleted
Displays a collection (list) of users.
"""
- if not trans.user_is_admin():
- trans.response.status = 403
- return "You are not authorized to view the list of users."
rval = []
- for user in trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.deleted == False ):
+ query = trans.sa_session.query( trans.app.model.User )
+ deleted = util.string_as_bool( deleted )
+ if deleted:
+ route = 'deleted_user'
+ query = query.filter( trans.app.model.User.table.c.deleted == True )
+ # only admins can see deleted users
+ if not trans.user_is_admin():
+ return []
+ else:
+ route = 'user'
+ query = query.filter( trans.app.model.User.table.c.deleted == False )
+ # special case: user can see only their own user
+ if not trans.user_is_admin():
+ item = trans.user.get_api_value( value_mapper={ 'id': trans.security.encode_id } )
+ item['url'] = url_for( route, id=encoded_id )
+ return item
+ for user in query:
item = user.get_api_value( value_mapper={ 'id': trans.security.encode_id } )
encoded_id = trans.security.encode_id( user.id )
- item['url'] = url_for( 'user', id=encoded_id )
+ item['url'] = url_for( route, id=encoded_id )
rval.append( item )
return rval
@web.expose_api
- def show( self, trans, id, **kwd ):
+ def show( self, trans, id, deleted='False', **kwd ):
"""
GET /api/users/{encoded_user_id}
+ GET /api/users/deleted/{encoded_user_id}
Displays information about a user.
"""
- if not trans.user_is_admin():
- trans.response.status = 403
- return "You are not authorized to view user info."
- user_id = id
+ deleted = util.string_as_bool( deleted )
try:
- decoded_user_id = trans.security.decode_id( user_id )
- except TypeError:
- trans.response.status = 400
- return "Malformed user id ( %s ) specified, unable to decode." % str( user_id )
- try:
- user = trans.sa_session.query( trans.app.model.User ).get( decoded_user_id )
+ user = self.get_user( trans, id, deleted=deleted )
+ if not trans.user_is_admin():
+ assert trans.user == user
+ assert not user.deleted
except:
- trans.response.status = 400
- return "That user does not exist."
- item = user.get_api_value( view='element', value_mapper={ 'id': trans.security.encode_id } )
- item['url'] = url_for( 'user', id=user_id )
+ if trans.user_is_admin():
+ raise
+ else:
+ raise HTTPBadRequest( detail='Invalid user id ( %s ) specified' % id )
+ item = user.get_api_value( view='element', value_mapper={ 'id': trans.security.encode_id,
+ 'total_disk_usage': float } )
return item
- @web.expose_api
- def create( self, trans, payload, **kwd ):
- """
- POST /api/users
- Creates a new user.
- """
- trans.response.status = 403
- return "Not implemented."
+ @web.expose
+ def create( self, trans, **kwd ):
+ raise HTTPNotImplemented()
+
+ @web.expose
+ def update( self, trans, **kwd ):
+ raise HTTPNotImplemented()
+
+ @web.expose
+ def delete( self, trans, **kwd ):
+ raise HTTPNotImplemented()
+
+ @web.expose
+ def undelete( self, trans, **kwd ):
+ raise HTTPNotImplemented()
--- a/lib/galaxy/web/api/util.py Thu Sep 22 12:18:38 2011 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-"""
-Utility methods for API controllers
-"""
-
-class BadRequestException( Exception ):
- pass
-
-def get_history_for_access( trans, history_id ):
- try:
- decoded_history_id = trans.security.decode_id( history_id )
- except TypeError:
- trans.response.status = 400
- raise BadRequestException( "Malformed history id ( %s ) specified, unable to decode." % str( history_id ) )
- try:
- history = trans.sa_session.query( trans.app.model.History ).get( decoded_history_id )
- assert history
- if history.user != trans.user and not trans.user_is_admin():
- assert trans.sa_session.query( trans.app.model.HistoryUserShareAssociation ).filter_by( user=trans.user, history=history ).count() != 0
- except:
- trans.response.status = 400
- raise BadRequestException( "Invalid history id ( %s ) specified." % str( history_id ) )
- return history
-
-def get_history_for_modification( trans, history_id ):
- history = get_history_for_access( trans, history_id )
- try:
- assert trans.user_is_admin() or history.user == trans.user
- except:
- trans.response.status = 400
- raise BadRequestException( "Invalid history id ( %s ) specified." % str( history_id ) )
- return history
-
-def get_history_content_for_access( trans, content_id ):
- # Note that we could check the history provided in the URL heirarchy here,
- # but it's irrelevant, we care about the history associated with the hda.
- try:
- decoded_content_id = trans.security.decode_id( content_id )
- model_class = trans.app.model.HistoryDatasetAssociation
- except:
- trans.response.status = 400
- raise BadRequestException( "Malformed history content id ( %s ) specified, unable to decode." % str( content_id ) )
- try:
- content = trans.sa_session.query( model_class ).get( decoded_content_id )
- assert content
- if content.history.user != trans.user and not trans.user_is_admin():
- assert trans.sa_session.query(trans.app.model.HistoryUserShareAssociation).filter_by(user=trans.user, history=content.history).count() != 0
- except:
- trans.response.status = 400
- raise BadRequestException( "Invalid history content id ( %s ) specified." % ( str( content_id ) ) )
- return content
-
-def get_library_folder_for_access( trans, library_id, folder_id ):
- """
- When we know we're looking for a folder, take either the 'F' + encoded_id or bare encoded_id.
- """
- if ( len( folder_id ) % 16 == 0 ):
- folder_id = 'F' + folder_id
- return get_library_content_for_access( trans, folder_id )
-
-def get_library_content_for_access( trans, content_id ):
- try:
- if ( len( content_id ) % 16 == 0 ):
- model_class = trans.app.model.LibraryDataset
- decoded_content_id = trans.security.decode_id( content_id )
- elif ( content_id.startswith( 'F' ) ):
- model_class = trans.app.model.LibraryFolder
- decoded_content_id = trans.security.decode_id( content_id[1:] )
- else:
- raise Exception( 'Bad id' )
- except:
- trans.response.status = 400
- raise BadRequestException( "Malformed library content id ( %s ) specified, unable to decode." % str( content_id ) )
- try:
- content = trans.sa_session.query( model_class ).get( decoded_content_id )
- assert content
- assert trans.user_is_admin() or trans.app.security_agent.can_access_library_item( trans.get_current_user_roles(), content, trans.user )
- except:
- trans.response.status = 400
- raise BadRequestException( "Invalid library content id ( %s ) specified." % str( content_id ) )
- return content
-
-def get_quota_for_access( trans, quota_id, deleted=False ):
- """
- No security - the only methods that use this do so with admin users. If
- quota modification becomes a role, this will need to be updated.
- """
- try:
- decoded_quota_id = trans.security.decode_id( quota_id )
- except TypeError:
- trans.response.status = 400
- raise BadRequestException( "Malformed quota id ( %s ) specified, unable to decode." % str( quota_id ) )
- try:
- quota = trans.sa_session.query( trans.app.model.Quota ).get( decoded_quota_id )
- assert quota is not None
- if deleted:
- assert quota.deleted
- else:
- assert not quota.deleted
- except:
- trans.response.status = 400
- raise BadRequestException( "Invalid quota id ( %s ) specified." % str( quota_id ) )
- return quota
-
-def encode_all_ids( trans, rval ):
- """
- encodes all integer values in the dict rval whose keys are 'id' or end with '_id'
- """
- if type( rval ) != dict:
- return rval
- for k, v in rval.items():
- if k == 'id' or k.endswith( '_id' ):
- try:
- rval[k] = trans.security.encode_id( v )
- except:
- pass # probably already encoded
- return rval
--- a/lib/galaxy/web/api/workflows.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/api/workflows.py Thu Sep 22 17:13:53 2011 -0400
@@ -7,13 +7,13 @@
from galaxy import util
from galaxy import web
from galaxy.tools.parameters import visit_input_values, DataToolParameter
-from galaxy.web.base.controller import BaseController, url_for
+from galaxy.web.base.controller import BaseAPIController, url_for
from galaxy.workflow.modules import module_factory
from galaxy.jobs.actions.post import ActionBox
log = logging.getLogger(__name__)
-class WorkflowsAPIController(BaseController):
+class WorkflowsAPIController(BaseAPIController):
@web.expose_api
def index(self, trans, **kwd):
"""
--- a/lib/galaxy/web/base/controller.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/base/controller.py Thu Sep 22 17:13:53 2011 -0400
@@ -13,6 +13,8 @@
from galaxy.visualization.tracks.data_providers import get_data_provider
from galaxy.visualization.tracks.visual_analytics import get_tool_def
from galaxy.security.validate_user_input import validate_username
+from paste.httpexceptions import *
+from galaxy.exceptions import *
from Cheetah.Template import Template
@@ -35,10 +37,11 @@
def __init__( self, app ):
"""Initialize an interface for application 'app'"""
self.app = app
+ self.sa_session = app.model.context
def get_toolbox(self):
"""Returns the application toolbox"""
return self.app.toolbox
- def get_class( self, trans, class_name ):
+ def get_class( self, class_name ):
""" Returns the class object that a string denotes. Without this method, we'd have to do eval(<class_name>). """
if class_name == 'History':
item_class = trans.model.History
@@ -53,27 +56,144 @@
elif class_name == 'Tool':
item_class = trans.model.Tool
elif class_name == 'Job':
- item_class == trans.model.Job
+ item_class = trans.model.Job
+ elif class_name == 'User':
+ item_class = trans.model.User
+ elif class_name == 'Group':
+ item_class = trans.model.Group
+ elif class_name == 'Role':
+ item_class = trans.model.Role
+ elif class_name == 'Quota':
+ item_class = trans.model.Quota
+ elif class_name == 'Library':
+ item_class = trans.model.Library
+ elif class_name == 'LibraryFolder':
+ item_class = trans.model.LibraryFolder
+ elif class_name == 'LibraryDatasetDatasetAssociation':
+ item_class = trans.model.LibraryDatasetDatasetAssociation
+ elif class_name == 'LibraryDataset':
+ item_class = trans.model.LibraryDataset
else:
item_class = None
return item_class
+ def get_object( self, trans, id, class_name, check_ownership=False, check_accessible=False, deleted=None ):
+ """
+ Convenience method to get a model object with the specified checks.
+ """
+ try:
+ decoded_id = trans.security.decode_id( id )
+ except:
+ raise MessageException( "Malformed %s id ( %s ) specified, unable to decode" % ( class_name, str( id ) ), type='error' )
+ try:
+ item_class = self.get_class( class_name )
+ assert item_class is not None
+ item = trans.sa_session.query( item_class ).get( decoded_id )
+ assert item is not None
+ except:
+ raise MessageException( "Invalid %s id ( %s ) specified" % ( class_name, display_id ), type="error" )
+ if check_ownership or check_accessible:
+ self.security_check( trans, item, check_ownership, check_accessible, encoded_id )
+ if deleted == True and not item.deleted:
+ raise ItemDeletionException( '%s "%s" is not deleted' % ( class_name, getattr( item, 'name', id ) ), type="warning" )
+ elif deleted == False and item.deleted:
+ raise ItemDeletionException( '%s "%s" is deleted' % ( class_name, getattr( item, 'name', id ) ), type="warning" )
+ return item
+ def get_user( self, trans, id, check_ownership=False, check_accessible=False, deleted=None ):
+ return self.get_object( trans, id, 'User', check_ownership=False, check_accessible=False, deleted=deleted )
+ def get_group( self, trans, id, check_ownership=False, check_accessible=False, deleted=None ):
+ return self.get_object( trans, id, 'Group', check_ownership=False, check_accessible=False, deleted=deleted )
+ def get_role( self, trans, id, check_ownership=False, check_accessible=False, deleted=None ):
+ return self.get_object( trans, id, 'Role', check_ownership=False, check_accessible=False, deleted=deleted )
+ def encode_all_ids( self, trans, rval ):
+ """
+ Encodes all integer values in the dict rval whose keys are 'id' or end with '_id'
+
+ It might be useful to turn this in to a decorator
+ """
+ if type( rval ) != dict:
+ return rval
+ for k, v in rval.items():
+ if k == 'id' or k.endswith( '_id' ):
+ try:
+ rval[k] = trans.security.encode_id( v )
+ except:
+ pass # probably already encoded
+ return rval
Root = BaseController
+class BaseUIController( BaseController ):
+ def get_object( self, trans, id, class_name, check_ownership=False, check_accessible=False, deleted=None ):
+ try:
+ return BaseController.get_object( self, trans, id, class_name, check_ownership=False, check_accessible=False, deleted=None )
+ except MessageException, e:
+ raise # handled in the caller
+ except:
+ log.exception( "Execption in get_object check for %s %s:" % ( class_name, str( id ) ) )
+ raise Exception( 'Server error retrieving %s id ( %s ).' % ( class_name, str( id ) ) )
+
+class BaseAPIController( BaseController ):
+ def get_object( self, trans, id, class_name, check_ownership=False, check_accessible=False, deleted=None ):
+ try:
+ return BaseController.get_object( self, trans, id, class_name, check_ownership=False, check_accessible=False, deleted=None )
+ except ItemDeletionException, e:
+ raise HTTPBadRequest( detail="Invalid %s id ( %s ) specified" % ( class_name, str( id ) ) )
+ except MessageException, e:
+ raise HTTPBadRequest( detail=e.err_msg )
+ except Exception, e:
+ log.exception( "Execption in get_object check for %s %s:" % ( class_name, str( id ) ) )
+ raise HTTPInternalServerError( comment=str( e ) )
+ def validate_in_users_and_groups( self, trans, payload ):
+ """
+ For convenience, in_users and in_groups can be encoded IDs or emails/group names in the API.
+ """
+ def get_id( item, model_class, column ):
+ try:
+ return trans.security.decode_id( item )
+ except:
+ pass # maybe an email/group name
+ # this will raise if the item is invalid
+ return trans.sa_session.query( model_class ).filter( column == item ).first().id
+ new_in_users = []
+ new_in_groups = []
+ invalid = []
+ for item in util.listify( payload.get( 'in_users', [] ) ):
+ try:
+ new_in_users.append( get_id( item, trans.app.model.User, trans.app.model.User.table.c.email ) )
+ except:
+ invalid.append( item )
+ for item in util.listify( payload.get( 'in_groups', [] ) ):
+ try:
+ new_in_groups.append( get_id( item, trans.app.model.Group, trans.app.model.Group.table.c.name ) )
+ except:
+ invalid.append( item )
+ if invalid:
+ msg = "The following value(s) for associated users and/or groups could not be parsed: %s." % ', '.join( invalid )
+ msg += " Valid values are email addresses of users, names of groups, or IDs of both."
+ raise Exception( msg )
+ payload['in_users'] = map( str, new_in_users )
+ payload['in_groups'] = map( str, new_in_groups )
+ def not_implemented( self, trans, **kwd ):
+ raise HTTPNotImplemented()
+
class SharableItemSecurity:
""" Mixin for handling security for sharable items. """
- def security_check( self, user, item, check_ownership=False, check_accessible=False ):
+ def security_check( self, trans, item, check_ownership=False, check_accessible=False ):
""" Security checks for an item: checks if (a) user owns item or (b) item is accessible to user. """
if check_ownership:
# Verify ownership.
- if not user:
- error( "Must be logged in to manage Galaxy items" )
- if item.user != user:
- error( "%s is not owned by current user" % item.__class__.__name__ )
+ if not trans.user:
+ raise ItemOwnershipException( "Must be logged in to manage Galaxy items", type='error' )
+ if item.user != trans.user:
+ raise ItemOwnershipException( "%s is not owned by the current user" % item.__class__.__name__, type='error' )
if check_accessible:
- # Verify accessible.
- if ( item.user != user ) and ( not item.importable ) and ( user not in item.users_shared_with_dot_users ):
- error( "%s is not accessible to current user" % item.__class__.__name__ )
+ if type( item ) in ( trans.app.model.LibraryFolder, trans.app.model.LibraryDatasetDatasetAssociation, trans.app.model.LibraryDataset ):
+ if not ( trans.user_is_admin() or trans.app.security_agent.can_access_library_i9tem( trans.get_current_user_roles(), item, trans.user ) ):
+ raise ItemAccessibilityException( "%s is not accessible to the current user" % item.__class__.__name__, type='error' )
+ else:
+ # Verify accessible.
+ if ( item.user != trans.user ) and ( not item.importable ) and ( trans.user not in item.users_shared_with_dot_users ):
+ raise ItemAccessibilityException( "%s is not accessible to the current user" % item.__class__.__name__, type='error' )
return item
#
@@ -95,7 +215,7 @@
except:
data = None
if not data:
- raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid dataset id: %s." % str( dataset_id ) )
+ raise HTTPRequestRangeNotSatisfiable( "Invalid dataset id: %s." % str( dataset_id ) )
if check_ownership:
# Verify ownership.
user = trans.get_user()
@@ -111,6 +231,16 @@
else:
error( "You are not allowed to access this dataset" )
return data
+ def get_history_dataset_association( self, trans, dataset_id, check_ownership=True, check_accessible=False ):
+ """Get a HistoryDatasetAssociation from the database by id, verifying ownership."""
+ hda = self.get_object( trans, id, 'HistoryDatasetAssociation', check_ownership=check_ownership, check_accessible=check_accessible, deleted=deleted )
+ self.security_check( trans, history, check_ownership=check_ownership, check_accessible=False ) # check accessibility here
+ if check_accessible:
+ if trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), hda.dataset ):
+ if hda.state == trans.model.Dataset.states.UPLOAD:
+ error( "Please wait until this dataset finishes uploading before attempting to view it." )
+ else:
+ error( "You are not allowed to access this dataset" )
def get_data( self, dataset, preview=True ):
""" Gets a dataset's data. """
# Get data from file, truncating if necessary.
@@ -126,6 +256,21 @@
truncated = False
return truncated, dataset_data
+class UsesLibrary:
+ def get_library( self, trans, id, check_ownership=False, check_accessible=True ):
+ l = self.get_object( trans, id, 'Library' )
+ if check_accessible and not ( trans.user_is_admin() or trans.app.security_agent.can_access_library( trans.get_current_user_roles(), l ) ):
+ error( "LibraryFolder is not accessible to the current user" )
+ return l
+
+class UsesLibraryItems( SharableItemSecurity ):
+ def get_library_folder( self, trans, id, check_ownership=False, check_accessible=True ):
+ return self.get_object( trans, id, 'LibraryFolder', check_ownership=False, check_accessible=check_accessible )
+ def get_library_dataset_dataset_association( self, trans, id, check_ownership=False, check_accessible=True ):
+ return self.get_object( trans, id, 'LibraryDatasetDatasetAssociation', check_ownership=False, check_accessible=check_accessible )
+ def get_library_dataset( self, trans, id, check_ownership=False, check_accessible=True ):
+ return self.get_object( trans, id, 'LibraryDataset', check_ownership=False, check_accessible=check_accessible )
+
class UsesVisualization( SharableItemSecurity ):
""" Mixin for controllers that use Visualization objects. """
@@ -157,7 +302,7 @@
if not visualization:
error( "Visualization not found" )
else:
- return self.security_check( trans.get_user(), visualization, check_ownership, check_accessible )
+ return self.security_check( trans, visualization, check_ownership, check_accessible )
def get_visualization_config( self, trans, visualization ):
""" Returns a visualization's configuration. Only works for trackster visualizations right now. """
@@ -218,7 +363,7 @@
if not workflow:
error( "Workflow not found" )
else:
- return self.security_check( trans.get_user(), workflow, check_ownership, check_accessible )
+ return self.security_check( trans, workflow, check_ownership, check_accessible )
def get_stored_workflow_steps( self, trans, stored_workflow ):
""" Restores states for a stored workflow's steps. """
for step in stored_workflow.latest_workflow.steps:
@@ -246,17 +391,10 @@
class UsesHistory( SharableItemSecurity ):
""" Mixin for controllers that use History objects. """
- def get_history( self, trans, id, check_ownership=True, check_accessible=False ):
+ def get_history( self, trans, id, check_ownership=True, check_accessible=False, deleted=None ):
"""Get a History from the database by id, verifying ownership."""
- # Load history from database
- try:
- history = trans.sa_session.query( trans.model.History ).get( trans.security.decode_id( id ) )
- except TypeError:
- history = None
- if not history:
- error( "History not found" )
- else:
- return self.security_check( trans.get_user(), history, check_ownership, check_accessible )
+ history = self.get_object( trans, id, 'History', check_ownership=check_ownership, check_accessible=check_accessible, deleted=deleted )
+ return self.security_check( trans, history, check_ownership, check_accessible )
def get_history_datasets( self, trans, history, show_deleted=False, show_hidden=False, show_purged=False ):
""" Returns history's datasets. """
query = trans.sa_session.query( trans.model.HistoryDatasetAssociation ) \
@@ -1113,6 +1251,10 @@
""" Return item based on id. """
raise "Unimplemented Method"
+class UsesQuota( object ):
+ def get_quota( self, trans, id, check_ownership=False, check_accessible=False, deleted=None ):
+ return self.get_object( trans, id, 'Quota', check_ownership=False, check_accessible=False, deleted=deleted )
+
"""
Deprecated: `BaseController` used to be available under the name `Root`
"""
@@ -1524,538 +1666,6 @@
message=util.sanitize_text( message ),
status='done' ) )
- # Galaxy Quota Stuff
- @web.expose
- @web.require_admin
- def quotas( self, trans, **kwargs ):
- if 'operation' in kwargs:
- operation = kwargs['operation'].lower()
- if operation == "quotas":
- return self.quota( trans, **kwargs )
- if operation == "create":
- return self.create_quota( trans, **kwargs )
- if operation == "delete":
- return self.mark_quota_deleted( trans, **kwargs )
- if operation == "undelete":
- return self.undelete_quota( trans, **kwargs )
- if operation == "purge":
- return self.purge_quota( trans, **kwargs )
- if operation == "change amount":
- return self.edit_quota( trans, **kwargs )
- if operation == "manage users and groups":
- return self.manage_users_and_groups_for_quota( trans, **kwargs )
- if operation == "rename":
- return self.rename_quota( trans, **kwargs )
- if operation == "edit":
- return self.edit_quota( trans, **kwargs )
- # Render the list view
- return self.quota_list_grid( trans, **kwargs )
-
- @web.expose
- @web.require_admin
- def create_quota( self, trans, cntrller='admin', **kwd ):
- params = util.Params( kwd )
- webapp = params.get( 'webapp', 'galaxy' )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- name = util.restore_text( params.get( 'name', '' ) )
- description = util.restore_text( params.get( 'description', '' ) )
- amount = util.restore_text( params.get( 'amount', '' ).strip() )
- if amount.lower() in ( 'unlimited', 'none', 'no limit' ):
- create_amount = None
- else:
- try:
- create_amount = util.size_to_bytes( amount )
- except AssertionError:
- create_amount = False
- operation = params.get( 'operation', '' )
- default = params.get( 'default', 'no' )
- in_users = util.listify( params.get( 'in_users', [] ) )
- out_users = util.listify( params.get( 'out_users', [] ) )
- in_groups = util.listify( params.get( 'in_groups', [] ) )
- out_groups = util.listify( params.get( 'out_groups', [] ) )
- if params.get( 'create_quota_button', False ) or cntrller == 'api':
- if not name or not description:
- message = "Enter a valid name and a description."
- status = 'error'
- elif trans.sa_session.query( trans.app.model.Quota ).filter( trans.app.model.Quota.table.c.name==name ).first():
- message = "Quota names must be unique and a quota with that name already exists, so choose another name."
- status = 'error'
- elif not params.get( 'amount', None ):
- message = "Enter a valid quota amount."
- status = 'error'
- elif create_amount is False:
- message = "Unable to parse the provided amount."
- status = 'error'
- elif operation not in trans.app.model.Quota.valid_operations:
- message = "Enter a valid operation."
- status = 'error'
- elif default != 'no' and default not in trans.app.model.DefaultQuotaAssociation.types.__dict__.values():
- message = "Enter a valid default type."
- status = 'error'
- elif default != 'no' and operation != '=':
- message = "Operation for a default quota must be '='."
- status = 'error'
- operation = '='
- else:
- # Create the quota
- quota = trans.app.model.Quota( name=name, description=description, amount=create_amount, operation=operation )
- trans.sa_session.add( quota )
- # If this is a default quota, create the DefaultQuotaAssociation
- if default != 'no':
- trans.app.quota_agent.set_default_quota( default, quota )
- else:
- # Create the UserQuotaAssociations
- for user in [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in in_users ]:
- uqa = trans.app.model.UserQuotaAssociation( user, quota )
- trans.sa_session.add( uqa )
- # Create the GroupQuotaAssociations
- for group in [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in in_groups ]:
- gqa = trans.app.model.GroupQuotaAssociation( group, quota )
- trans.sa_session.add( gqa )
- trans.sa_session.flush()
- message = "Quota '%s' has been created with %d associated users and %d associated groups." % ( quota.name, len( in_users ), len( in_groups ) )
- if cntrller == 'api':
- return 200, quota
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=util.sanitize_text( message ),
- status='done' ) )
- in_users = map( int, in_users )
- in_groups = map( int, in_groups )
- new_in_users = []
- new_in_groups = []
- for user in trans.sa_session.query( trans.app.model.User ) \
- .filter( trans.app.model.User.table.c.deleted==False ) \
- .order_by( trans.app.model.User.table.c.email ):
- if user.id in in_users:
- new_in_users.append( ( user.id, user.email ) )
- else:
- out_users.append( ( user.id, user.email ) )
- for group in trans.sa_session.query( trans.app.model.Group ) \
- .filter( trans.app.model.Group.table.c.deleted==False ) \
- .order_by( trans.app.model.Group.table.c.name ):
- if group.id in in_groups:
- new_in_groups.append( ( group.id, group.name ) )
- else:
- out_groups.append( ( group.id, group.name ) )
- if cntrller == 'api':
- if status == 'error':
- return 400, message
- return 500, message # should never get here...
- return trans.fill_template( '/admin/quota/quota_create.mako',
- webapp=webapp,
- name=name,
- description=description,
- amount=amount,
- operation=operation,
- default=default,
- in_users=new_in_users,
- out_users=out_users,
- in_groups=new_in_groups,
- out_groups=out_groups,
- message=message,
- status=status )
-
- @web.expose
- @web.require_admin
- def rename_quota( self, trans, cntrller='admin', **kwd ):
- params = util.Params( kwd )
- webapp = params.get( 'webapp', 'galaxy' )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- id = params.get( 'id', None )
- error = True
- try:
- assert id, 'No quota ids received for renaming'
- quota = get_quota( trans, id )
- assert quota, 'Quota id (%s) is invalid' % id
- error = False
- except AssertionError, e:
- message = str( e )
- if error:
- if cntrller == 'api':
- return 400, message
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=message,
- status='error' ) )
- if params.get( 'rename_quota_button', False ) or cntrller == 'api':
- new_name = util.restore_text( params.get( 'name', quota.name ) )
- new_description = util.restore_text( params.get( 'description', quota.description ) )
- if not new_name:
- message = 'Enter a valid name'
- status='error'
- elif new_name != quota.name and trans.sa_session.query( trans.app.model.Quota ).filter( trans.app.model.Quota.table.c.name==new_name ).first():
- message = 'A quota with that name already exists'
- status = 'error'
- else:
- old_name = quota.name
- quota.name = new_name
- quota.description = new_description
- trans.sa_session.add( quota )
- trans.sa_session.flush()
- message = "Quota '%s' has been renamed to '%s'" % ( old_name, new_name )
- if cntrller == 'api':
- return 200, message
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=util.sanitize_text( message ),
- status='done' ) )
- if cntrller == 'api':
- if status == 'error':
- return 400, message
- return 500, message # should never get here...
- return trans.fill_template( '/admin/quota/quota_rename.mako',
- quota=quota,
- webapp=webapp,
- message=message,
- status=status )
-
- @web.expose
- @web.require_admin
- def manage_users_and_groups_for_quota( self, trans, cntrller='admin', **kwd ):
- params = util.Params( kwd )
- webapp = params.get( 'webapp', 'galaxy' )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- id = params.get( 'id', None )
- error = True
- try:
- assert id, 'No quota ids received for managing users and groups'
- quota = get_quota( trans, id )
- assert quota, 'Quota id (%s) is invalid' % id
- assert not quota.default, 'Default quotas cannot be associated with specific users and groups'
- error = False
- except AssertionError, e:
- message = str( e )
- if error:
- if cntrller == 'api':
- return 400, message
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=message,
- status='error' ) )
- if params.get( 'quota_members_edit_button', False ) or cntrller == 'api':
- in_users = [ trans.sa_session.query( trans.app.model.User ).get( x ) for x in util.listify( params.in_users ) ]
- in_groups = [ trans.sa_session.query( trans.app.model.Group ).get( x ) for x in util.listify( params.in_groups ) ]
- trans.app.quota_agent.set_entity_quota_associations( quotas=[ quota ], users=in_users, groups=in_groups )
- trans.sa_session.refresh( quota )
- message = "Quota '%s' has been updated with %d associated users and %d associated groups" % ( quota.name, len( in_users ), len( in_groups ) )
- if cntrller == 'api':
- return 200, message
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=util.sanitize_text( message ),
- status=status ) )
- # api cannot get to here
- in_users = []
- out_users = []
- in_groups = []
- out_groups = []
- for user in trans.sa_session.query( trans.app.model.User ) \
- .filter( trans.app.model.User.table.c.deleted==False ) \
- .order_by( trans.app.model.User.table.c.email ):
- if user in [ x.user for x in quota.users ]:
- in_users.append( ( user.id, user.email ) )
- else:
- out_users.append( ( user.id, user.email ) )
- for group in trans.sa_session.query( trans.app.model.Group ) \
- .filter( trans.app.model.Group.table.c.deleted==False ) \
- .order_by( trans.app.model.Group.table.c.name ):
- if group in [ x.group for x in quota.groups ]:
- in_groups.append( ( group.id, group.name ) )
- else:
- out_groups.append( ( group.id, group.name ) )
- return trans.fill_template( '/admin/quota/quota.mako',
- quota=quota,
- in_users=in_users,
- out_users=out_users,
- in_groups=in_groups,
- out_groups=out_groups,
- webapp=webapp,
- message=message,
- status=status )
-
- @web.expose
- @web.require_admin
- def edit_quota( self, trans, cntrller='admin', **kwd ):
- params = util.Params( kwd )
- webapp = params.get( 'webapp', 'galaxy' )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- id = params.get( 'id', None )
- if not id:
- message = "No quota ids received for editing"
- if cntrller == 'api':
- return 400, message
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=message,
- status='error' ) )
- quota = get_quota( trans, id )
- if params.get( 'edit_quota_button', False ) or cntrller == 'api':
- amount = util.restore_text( params.get( 'amount', '' ).strip() )
- if amount.lower() in ( 'unlimited', 'none', 'no limit' ):
- new_amount = None
- else:
- try:
- new_amount = util.size_to_bytes( amount )
- except AssertionError:
- new_amount = False
- operation = params.get( 'operation', None )
- if not params.get( 'amount', None ):
- message = 'Enter a valid amount'
- status='error'
- elif new_amount is False:
- message = 'Unable to parse the provided amount'
- status = 'error'
- elif operation not in trans.app.model.Quota.valid_operations:
- message = 'Enter a valid operation'
- status = 'error'
- else:
- quota.amount = new_amount
- quota.operation = operation
- trans.sa_session.add( quota )
- trans.sa_session.flush()
- message = "Quota '%s' is now '%s'" % ( quota.name, quota.operation + quota.display_amount )
- if cntrller == 'api':
- return 200, message
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=util.sanitize_text( message ),
- status='done' ) )
- if cntrller == 'api':
- if status == 'error':
- return 400, message
- return 500, message # should never get here...
- return trans.fill_template( '/admin/quota/quota_edit.mako',
- quota=quota,
- webapp=webapp,
- message=message,
- status=status )
-
- @web.expose
- @web.require_admin
- def set_quota_default( self, trans, cntrller='admin', **kwd ):
- params = util.Params( kwd )
- webapp = params.get( 'webapp', 'galaxy' )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- default = params.get( 'default', '' )
- id = params.get( 'id', None )
- if not id:
- message = "No quota ids received for managing defaults"
- if cntrller == 'api':
- return 400, message
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=message,
- status='error' ) )
- quota = get_quota( trans, id )
- if params.get( 'set_default_quota_button', False ) or cntrller == 'api':
- if default != 'no' and default not in trans.app.model.DefaultQuotaAssociation.types.__dict__.values():
- message = "Enter a valid default type."
- status = 'error'
- else:
- if default != 'no':
- trans.app.quota_agent.set_default_quota( default, quota )
- message = "Quota '%s' is now the default for %s users" % ( quota.name, default )
- if cntrller == 'api':
- return 200, message
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=util.sanitize_text( message ),
- status='done' ) )
- if not default:
- default = 'no'
- if cntrller == 'api':
- if status == 'error':
- return 400, message
- return 500, message # should never get here...
- return trans.fill_template( '/admin/quota/quota_set_default.mako',
- quota=quota,
- webapp=webapp,
- default=default,
- message=message,
- status=status )
- @web.expose
- @web.require_admin
- def unset_quota_default( self, trans, cntrller='admin', **kwd ):
- params = util.Params( kwd )
- webapp = params.get( 'webapp', 'galaxy' )
- message = util.restore_text( params.get( 'message', '' ) )
- status = params.get( 'status', 'done' )
- default = params.get( 'default', '' )
- id = params.get( 'id', None )
- if not id:
- message = "No quota ids received for managing defaults"
- if cntrller == 'api':
- return 400, message
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=message,
- status='error' ) )
- quota = get_quota( trans, id )
- if not quota.default:
- message = "Quota '%s' is not a default." % quota.name
- status = 'error'
- else:
- message = "Quota '%s' is no longer the default for %s users." % ( quota.name, quota.default[0].type )
- status = 'done'
- for dqa in quota.default:
- trans.sa_session.delete( dqa )
- trans.sa_session.flush()
- if cntrller == 'api':
- if status == 'done':
- return 200, message
- elif status == 'error':
- return 400, message
- return 500, message # should never get here...
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=message,
- status=status ) )
-
- @web.expose
- @web.require_admin
- def mark_quota_deleted( self, trans, cntrller='admin', **kwd ):
- params = util.Params( kwd )
- webapp = params.get( 'webapp', 'galaxy' )
- id = kwd.get( 'id', None )
- ids = util.listify( id )
- error = True
- quotas = []
- try:
- assert id, 'No quota ids received for deleting'
- for quota_id in ids:
- quota = get_quota( trans, quota_id )
- assert quota, 'Quota id (%s) is invalid' % id
- assert not quota.default, "Quota '%s' is a default, please unset it as a default before deleting it" % ( quota.name )
- quotas.append( quota )
- error = False
- except AssertionError, e:
- message = str( e )
- if error:
- if cntrller == 'api':
- return 400, message
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=message,
- status='error' ) )
- message = "Deleted %d quotas: " % len( ids )
- for quota in quotas:
- quota.deleted = True
- trans.sa_session.add( quota )
- message += " %s " % quota.name
- trans.sa_session.flush()
- if cntrller == 'api':
- return 200, message
- trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=util.sanitize_text( message ),
- status='done' ) )
- @web.expose
- @web.require_admin
- def undelete_quota( self, trans, cntrller='admin', **kwd ):
- params = util.Params( kwd )
- webapp = params.get( 'webapp', 'galaxy' )
- id = kwd.get( 'id', None )
- ids = util.listify( id )
- error = True
- quotas = []
- try:
- assert id, 'No quota ids received for undeleting'
- for quota_id in ids:
- quota = get_quota( trans, quota_id )
- assert quota, 'Quota id (%s) is invalid' % id
- assert quota.deleted, "Quota '%s' has not been deleted, so it cannot be undeleted." % quota.name
- quotas.append( quota )
- error = False
- except AssertionError, e:
- message = str( e )
- if error:
- if cntrller == 'api':
- return 400, message
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=message,
- status='error' ) )
- message = "Undeleted %d quotas: " % len( ids )
- for quota in quotas:
- quota.deleted = False
- trans.sa_session.add( quota )
- trans.sa_session.flush()
- message += " %s " % quota.name
- if cntrller == 'api':
- return 200, message
- trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=util.sanitize_text( message ),
- status='done' ) )
- @web.expose
- @web.require_admin
- def purge_quota( self, trans, cntrller='admin', **kwd ):
- # This method should only be called for a Quota that has previously been deleted.
- # Purging a deleted Quota deletes all of the following from the database:
- # - UserQuotaAssociations where quota_id == Quota.id
- # - GroupQuotaAssociations where quota_id == Quota.id
- params = util.Params( kwd )
- webapp = params.get( 'webapp', 'galaxy' )
- id = kwd.get( 'id', None )
- ids = util.listify( id )
- error = True
- quotas = []
- try:
- assert id, 'No quota ids received for undeleting'
- for quota_id in ids:
- quota = get_quota( trans, quota_id )
- assert quota, 'Quota id (%s) is invalid' % id
- assert quota.deleted, "Quota '%s' has not been deleted, so it cannot be purged." % quota.name
- quotas.append( quota )
- error = False
- except AssertionError, e:
- message = str( e )
- if error:
- if cntrller == 'api':
- return 400, message
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=message,
- status='error' ) )
- message = "Purged %d quotas: " % len( ids )
- for quota in quotas:
- # Delete UserQuotaAssociations
- for uqa in quota.users:
- trans.sa_session.delete( uqa )
- # Delete GroupQuotaAssociations
- for gqa in quota.groups:
- trans.sa_session.delete( gqa )
- trans.sa_session.flush()
- message += " %s " % quota.name
- if cntrller == 'api':
- return 200, message
- trans.response.send_redirect( web.url_for( controller='admin',
- action='quotas',
- webapp=webapp,
- message=util.sanitize_text( message ),
- status='done' ) )
# Galaxy Group Stuff
@web.expose
@web.require_admin
--- a/lib/galaxy/web/buildapp.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/buildapp.py Thu Sep 22 17:13:53 2011 -0400
@@ -22,12 +22,12 @@
import galaxy.datatypes.registry
import galaxy.web.framework
-def add_controllers( webapp, app ):
+def add_ui_controllers( webapp, app ):
"""
Search for controllers in the 'galaxy.web.controllers' module and add
them to the webapp.
"""
- from galaxy.web.base.controller import BaseController
+ from galaxy.web.base.controller import BaseUIController
from galaxy.web.base.controller import ControllerUnavailable
import galaxy.web.controllers
controller_dir = galaxy.web.controllers.__path__[0]
@@ -45,11 +45,11 @@
# Look for a controller inside the modules
for key in dir( module ):
T = getattr( module, key )
- if isclass( T ) and T is not BaseController and issubclass( T, BaseController ):
- webapp.add_controller( name, T( app ) )
+ if isclass( T ) and T is not BaseUIController and issubclass( T, BaseUIController ):
+ webapp.add_ui_controller( name, T( app ) )
def add_api_controllers( webapp, app ):
- from galaxy.web.base.controller import BaseController
+ from galaxy.web.base.controller import BaseAPIController
from galaxy.web.base.controller import ControllerUnavailable
import galaxy.web.api
controller_dir = galaxy.web.api.__path__[0]
@@ -66,7 +66,7 @@
module = getattr( module, comp )
for key in dir( module ):
T = getattr( module, key )
- if isclass( T ) and T is not BaseController and issubclass( T, BaseController ):
+ if isclass( T ) and T is not BaseAPIController and issubclass( T, BaseAPIController ):
webapp.add_api_controller( name, T( app ) )
def app_factory( global_conf, **kwargs ):
@@ -87,7 +87,7 @@
atexit.register( app.shutdown )
# Create the universe WSGI application
webapp = galaxy.web.framework.WebApplication( app, session_cookie='galaxysession' )
- add_controllers( webapp, app )
+ add_ui_controllers( webapp, app )
# Force /history to go to /root/history -- needed since the tests assume this
webapp.add_route( '/history', controller='root', action='history' )
# These two routes handle our simple needs at the moment
@@ -129,9 +129,9 @@
webapp.api_mapper.resource( 'request_type', 'request_types', path_prefix='/api' )
webapp.api_mapper.resource( 'role', 'roles', path_prefix='/api' )
webapp.api_mapper.resource_with_deleted( 'quota', 'quotas', path_prefix='/api' )
- webapp.api_mapper.resource( 'user', 'users', path_prefix='/api' )
+ webapp.api_mapper.resource_with_deleted( 'user', 'users', path_prefix='/api' )
webapp.api_mapper.resource( 'workflow', 'workflows', path_prefix='/api' )
- webapp.api_mapper.resource( 'history', 'histories', path_prefix='/api' )
+ webapp.api_mapper.resource_with_deleted( 'history', 'histories', path_prefix='/api' )
#webapp.api_mapper.connect( 'run_workflow', '/api/workflow/{workflow_id}/library/{library_id}', controller='workflows', action='run', workflow_id=None, library_id=None, conditions=dict(method=["GET"]) )
webapp.finalize_config()
--- a/lib/galaxy/web/controllers/admin.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/admin.py Thu Sep 22 17:13:53 2011 -0400
@@ -5,6 +5,10 @@
import logging
log = logging.getLogger( __name__ )
+from galaxy.actions.admin import AdminActions
+from galaxy.web.params import QuotaParamParser
+from galaxy.exceptions import *
+
class UserListGrid( grids.Grid ):
class EmailColumn( grids.TextColumn ):
def get_value( self, trans, grid, user ):
@@ -344,7 +348,7 @@
allow_multiple=False,
url_args=dict( webapp="galaxy", action="edit_quota" ) ),
grids.GridOperation( "Manage users and groups",
- condition=( lambda item: not item.default ),
+ condition=( lambda item: not item.default and not item.deleted ),
allow_multiple=False,
url_args=dict( webapp="galaxy", action="manage_users_and_groups_for_quota" ) ),
grids.GridOperation( "Set as different type of default",
@@ -352,11 +356,11 @@
allow_multiple=False,
url_args=dict( webapp="galaxy", action="set_quota_default" ) ),
grids.GridOperation( "Set as default",
- condition=( lambda item: not item.default ),
+ condition=( lambda item: not item.default and not item.deleted ),
allow_multiple=False,
url_args=dict( webapp="galaxy", action="set_quota_default" ) ),
grids.GridOperation( "Unset as default",
- condition=( lambda item: item.default ),
+ condition=( lambda item: item.default and not item.deleted ),
allow_multiple=False,
url_args=dict( webapp="galaxy", action="unset_quota_default" ) ),
grids.GridOperation( "Delete",
@@ -380,9 +384,252 @@
preserve_state = False
use_paging = True
-class AdminGalaxy( BaseController, Admin ):
+class AdminGalaxy( BaseUIController, Admin, AdminActions, QuotaParamParser ):
user_list_grid = UserListGrid()
role_list_grid = RoleListGrid()
group_list_grid = GroupListGrid()
quota_list_grid = QuotaListGrid()
+
+ # Galaxy Quota Stuff
+ @web.expose
+ @web.require_admin
+ def quotas( self, trans, **kwargs ):
+ if 'operation' in kwargs:
+ operation = kwargs.pop('operation').lower()
+ if operation == "quotas":
+ return self.quota( trans, **kwargs )
+ if operation == "create":
+ return self.create_quota( trans, **kwargs )
+ if operation == "delete":
+ return self.mark_quota_deleted( trans, **kwargs )
+ if operation == "undelete":
+ return self.undelete_quota( trans, **kwargs )
+ if operation == "purge":
+ return self.purge_quota( trans, **kwargs )
+ if operation == "change amount":
+ return self.edit_quota( trans, **kwargs )
+ if operation == "manage users and groups":
+ return self.manage_users_and_groups_for_quota( trans, **kwargs )
+ if operation == "rename":
+ return self.rename_quota( trans, **kwargs )
+ if operation == "edit":
+ return self.edit_quota( trans, **kwargs )
+ # Render the list view
+ return self.quota_list_grid( trans, **kwargs )
+
+ @web.expose
+ @web.require_admin
+ def create_quota( self, trans, **kwd ):
+ params = self.get_quota_params( kwd )
+ if params.get( 'create_quota_button', False ):
+ try:
+ quota, message = self._create_quota( trans, params )
+ return trans.response.send_redirect( web.url_for( controller='admin',
+ action='quotas',
+ webapp=params.webapp,
+ message=util.sanitize_text( message ),
+ status='done' ) )
+ except MessageException, e:
+ params.message = str( e )
+ params.status = 'error'
+ in_users = map( int, params.in_users )
+ in_groups = map( int, params.in_groups )
+ new_in_users = []
+ new_in_groups = []
+ for user in trans.sa_session.query( trans.app.model.User ) \
+ .filter( trans.app.model.User.table.c.deleted==False ) \
+ .order_by( trans.app.model.User.table.c.email ):
+ if user.id in in_users:
+ new_in_users.append( ( user.id, user.email ) )
+ else:
+ params.out_users.append( ( user.id, user.email ) )
+ for group in trans.sa_session.query( trans.app.model.Group ) \
+ .filter( trans.app.model.Group.table.c.deleted==False ) \
+ .order_by( trans.app.model.Group.table.c.name ):
+ if group.id in in_groups:
+ new_in_groups.append( ( group.id, group.name ) )
+ else:
+ params.out_groups.append( ( group.id, group.name ) )
+ return trans.fill_template( '/admin/quota/quota_create.mako',
+ webapp=params.webapp,
+ name=params.name,
+ description=params.description,
+ amount=params.amount,
+ operation=params.operation,
+ default=params.default,
+ in_users=new_in_users,
+ out_users=params.out_users,
+ in_groups=new_in_groups,
+ out_groups=params.out_groups,
+ message=params.message,
+ status=params.status )
+
+ @web.expose
+ @web.require_admin
+ def rename_quota( self, trans, **kwd ):
+ quota, params = self._quota_op( trans, 'rename_quota_button', self._rename_quota, kwd )
+ if not quota:
+ return
+ return trans.fill_template( '/admin/quota/quota_rename.mako',
+ id=params.id,
+ name=params.name or quota.name,
+ description=params.description or quota.description,
+ webapp=params.webapp,
+ message=params.message,
+ status=params.status )
+
+ @web.expose
+ @web.require_admin
+ def manage_users_and_groups_for_quota( self, trans, **kwd ):
+ quota, params = self._quota_op( trans, 'quota_members_edit_button', self._manage_users_and_groups_for_quota, kwd )
+ if not quota:
+ return
+ in_users = []
+ out_users = []
+ in_groups = []
+ out_groups = []
+ for user in trans.sa_session.query( trans.app.model.User ) \
+ .filter( trans.app.model.User.table.c.deleted==False ) \
+ .order_by( trans.app.model.User.table.c.email ):
+ if user in [ x.user for x in quota.users ]:
+ in_users.append( ( user.id, user.email ) )
+ else:
+ out_users.append( ( user.id, user.email ) )
+ for group in trans.sa_session.query( trans.app.model.Group ) \
+ .filter( trans.app.model.Group.table.c.deleted==False ) \
+ .order_by( trans.app.model.Group.table.c.name ):
+ if group in [ x.group for x in quota.groups ]:
+ in_groups.append( ( group.id, group.name ) )
+ else:
+ out_groups.append( ( group.id, group.name ) )
+ return trans.fill_template( '/admin/quota/quota.mako',
+ id=params.id,
+ name=quota.name,
+ in_users=in_users,
+ out_users=out_users,
+ in_groups=in_groups,
+ out_groups=out_groups,
+ webapp=params.webapp,
+ message=params.message,
+ status=params.status )
+
+ @web.expose
+ @web.require_admin
+ def edit_quota( self, trans, **kwd ):
+ quota, params = self._quota_op( trans, 'edit_quota_button', self._edit_quota, kwd )
+ if not quota:
+ return
+ return trans.fill_template( '/admin/quota/quota_edit.mako',
+ id=params.id,
+ operation=params.operation or quota.operation,
+ display_amount=params.amount or quota.display_amount,
+ webapp=params.webapp,
+ message=params.message,
+ status=params.status )
+
+ @web.expose
+ @web.require_admin
+ def set_quota_default( self, trans, **kwd ):
+ quota, params = self._quota_op( trans, 'set_default_quota_button', self._set_quota_default, kwd )
+ if not quota:
+ return
+ if params.default:
+ default = params.default
+ elif quota.default:
+ default = quota.default[0].type
+ else:
+ default = "no"
+ return trans.fill_template( '/admin/quota/quota_set_default.mako',
+ id=params.id,
+ default=default,
+ webapp=params.webapp,
+ message=params.message,
+ status=params.status )
+
+ @web.expose
+ @web.require_admin
+ def unset_quota_default( self, trans, **kwd ):
+ quota, params = self._quota_op( trans, True, self._unset_quota_default, kwd )
+ if not quota:
+ return
+ return trans.response.send_redirect( web.url_for( controller='admin',
+ action='quotas',
+ webapp=params.webapp,
+ message=util.sanitize_text( params.message ),
+ status='error' ) )
+
+
+ @web.expose
+ @web.require_admin
+ def mark_quota_deleted( self, trans, **kwd ):
+ quota, params = self._quota_op( trans, True, self._mark_quota_deleted, kwd, listify=True )
+ if not quota:
+ return
+ return trans.response.send_redirect( web.url_for( controller='admin',
+ action='quotas',
+ webapp=params.webapp,
+ message=util.sanitize_text( params.message ),
+ status='error' ) )
+
+ @web.expose
+ @web.require_admin
+ def undelete_quota( self, trans, **kwd ):
+ quota, params = self._quota_op( trans, True, self._undelete_quota, kwd, listify=True )
+ if not quota:
+ return
+ return trans.response.send_redirect( web.url_for( controller='admin',
+ action='quotas',
+ webapp=params.webapp,
+ message=util.sanitize_text( params.message ),
+ status='error' ) )
+
+ @web.expose
+ @web.require_admin
+ def purge_quota( self, trans, **kwd ):
+ quota, params = self._quota_op( trans, True, self._purge_quota, kwd, listify=True )
+ if not quota:
+ return
+ return trans.response.send_redirect( web.url_for( controller='admin',
+ action='quotas',
+ webapp=params.webapp,
+ message=util.sanitize_text( params.message ),
+ status='error' ) )
+
+ def _quota_op( self, trans, do_op, op_method, kwd, listify=False ):
+ params = self.get_quota_params( kwd )
+ if listify:
+ quota = []
+ messages = []
+ for id in util.listify( params.id ):
+ try:
+ quota.append( self.get_quota( trans, id ) )
+ except MessageException, e:
+ messages.append( str( e ) )
+ if messages:
+ return None, trans.response.send_redirect( web.url_for( controller='admin',
+ action='quotas',
+ webapp=params.webapp,
+ message=util.sanitize_text( ', '.join( messages ) ),
+ status='error' ) )
+ else:
+ try:
+ quota = self.get_quota( trans, params.id, deleted=False )
+ except MessageException, e:
+ return None, trans.response.send_redirect( web.url_for( controller='admin',
+ action='quotas',
+ webapp=params.webapp,
+ message=util.sanitize_text( str( e ) ),
+ status='error' ) )
+ if do_op == True or ( do_op != False and params.get( do_op, False ) ):
+ try:
+ message = op_method( quota, params )
+ return None, trans.response.send_redirect( web.url_for( controller='admin',
+ action='quotas',
+ webapp=params.webapp,
+ message=util.sanitize_text( message ),
+ status='done' ) )
+ except MessageException, e:
+ params.message = e.err_msg
+ params.status = e.type
+ return quota, params
--- a/lib/galaxy/web/controllers/async.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/async.py Thu Sep 22 17:13:53 2011 -0400
@@ -11,7 +11,7 @@
log = logging.getLogger( __name__ )
-class ASync( BaseController ):
+class ASync( BaseUIController ):
@web.expose
def default(self, trans, tool_id=None, data_id=None, data_secret=None, **kwd):
--- a/lib/galaxy/web/controllers/dataset.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/dataset.py Thu Sep 22 17:13:53 2011 -0400
@@ -145,7 +145,7 @@
.filter( model.History.deleted==False ) \
.filter( self.model_class.visible==True )
-class DatasetInterface( BaseController, UsesAnnotations, UsesHistory, UsesHistoryDatasetAssociation, UsesItemRatings ):
+class DatasetInterface( BaseUIController, UsesAnnotations, UsesHistory, UsesHistoryDatasetAssociation, UsesItemRatings ):
stored_list_grid = HistoryDatasetAssociationListGrid()
--- a/lib/galaxy/web/controllers/error.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/error.py Thu Sep 22 17:13:53 2011 -0400
@@ -1,6 +1,6 @@
from galaxy.web.base.controller import *
-class Error( BaseController ):
+class Error( BaseUIController ):
@web.expose
def index( self, trans ):
raise Exception, "Fake error"
\ No newline at end of file
--- a/lib/galaxy/web/controllers/external_service.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/external_service.py Thu Sep 22 17:13:53 2011 -0400
@@ -63,7 +63,7 @@
grids.GridAction( "Create new external service", dict( controller='external_service', action='create_external_service' ) )
]
-class ExternalService( BaseController, UsesFormDefinitions ):
+class ExternalService( BaseUIController, UsesFormDefinitions ):
external_service_grid = ExternalServiceGrid()
@web.expose
--- a/lib/galaxy/web/controllers/external_services.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/external_services.py Thu Sep 22 17:13:53 2011 -0400
@@ -9,7 +9,7 @@
for model_class in [Sample]:
class_name_to_class[ model_class.__name__ ] = model_class
-class ExternalServiceController( BaseController ):
+class ExternalServiceController( BaseUIController ):
@web.expose
@web.require_admin
def access_action( self, trans, external_service_action, item, item_type, **kwd ):
--- a/lib/galaxy/web/controllers/forms.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/forms.py Thu Sep 22 17:13:53 2011 -0400
@@ -66,7 +66,7 @@
grids.GridAction( "Create new form", dict( controller='forms', action='create_form_definition' ) )
]
-class Forms( BaseController ):
+class Forms( BaseUIController ):
# Empty TextField
empty_field = { 'name': '',
'label': '',
--- a/lib/galaxy/web/controllers/history.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/history.py Thu Sep 22 17:13:53 2011 -0400
@@ -175,7 +175,7 @@
# A public history is published, has a slug, and is not deleted.
return query.filter( self.model_class.published == True ).filter( self.model_class.slug != None ).filter( self.model_class.deleted == False )
-class HistoryController( BaseController, Sharable, UsesAnnotations, UsesItemRatings, UsesHistory ):
+class HistoryController( BaseUIController, Sharable, UsesAnnotations, UsesItemRatings, UsesHistory ):
@web.expose
def index( self, trans ):
return ""
@@ -701,7 +701,7 @@
if not import_history:
return trans.show_error_message( "The specified history does not exist.<br>You can %s." % referer_message, use_panels=True )
# History is importable if user is admin or it's accessible. TODO: probably want to have app setting to enable admin access to histories.
- if not trans.user_is_admin() and not self.security_check( user, import_history, check_ownership=False, check_accessible=True ):
+ if not trans.user_is_admin() and not self.security_check( trans, import_history, check_ownership=False, check_accessible=True ):
return trans.show_error_message( "You cannot access this history.<br>You can %s." % referer_message, use_panels=True )
if user:
#dan: I can import my own history.
@@ -780,7 +780,7 @@
if history is None:
raise web.httpexceptions.HTTPNotFound()
# Security check raises error if user cannot access history.
- self.security_check( trans.get_user(), history, False, True)
+ self.security_check( trans, history, False, True)
# Get datasets.
datasets = self.get_history_datasets( trans, history )
--- a/lib/galaxy/web/controllers/library.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/library.py Thu Sep 22 17:13:53 2011 -0400
@@ -65,7 +65,7 @@
# public libraries and restricted libraries accessible by the current user.
return query.filter( or_( not_( trans.model.Library.table.c.id.in_( restricted_library_ids ) ),
trans.model.Library.table.c.id.in_( accessible_restricted_library_ids ) ) )
-class Library( BaseController ):
+class Library( BaseUIController ):
library_list_grid = LibraryListGrid()
--- a/lib/galaxy/web/controllers/library_admin.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/library_admin.py Thu Sep 22 17:13:53 2011 -0400
@@ -69,7 +69,7 @@
preserve_state = False
use_paging = True
-class LibraryAdmin( BaseController ):
+class LibraryAdmin( BaseUIController ):
library_list_grid = LibraryListGrid()
--- a/lib/galaxy/web/controllers/library_common.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/library_common.py Thu Sep 22 17:13:53 2011 -0400
@@ -68,7 +68,7 @@
pass
os.rmdir( tmpd )
-class LibraryCommon( BaseController, UsesFormDefinitions ):
+class LibraryCommon( BaseUIController, UsesFormDefinitions ):
@web.json
def library_item_updates( self, trans, ids=None, states=None ):
# Avoid caching
--- a/lib/galaxy/web/controllers/mobile.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/mobile.py Thu Sep 22 17:13:53 2011 -0400
@@ -1,6 +1,6 @@
from galaxy.web.base.controller import *
-class Mobile( BaseController ):
+class Mobile( BaseUIController ):
@web.expose
def index( self, trans, **kwargs ):
return trans.fill_template( "mobile/index.mako" )
--- a/lib/galaxy/web/controllers/page.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/page.py Thu Sep 22 17:13:53 2011 -0400
@@ -272,7 +272,7 @@
# Default behavior:
_BaseHTMLProcessor.unknown_endtag( self, tag )
-class PageController( BaseController, Sharable, UsesAnnotations, UsesHistory,
+class PageController( BaseUIController, Sharable, UsesAnnotations, UsesHistory,
UsesStoredWorkflow, UsesHistoryDatasetAssociation, UsesVisualization, UsesItemRatings ):
_page_list = PageListGrid()
@@ -533,7 +533,7 @@
annotations = from_json_string( annotations )
for annotation_dict in annotations:
item_id = trans.security.decode_id( annotation_dict[ 'item_id' ] )
- item_class = self.get_class( trans, annotation_dict[ 'item_class' ] )
+ item_class = self.get_class( annotation_dict[ 'item_class' ] )
item = trans.sa_session.query( item_class ).filter_by( id=item_id ).first()
if not item:
raise RuntimeError( "cannot find annotated item" )
@@ -582,7 +582,7 @@
if page is None:
raise web.httpexceptions.HTTPNotFound()
# Security check raises error if user cannot access page.
- self.security_check( trans.get_user(), page, False, True)
+ self.security_check( trans, page, False, True)
# Process page content.
processor = _PageContentProcessor( trans, 'utf-8', 'text/html', self._get_embed_html )
@@ -723,14 +723,14 @@
if not page:
err+msg( "Page not found" )
else:
- return self.security_check( trans.get_user(), page, check_ownership, check_accessible )
+ return self.security_check( trans, page, check_ownership, check_accessible )
def get_item( self, trans, id ):
return self.get_page( trans, id )
def _get_embed_html( self, trans, item_class, item_id ):
""" Returns HTML for embedding an item in a page. """
- item_class = self.get_class( trans, item_class )
+ item_class = self.get_class( item_class )
if item_class == model.History:
history = self.get_history( trans, item_id, False, True )
history.annotation = self.get_item_annotation_str( trans.sa_session, history.user, history )
--- a/lib/galaxy/web/controllers/request_type.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/request_type.py Thu Sep 22 17:13:53 2011 -0400
@@ -72,7 +72,7 @@
grids.GridAction( "Create new request type", dict( controller='request_type', action='create_request_type' ) )
]
-class RequestType( BaseController, UsesFormDefinitions ):
+class RequestType( BaseUIController, UsesFormDefinitions ):
request_type_grid = RequestTypeGrid()
@web.expose
--- a/lib/galaxy/web/controllers/requests.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/requests.py Thu Sep 22 17:13:53 2011 -0400
@@ -15,7 +15,7 @@
def apply_query_filter( self, trans, query, **kwd ):
return query.filter_by( user=trans.user )
-class Requests( BaseController ):
+class Requests( BaseUIController ):
request_grid = UserRequestsGrid()
@web.expose
--- a/lib/galaxy/web/controllers/requests_admin.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/requests_admin.py Thu Sep 22 17:13:53 2011 -0400
@@ -94,7 +94,7 @@
return query
return query.filter_by( sample_id=trans.security.decode_id( sample_id ) )
-class RequestsAdmin( BaseController, UsesFormDefinitions ):
+class RequestsAdmin( BaseUIController, UsesFormDefinitions ):
request_grid = AdminRequestsGrid()
datatx_grid = DataTransferGrid()
--- a/lib/galaxy/web/controllers/requests_common.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/requests_common.py Thu Sep 22 17:13:53 2011 -0400
@@ -93,7 +93,7 @@
confirm="Samples cannot be added to this request after it is submitted. Click OK to submit." )
]
-class RequestsCommon( BaseController, UsesFormDefinitions ):
+class RequestsCommon( BaseUIController, UsesFormDefinitions ):
@web.json
def sample_state_updates( self, trans, ids=None, states=None ):
# Avoid caching
--- a/lib/galaxy/web/controllers/root.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/root.py Thu Sep 22 17:13:53 2011 -0400
@@ -11,7 +11,7 @@
log = logging.getLogger( __name__ )
-class RootController( BaseController, UsesHistory, UsesAnnotations ):
+class RootController( BaseUIController, UsesHistory, UsesAnnotations ):
@web.expose
def default(self, trans, target1=None, target2=None, **kwd):
--- a/lib/galaxy/web/controllers/tag.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/tag.py Thu Sep 22 17:13:53 2011 -0400
@@ -8,9 +8,9 @@
log = logging.getLogger( __name__ )
-class TagsController ( BaseController ):
+class TagsController ( BaseUIController ):
def __init__( self, app ):
- BaseController.__init__( self, app )
+ BaseUIController.__init__( self, app )
self.tag_handler = app.tag_handler
@web.expose
@web.require_login( "edit item tags" )
@@ -72,7 +72,7 @@
if item_id is not None:
item = self._get_item( trans, item_class, trans.security.decode_id( item_id ) )
user = trans.user
- item_class = self.get_class( trans, item_class )
+ item_class = self.get_class( item_class )
q = q.encode( 'utf-8' )
if q.find( ":" ) == -1:
return self._get_tag_autocomplete_names( trans, q, limit, timestamp, user, item, item_class )
--- a/lib/galaxy/web/controllers/tool_runner.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/tool_runner.py Thu Sep 22 17:13:53 2011 -0400
@@ -17,7 +17,7 @@
self.debug = None
self.from_noframe = None
-class ToolRunner( BaseController ):
+class ToolRunner( BaseUIController ):
#Hack to get biomart to work, ideally, we could pass tool_id to biomart and receive it back
@web.expose
--- a/lib/galaxy/web/controllers/tracks.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/tracks.py Thu Sep 22 17:13:53 2011 -0400
@@ -162,7 +162,7 @@
def apply_query_filter( self, trans, query, **kwargs ):
return query.filter( self.model_class.user_id == trans.user.id )
-class TracksController( BaseController, UsesVisualization, UsesHistoryDatasetAssociation ):
+class TracksController( BaseUIController, UsesVisualization, UsesHistoryDatasetAssociation ):
"""
Controller for track browser interface. Handles building a new browser from
datasets in the current history, and display of the resulting browser.
--- a/lib/galaxy/web/controllers/ucsc_proxy.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/ucsc_proxy.py Thu Sep 22 17:13:53 2011 -0400
@@ -11,7 +11,7 @@
log = logging.getLogger( __name__ )
-class UCSCProxy( BaseController ):
+class UCSCProxy( BaseUIController ):
def create_display(self, store):
"""Creates a more meaningulf display name"""
--- a/lib/galaxy/web/controllers/user.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/user.py Thu Sep 22 17:13:53 2011 -0400
@@ -49,7 +49,7 @@
def build_initial_query( self, trans, **kwd ):
return trans.sa_session.query( self.model_class ).filter( self.model_class.user_id == trans.user.id )
-class User( BaseController, UsesFormDefinitions ):
+class User( BaseUIController, UsesFormDefinitions ):
user_openid_grid = UserOpenIDGrid()
installed_len_files = None
--- a/lib/galaxy/web/controllers/visualization.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/visualization.py Thu Sep 22 17:13:53 2011 -0400
@@ -68,7 +68,7 @@
return query.filter( self.model_class.deleted==False ).filter( self.model_class.published==True )
-class VisualizationController( BaseController, Sharable, UsesAnnotations,
+class VisualizationController( BaseUIController, Sharable, UsesAnnotations,
UsesHistoryDatasetAssociation, UsesVisualization,
UsesItemRatings ):
_user_list_grid = VisualizationListGrid()
@@ -299,7 +299,7 @@
raise web.httpexceptions.HTTPNotFound()
# Security check raises error if user cannot access visualization.
- self.security_check( trans.get_user(), visualization, False, True)
+ self.security_check( trans, visualization, False, True)
# Get rating data.
user_item_rating = 0
@@ -453,4 +453,4 @@
def get_item( self, trans, id ):
return self.get_visualization( trans, id )
-
\ No newline at end of file
+
--- a/lib/galaxy/web/controllers/workflow.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/controllers/workflow.py Thu Sep 22 17:13:53 2011 -0400
@@ -103,7 +103,7 @@
if self.cur_tag == self.target_tag:
self.tag_content += text
-class WorkflowController( BaseController, Sharable, UsesStoredWorkflow, UsesAnnotations, UsesItemRatings ):
+class WorkflowController( BaseUIController, Sharable, UsesStoredWorkflow, UsesAnnotations, UsesItemRatings ):
stored_list_grid = StoredWorkflowListGrid()
published_list_grid = StoredWorkflowAllPublishedGrid()
@@ -199,7 +199,7 @@
if stored_workflow is None:
raise web.httpexceptions.HTTPNotFound()
# Security check raises error if user cannot access workflow.
- self.security_check( trans.get_user(), stored_workflow, False, True)
+ self.security_check( trans, stored_workflow, False, True)
# Get data for workflow's steps.
self.get_stored_workflow_steps( trans, stored_workflow )
@@ -1016,7 +1016,7 @@
id = trans.security.decode_id( id )
trans.workflow_building_mode = True
stored = trans.sa_session.query( model.StoredWorkflow ).get( id )
- self.security_check( trans.get_user(), stored, False, True )
+ self.security_check( trans, stored, False, True )
# Convert workflow to dict.
workflow_dict = self._workflow_to_dict( trans, stored )
--- a/lib/galaxy/web/framework/__init__.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/framework/__init__.py Thu Sep 22 17:13:53 2011 -0400
@@ -10,6 +10,7 @@
import base
import pickle
from galaxy import util
+from galaxy.exceptions import MessageException
from galaxy.util.json import to_json_string, from_json_string
pkg_resources.require( "simplejson" )
@@ -19,6 +20,7 @@
pkg_resources.require( "PasteDeploy" )
from paste.deploy.converters import asbool
+import paste.httpexceptions
pkg_resources.require( "Mako" )
import mako.template
@@ -103,6 +105,9 @@
except NoResultFound:
error_message = 'Provided API key is not valid.'
return error
+ if provided_key.user.deleted:
+ error_message = 'User account is deactivated, please contact an administrator.'
+ return error
newest_key = provided_key.user.api_keys[0]
if newest_key.key != provided_key.key:
error_message = 'Provided API key has expired.'
@@ -135,10 +140,16 @@
trans.response.status = 400
return "That user does not exist."
- if trans.debug:
- return simplejson.dumps( func( self, trans, *args, **kwargs ), indent=4, sort_keys=True )
- else:
- return simplejson.dumps( func( self, trans, *args, **kwargs ) )
+ try:
+ if trans.debug:
+ return simplejson.dumps( func( self, trans, *args, **kwargs ), indent=4, sort_keys=True )
+ else:
+ return simplejson.dumps( func( self, trans, *args, **kwargs ) )
+ except paste.httpexceptions.HTTPException:
+ raise # handled
+ except:
+ log.exception( 'Uncaught exception in exposed API method:' )
+ raise paste.httpexceptions.HTTPServerError()
if not hasattr(func, '_orig'):
decorator._orig = func
decorator.exposed = True
@@ -164,14 +175,6 @@
NOT_SET = object()
-class MessageException( Exception ):
- """
- Exception to make throwing errors from deep in controllers easier
- """
- def __init__( self, err_msg, type="info" ):
- self.err_msg = err_msg
- self.type = type
-
def error( message ):
raise MessageException( message, type='error' )
--- a/lib/galaxy/web/framework/base.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/framework/base.py Thu Sep 22 17:13:53 2011 -0400
@@ -37,8 +37,8 @@
"""
collection_path = kwargs.get( 'path_prefix', '' ) + '/' + collection_name + '/deleted'
member_path = collection_path + '/:id'
- self.connect( 'deleted_' + collection_name, collection_path, controller=collection_name, action='index', deleted=True )
- self.connect( 'deleted_' + member_name, member_path, controller=collection_name, action='show', deleted=True )
+ self.connect( 'deleted_' + collection_name, collection_path, controller=collection_name, action='index', deleted=True, conditions=dict( method=['GET'] ) )
+ self.connect( 'deleted_' + member_name, member_path, controller=collection_name, action='show', deleted=True, conditions=dict( method=['GET'] ) )
self.connect( 'undelete_deleted_' + member_name, member_path + '/undelete', controller=collection_name, action='undelete',
conditions=dict( method=['POST'] ) )
self.resource( member_name, collection_name, **kwargs )
@@ -68,7 +68,7 @@
self.mapper.explicit = False
self.api_mapper = routes.Mapper()
self.transaction_factory = DefaultWebTransaction
- def add_controller( self, controller_name, controller ):
+ def add_ui_controller( self, controller_name, controller ):
"""
Add a controller class to this application. A controller class has
methods which handle web requests. To connect a URL to a controller's
--- a/lib/galaxy/web/security/__init__.py Thu Sep 22 12:18:38 2011 -0400
+++ b/lib/galaxy/web/security/__init__.py Thu Sep 22 17:13:53 2011 -0400
@@ -55,4 +55,3 @@
def get_new_guid( self ):
# Generate a unique, high entropy 128 bit random number
return get_random_bytes( 16 )
-
--- a/templates/admin/quota/quota.mako Thu Sep 22 12:18:38 2011 -0400
+++ b/templates/admin/quota/quota.mako Thu Sep 22 17:13:53 2011 -0400
@@ -32,7 +32,7 @@
$('#groups_remove_button').click(function() {
return !$('#in_groups option:selected').remove().appendTo('#out_groups');
});
- $('form#associate_role_user_group').submit(function() {
+ $('form#associate_quota_user_group').submit(function() {
$('#in_users option').each(function(i) {
$(this).attr("selected", "selected");
});
@@ -48,30 +48,30 @@
%endif
<div class="toolForm">
- <div class="toolFormTitle">Quota '${quota.name}'</div>
+ <div class="toolFormTitle">Quota '${name}'</div><div class="toolFormBody">
- <form name="associate_quota_user_group" id="associate_quota_user_group" action="${h.url_for( action='manage_users_and_groups_for_quota', id=trans.security.encode_id( quota.id ) )}" method="post" >
+ <form name="associate_quota_user_group" id="associate_quota_user_group" action="${h.url_for( action='manage_users_and_groups_for_quota', id=id )}" method="post" ><input name="webapp" type="hidden" value="${webapp}" size=40"/><div class="form-row"><div style="float: left; margin-right: 10px;">
- <label>Users associated with '${quota.name}'</label>
+ <label>Users associated with '${name}'</label>
${render_select( "in_users", in_users )}<br/><input type="submit" id="users_remove_button" value=">>"/></div><div>
- <label>Users not associated with '${quota.name}'</label>
+ <label>Users not associated with '${name}'</label>
${render_select( "out_users", out_users )}<br/><input type="submit" id="users_add_button" value="<<"/></div></div><div class="form-row"><div style="float: left; margin-right: 10px;">
- <label>Groups associated with '${quota.name}'</label>
+ <label>Groups associated with '${name}'</label>
${render_select( "in_groups", in_groups )}<br/><input type="submit" id="groups_remove_button" value=">>"/></div><div>
- <label>Groups not associated with '${quota.name}'</label>
+ <label>Groups not associated with '${name}'</label>
${render_select( "out_groups", out_groups )}<br/><input type="submit" id="groups_add_button" value="<<"/></div>
--- a/templates/admin/quota/quota_edit.mako Thu Sep 22 12:18:38 2011 -0400
+++ b/templates/admin/quota/quota_edit.mako Thu Sep 22 17:13:53 2011 -0400
@@ -14,7 +14,7 @@
from galaxy.web.form_builder import SelectField
operation_selectfield = SelectField( 'operation' )
for op in ( '=', '+', '-' ):
- selected = op == quota.operation
+ selected = op == operation
operation_selectfield.add_option( op, op, selected )
%>
@@ -27,10 +27,10 @@
<div class="toolFormBody"><form name="library" action="${h.url_for( controller='admin', action='edit_quota' )}" method="post" ><input name="webapp" type="hidden" value="${webapp}"/>
- <input name="id" type="hidden" value="${trans.security.encode_id( quota.id )}"/>
+ <input name="id" type="hidden" value="${id}"/><div class="form-row"><label>Amount</label>
- <input name="amount" type="textfield" value="${quota.display_amount}" size=40"/>
+ <input name="amount" type="textfield" value="${display_amount}" size=40"/><div class="toolParamHelp" style="clear: both;">
Examples: "10000MB", "99 gb", "0.2T", "unlimited"
</div>
--- a/templates/admin/quota/quota_rename.mako Thu Sep 22 12:18:38 2011 -0400
+++ b/templates/admin/quota/quota_rename.mako Thu Sep 22 17:13:53 2011 -0400
@@ -22,14 +22,14 @@
<input name="webapp" type="hidden" value="${webapp}" size=40"/><label>Name:</label><div style="float: left; width: 250px; margin-right: 10px;">
- <input type="text" name="name" value="${quota.name}" size="40"/>
+ <input type="text" name="name" value="${name}" size="40"/></div><div style="clear: both"></div></div><div class="form-row"><label>Description:</label><div style="float: left; width: 250px; margin-right: 10px;">
- <input name="description" type="textfield" value="${quota.description}" size=40"/>
+ <input name="description" type="textfield" value="${description}" size=40"/></div><div style="clear: both"></div></div>
@@ -41,7 +41,7 @@
</div><div class="form-row"><div style="float: left; width: 250px; margin-right: 10px;">
- <input type="hidden" name="id" value="${trans.security.encode_id( quota.id )}"/>
+ <input type="hidden" name="id" value="${id}"/></div><div style="clear: both"></div></div>
--- a/templates/admin/quota/quota_set_default.mako Thu Sep 22 12:18:38 2011 -0400
+++ b/templates/admin/quota/quota_set_default.mako Thu Sep 22 17:13:53 2011 -0400
@@ -25,11 +25,11 @@
%endif
<div class="toolForm">
- <div class="toolFormTitle">Create quota</div>
+ <div class="toolFormTitle">Set quota default</div><div class="toolFormBody"><form name="set_quota_default" id="set_quota_default" action="${h.url_for( action='set_quota_default' )}" method="post" ><input name="webapp" type="hidden" value="${webapp}" size=40"/>
- <input name="id" type="hidden" value="${trans.security.encode_id( quota.id )}"/>
+ <input name="id" type="hidden" value="${id}"/><div class="form-row"><label>Is this quota a default for a class of users (if yes, what type)?</label>
${default_selectfield.get_html()}
--- a/test/functional/test_history_functions.py Thu Sep 22 12:18:38 2011 -0400
+++ b/test/functional/test_history_functions.py Thu Sep 22 17:13:53 2011 -0400
@@ -203,7 +203,7 @@
self.login( email=regular_user2.email )
self.import_history_via_url( self.security.encode_id( history3.id ),
admin_user.email,
- strings_displayed_after_submit=[ 'History is not accessible to current user' ] )
+ strings_displayed_after_submit=[ 'History is not accessible to the current user' ] )
self.logout()
self.login( email=admin_user.email )
# Test sharing history3 with an invalid user
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: Improvements for dataset display on saved histories page: (1) performance improvements using a single query rather than iteration; and (2) do not count hidden datasets.
by Bitbucket 22 Sep '11
by Bitbucket 22 Sep '11
22 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/7850b1df5d39/
changeset: 7850b1df5d39
user: jgoecks
date: 2011-09-22 18:18:38
summary: Improvements for dataset display on saved histories page: (1) performance improvements using a single query rather than iteration; and (2) do not count hidden datasets.
affected #: 1 file (-1 bytes)
--- a/lib/galaxy/web/controllers/history.py Thu Sep 22 11:36:11 2011 -0400
+++ b/lib/galaxy/web/controllers/history.py Thu Sep 22 12:18:38 2011 -0400
@@ -11,7 +11,8 @@
from galaxy.tools.parameters.basic import UnvalidatedValue
from galaxy.tools.actions import upload_common
from galaxy.tags.tag_handler import GalaxyTagHandler
-from sqlalchemy.sql.expression import ClauseElement
+from sqlalchemy.sql.expression import ClauseElement, func
+from sqlalchemy.sql import select
import webhelpers, logging, operator, os, tempfile, subprocess, shutil, tarfile
from datetime import datetime
from cgi import escape
@@ -26,11 +27,29 @@
# Custom column types
class DatasetsByStateColumn( grids.GridColumn ):
def get_value( self, trans, grid, history ):
+ # Build query to get (state, count) pairs.
+ cols_to_select = [ trans.app.model.Dataset.table.c.state, func.count( '*' ) ]
+ from_obj = trans.app.model.HistoryDatasetAssociation.table.join( trans.app.model.Dataset.table )
+ where_clause = and_( trans.app.model.HistoryDatasetAssociation.table.c.history_id == history.id,
+ trans.app.model.HistoryDatasetAssociation.table.c.deleted == False,
+ trans.app.model.HistoryDatasetAssociation.table.c.visible == True,
+ )
+ group_by = trans.app.model.Dataset.table.c.state
+ query = select( columns=cols_to_select,
+ from_obj=from_obj,
+ whereclause=where_clause,
+ group_by=group_by )
+
+ # Process results.
+ state_count_dict = {}
+ for row in trans.sa_session.execute( query ):
+ state, count = row
+ state_count_dict[ state ] = count
rval = []
for state in ( 'ok', 'running', 'queued', 'error' ):
- total = sum( 1 for d in history.active_datasets if d.state == state )
- if total:
- rval.append( '<div class="count-box state-color-%s">%s</div>' % ( state, total ) )
+ count = state_count_dict.get( state, 0 )
+ if count:
+ rval.append( '<div class="count-box state-color-%s">%s</div>' % ( state, count ) )
else:
rval.append( '' )
return rval
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: dannon: Fix use_tasked_jobs to inherit the parent job's user.
by Bitbucket 22 Sep '11
by Bitbucket 22 Sep '11
22 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/3f926d934d98/
changeset: 3f926d934d98
user: dannon
date: 2011-09-22 17:36:11
summary: Fix use_tasked_jobs to inherit the parent job's user.
affected #: 1 file (-1 bytes)
--- a/lib/galaxy/jobs/__init__.py Wed Sep 21 16:50:18 2011 -0400
+++ b/lib/galaxy/jobs/__init__.py Thu Sep 22 11:36:11 2011 -0400
@@ -32,9 +32,9 @@
class JobManager( object ):
"""
Highest level interface to job management.
-
+
TODO: Currently the app accesses "job_queue" and "job_stop_queue" directly.
- This should be decoupled.
+ This should be decoupled.
"""
def __init__( self, app ):
self.app = app
@@ -71,7 +71,7 @@
class JobQueue( object ):
"""
- Job manager, waits for jobs to be runnable and then dispatches to
+ Job manager, waits for jobs to be runnable and then dispatches to
a JobRunner.
"""
STOP_SIGNAL = object()
@@ -95,7 +95,7 @@
self.running = True
self.dispatcher = dispatcher
self.monitor_thread = threading.Thread( target=self.__monitor )
- self.monitor_thread.start()
+ self.monitor_thread.start()
log.info( "job manager started" )
if app.config.get_bool( 'enable_job_recovery', True ):
self.__check_jobs_at_startup()
@@ -132,7 +132,7 @@
def __monitor( self ):
"""
- Continually iterate the waiting jobs, checking is each is ready to
+ Continually iterate the waiting jobs, checking is each is ready to
run and dispatching if so.
"""
# HACK: Delay until after forking, we need a way to do post fork notification!!!
@@ -180,12 +180,12 @@
jobs_to_check.append( self.sa_session.query( model.Job ).get( job_id ) )
except Empty:
pass
- # Iterate over new and waiting jobs and look for any that are
+ # Iterate over new and waiting jobs and look for any that are
# ready to run
new_waiting_jobs = []
for job in jobs_to_check:
try:
- # Check the job's dependencies, requeue if they're not done
+ # Check the job's dependencies, requeue if they're not done
job_state = self.__check_if_ready_to_run( job )
if job_state == JOB_WAIT:
if not self.track_jobs_in_database:
@@ -216,7 +216,7 @@
self.waiting_jobs = new_waiting_jobs
# Done with the session
self.sa_session.remove()
-
+
def __check_if_ready_to_run( self, job ):
"""
Check if a job is ready to run by verifying that each of its input
@@ -281,13 +281,13 @@
if len( user_jobs ) >= self.app.config.user_job_limit:
return JOB_WAIT
return JOB_READY
-
+
def put( self, job_id, tool ):
"""Add a job to the queue (by job identifier)"""
if not self.track_jobs_in_database:
self.queue.put( ( job_id, tool.id ) )
self.sleeper.wake()
-
+
def shutdown( self ):
"""Attempts to gracefully shut down the worker thread"""
if self.parent_pid != os.getpid():
@@ -304,7 +304,7 @@
class JobWrapper( object ):
"""
- Wraps a 'model.Job' with convenience methods for running processes and
+ Wraps a 'model.Job' with convenience methods for running processes and
state management.
"""
def __init__( self, job, queue ):
@@ -329,15 +329,15 @@
self.output_paths = None
self.tool_provided_job_metadata = None
# Wrapper holding the info required to restore and clean up from files used for setting metadata externally
- self.external_output_metadata = metadata.JobExternalOutputMetadataWrapper( job )
-
+ self.external_output_metadata = metadata.JobExternalOutputMetadataWrapper( job )
+
def get_job( self ):
return self.sa_session.query( model.Job ).get( self.job_id )
-
+
def get_id_tag(self):
# For compatability with drmaa, which uses job_id right now, and TaskWrapper
return str(self.job_id)
-
+
def get_param_dict( self ):
"""
Restore the dictionary of parameters from the database.
@@ -346,10 +346,10 @@
param_dict = dict( [ ( p.name, p.value ) for p in job.parameters ] )
param_dict = self.tool.params_from_strings( param_dict, self.app )
return param_dict
-
+
def get_version_string_path( self ):
return os.path.abspath(os.path.join(self.app.config.new_file_path, "GALAXY_VERSION_STRING_%s" % self.job_id))
-
+
def prepare( self ):
"""
Prepare the job to run by creating the working directory and the
@@ -371,9 +371,9 @@
out_data = dict( [ ( da.name, da.dataset ) for da in job.output_datasets ] )
inp_data.update( [ ( da.name, da.dataset ) for da in job.input_library_datasets ] )
out_data.update( [ ( da.name, da.dataset ) for da in job.output_library_datasets ] )
-
- # Set up output dataset association for export history jobs. Because job
- # uses a Dataset rather than an HDA or LDA, it's necessary to set up a
+
+ # Set up output dataset association for export history jobs. Because job
+ # uses a Dataset rather than an HDA or LDA, it's necessary to set up a
# fake dataset association that provides the needed attributes for
# preparing a job.
class FakeDatasetAssociation ( object ):
@@ -400,7 +400,7 @@
# ( this used to be performed in the "exec_before_job" hook, but hooks are deprecated ).
self.tool.exec_before_job( self.queue.app, inp_data, out_data, param_dict )
# Run the before queue ("exec_before_job") hook
- self.tool.call_hook( 'exec_before_job', self.queue.app, inp_data=inp_data,
+ self.tool.call_hook( 'exec_before_job', self.queue.app, inp_data=inp_data,
out_data=out_data, tool=self.tool, param_dict=incoming)
self.sa_session.flush()
# Build any required config files
@@ -433,7 +433,7 @@
def fail( self, message, exception=False ):
"""
- Indicate job failure by setting state and message on all output
+ Indicate job failure by setting state and message on all output
datasets.
"""
job = self.get_job()
@@ -479,7 +479,7 @@
if self.tool:
self.tool.job_failed( self, message, exception )
self.cleanup()
-
+
def change_state( self, state, info = False ):
job = self.get_job()
self.sa_session.refresh( job )
@@ -509,12 +509,12 @@
job.job_runner_external_id = external_id
self.sa_session.add( job )
self.sa_session.flush()
-
+
def finish( self, stdout, stderr ):
"""
- Called to indicate that the associated command has been run. Updates
+ Called to indicate that the associated command has been run. Updates
the output datasets based on stderr and stdout from the command, and
- the contents of the output files.
+ the contents of the output files.
"""
# default post job setup
self.sa_session.expunge_all()
@@ -536,7 +536,7 @@
if os.path.exists(version_filename):
self.version_string = open(version_filename).read()
os.unlink(version_filename)
-
+
if self.app.config.outputs_to_working_directory:
for dataset_path in self.get_output_fnames():
try:
@@ -584,7 +584,7 @@
else:
# Security violation.
log.exception( "from_work_dir specified a location not in the working directory: %s, %s" % ( source_file, self.working_directory ) )
-
+
dataset.blurb = 'done'
dataset.peek = 'no peek'
dataset.info = context['stdout'] + context['stderr']
@@ -599,7 +599,7 @@
dataset.init_meta( copy_from=dataset )
#if a dataset was copied, it won't appear in our dictionary:
#either use the metadata from originating output dataset, or call set_meta on the copies
- #it would be quicker to just copy the metadata from the originating output dataset,
+ #it would be quicker to just copy the metadata from the originating output dataset,
#but somewhat trickier (need to recurse up the copied_from tree), for now we'll call set_meta()
if not self.app.config.set_metadata_externally or \
( not self.external_output_metadata.external_metadata_set_successfully( dataset, self.sa_session ) \
@@ -611,7 +611,7 @@
#load metadata from file
#we need to no longer allow metadata to be edited while the job is still running,
#since if it is edited, the metadata changed on the running output will no longer match
- #the metadata that was stored to disk for use via the external process,
+ #the metadata that was stored to disk for use via the external process,
#and the changes made by the user will be lost, without warning or notice
dataset.metadata.from_JSON_dict( self.external_output_metadata.get_output_filenames_by_dataset( dataset, self.sa_session ).filename_out )
try:
@@ -652,13 +652,13 @@
# Flush all the dataset and job changes above. Dataset state changes
# will now be seen by the user.
self.sa_session.flush()
- # Save stdout and stderr
+ # Save stdout and stderr
if len( stdout ) > 32768:
log.error( "stdout for job %d is greater than 32K, only first part will be logged to database" % job.id )
job.stdout = stdout[:32768]
if len( stderr ) > 32768:
log.error( "stderr for job %d is greater than 32K, only first part will be logged to database" % job.id )
- job.stderr = stderr[:32768]
+ job.stderr = stderr[:32768]
# custom post process setup
inp_data = dict( [ ( da.name, da.dataset ) for da in job.input_datasets ] )
out_data = dict( [ ( da.name, da.dataset ) for da in job.output_datasets ] )
@@ -675,8 +675,8 @@
# ( this used to be performed in the "exec_after_process" hook, but hooks are deprecated ).
self.tool.exec_after_process( self.queue.app, inp_data, out_data, param_dict, job = job )
# Call 'exec_after_process' hook
- self.tool.call_hook( 'exec_after_process', self.queue.app, inp_data=inp_data,
- out_data=out_data, param_dict=param_dict,
+ self.tool.call_hook( 'exec_after_process', self.queue.app, inp_data=inp_data,
+ out_data=out_data, param_dict=param_dict,
tool=self.tool, stdout=stdout, stderr=stderr )
job.command_line = self.command_line
@@ -695,7 +695,7 @@
self.sa_session.flush()
log.debug( 'job %d ended' % self.job_id )
self.cleanup()
-
+
def cleanup( self ):
# remove temporary files
try:
@@ -709,10 +709,10 @@
galaxy.tools.imp_exp.JobImportHistoryArchiveWrapper( self.job_id ).cleanup_after_job( self.sa_session )
except:
log.exception( "Unable to cleanup job %d" % self.job_id )
-
+
def get_command_line( self ):
return self.command_line
-
+
def get_session_id( self ):
return self.session_id
@@ -865,7 +865,7 @@
Should be refactored into a generalized executable unit wrapper parent, then jobs and tasks.
"""
# Abstract this to be more useful for running tasks that *don't* necessarily compose a job.
-
+
def __init__(self, task, queue):
super(TaskWrapper, self).__init__(task.job, queue)
self.task_id = task.id
@@ -939,7 +939,7 @@
# ( this used to be performed in the "exec_before_job" hook, but hooks are deprecated ).
self.tool.exec_before_job( self.queue.app, inp_data, out_data, param_dict )
# Run the before queue ("exec_before_job") hook
- self.tool.call_hook( 'exec_before_job', self.queue.app, inp_data=inp_data,
+ self.tool.call_hook( 'exec_before_job', self.queue.app, inp_data=inp_data,
out_data=out_data, tool=self.tool, param_dict=incoming)
self.sa_session.flush()
# Build any required config files
@@ -986,12 +986,12 @@
task.state = state
self.sa_session.add( task )
self.sa_session.flush()
-
+
def get_state( self ):
task = self.get_task()
self.sa_session.refresh( task )
return task.state
-
+
def set_runner( self, runner_url, external_id ):
task = self.get_task()
self.sa_session.refresh( task )
@@ -1000,15 +1000,15 @@
# DBTODO Check task job_runner_stuff
self.sa_session.add( task )
self.sa_session.flush()
-
+
def finish( self, stdout, stderr ):
# 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) )
"""
- Called to indicate that the associated command has been run. Updates
+ Called to indicate that the associated command has been run. Updates
the output datasets based on stderr and stdout from the command, and
- the contents of the output files.
+ the contents of the output files.
"""
# default post job setup_external_metadata
self.sa_session.expunge_all()
@@ -1025,7 +1025,7 @@
task.state = task.states.ERROR
else:
task.state = task.states.OK
- # Save stdout and stderr
+ # 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 )
task.stdout = stdout[:32768]
@@ -1039,7 +1039,7 @@
def cleanup( self ):
# There is no task cleanup. The job cleans up for all tasks.
pass
-
+
def get_command_line( self ):
return self.command_line
@@ -1049,7 +1049,7 @@
def get_output_file_id( self, file ):
# There is no permanent output file for tasks.
return None
-
+
def get_tool_provided_job_metadata( self ):
# DBTODO Handle this as applicable for tasks.
return None
@@ -1071,10 +1071,6 @@
def setup_external_metadata( self, exec_dir = None, tmp_dir = None, dataset_files_path = None, config_root = None, datatypes_config = None, set_extension = True, **kwds ):
# There is no metadata setting for tasks. This is handled after the merge, at the job level.
return ""
-
- @property
- def user( self ):
- pass
class DefaultJobDispatcher( object ):
def __init__( self, app ):
@@ -1105,13 +1101,19 @@
runner = getattr( module, obj )
self.job_runners[name] = runner( self.app )
log.debug( 'Loaded job runner: %s' % display_name )
-
+
def put( self, job_wrapper ):
try:
- if self.app.config.use_tasked_jobs and job_wrapper.tool.parallelism is not None and not isinstance(job_wrapper, TaskWrapper):
- runner_name = "tasks"
- log.debug( "dispatching job %d to %s runner" %( job_wrapper.job_id, runner_name ) )
- self.job_runners[runner_name].put( job_wrapper )
+ if self.app.config.use_tasked_jobs and job_wrapper.tool.parallelism is not None:
+ if isinstance(job_wrapper, TaskWrapper):
+ #DBTODO Refactor
+ runner_name = ( job_wrapper.tool.job_runner.split(":", 1) )[0]
+ log.debug( "dispatching task %s, of job %d, to %s runner" %( job_wrapper.task_id, job_wrapper.job_id, runner_name ) )
+ self.job_runners[runner_name].put( job_wrapper )
+ else:
+ runner_name = "tasks"
+ log.debug( "dispatching job %d to %s runner" %( job_wrapper.job_id, runner_name ) )
+ self.job_runners[runner_name].put( job_wrapper )
else:
runner_name = ( job_wrapper.tool.job_runner.split(":", 1) )[0]
log.debug( "dispatching job %d to %s runner" %( job_wrapper.job_id, runner_name ) )
@@ -1167,7 +1169,7 @@
self.sleeper = Sleeper()
self.running = True
self.monitor_thread = threading.Thread( target=self.monitor )
- self.monitor_thread.start()
+ self.monitor_thread.start()
log.info( "job stopper started" )
def monitor( self ):
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: richard_burhans: aaChanges tool: Added an option to keep the columns from the SNP dataset
by Bitbucket 21 Sep '11
by Bitbucket 21 Sep '11
21 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/5c0412d06db9/
changeset: 5c0412d06db9
user: richard_burhans
date: 2011-09-21 22:50:18
summary: aaChanges tool: Added an option to keep the columns from the SNP dataset
affected #: 1 file (-1 bytes)
--- a/tools/evolution/codingSnps.xml Wed Sep 21 12:20:07 2011 -0400
+++ b/tools/evolution/codingSnps.xml Wed Sep 21 16:50:18 2011 -0400
@@ -2,7 +2,7 @@
<description>amino-acid changes caused by a set of SNPs</description><command interpreter="perl">
- codingSnps.pl $input1 $input2 Galaxy build=${input1.metadata.dbkey} loc=${GALAXY_DATA_INDEX_DIR}/codingSnps.loc chr=${input1.metadata.chromCol} start=${input1.metadata.startCol} end=${input1.metadata.endCol} snp=$col1 > $out_file1
+ codingSnps.pl $input1 $input2 Galaxy build=${input1.metadata.dbkey} loc=${GALAXY_DATA_INDEX_DIR}/codingSnps.loc chr=${input1.metadata.chromCol} start=${input1.metadata.startCol} end=${input1.metadata.endCol} snp=$col1 keepColumns=$keep > $out_file1
</command><inputs>
@@ -13,6 +13,10 @@
<param format="interval" name="input2" type="data" label="Gene dataset"><validator type="dataset_metadata_in_file" filename="codingSnps.loc" metadata_name="dbkey" metadata_column="0" message="Sequences are not currently available for the specified build." split="\t" /></param>
+ <param name="keep" type="select" label="Keep columns from SNP dataset">
+ <option value="0" selected="true">No</option>
+ <option value="1">Yes</option>
+ </param></inputs><outputs>
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: Read and write summary tree in binary; this mitigates problems in reading summary tree file on some platforms.
by Bitbucket 21 Sep '11
by Bitbucket 21 Sep '11
21 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/b2c68b980ffc/
changeset: b2c68b980ffc
user: jgoecks
date: 2011-09-21 18:20:07
summary: Read and write summary tree in binary; this mitigates problems in reading summary tree file on some platforms.
affected #: 1 file (-1 bytes)
--- a/lib/galaxy/visualization/tracks/summary.py Wed Sep 21 11:36:58 2011 -0400
+++ b/lib/galaxy/visualization/tracks/summary.py Wed Sep 21 12:20:07 2011 -0400
@@ -89,5 +89,5 @@
cPickle.dump(self, open(filename, 'wb'), 2)
def summary_tree_from_file(filename):
- return cPickle.load(open(filename, "r"))
+ return cPickle.load(open(filename, "rb"))
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/ce13c0d3a3d7/
changeset: ce13c0d3a3d7
user: dan
date: 2011-09-21 10:11:07
summary: Tool help updates.
affected #: 134 files (-1 bytes)
--- a/tools/annotation_profiler/annotation_profiler.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/annotation_profiler/annotation_profiler.xml Wed Sep 21 04:11:07 2011 -0400
@@ -132,5 +132,11 @@
**TIP:** non-redundant (nr) refers to the set of intervals that remains after the intervals provided have been merged to resolve overlaps
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/emboss_5/emboss_antigenic.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_antigenic.xml Wed Sep 21 04:11:07 2011 -0400
@@ -44,6 +44,13 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/antigenic.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/antigenic.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
+
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_backtranseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_backtranseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -215,6 +215,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/backtranseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/backtranseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_banana.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_banana.xml Wed Sep 21 04:11:07 2011 -0400
@@ -19,6 +19,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/banana.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/banana.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_biosed.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_biosed.xml Wed Sep 21 04:11:07 2011 -0400
@@ -1,7 +1,7 @@
<tool id="EMBOSS: biosed4" name="biosed" version="5.0.0"><description>Replace or delete sequence sections</description><requirements><requirement type="package" version="5.0.0">emboss</requirement></requirements>
- <command>biosed -sequence $input1 -outseq $out_file1 -target $target -replace $replace -osformat2 $out_format1 -auto</command>
+ <command>biosed -sequence $input1 -outseq $out_file1 -target "$target" -replace "$replace" -osformat2 "$out_format1" -auto</command><inputs><param format="fasta" name="input1" type="data"><label>On query</label>
@@ -68,6 +68,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/biosed.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/biosed.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_btwisted.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_btwisted.xml Wed Sep 21 04:11:07 2011 -0400
@@ -19,6 +19,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/btwisted.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/btwisted.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_cai.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_cai.xml Wed Sep 21 04:11:07 2011 -0400
@@ -180,6 +180,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/cai.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/cai.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_cai_custom.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_cai_custom.xml Wed Sep 21 04:11:07 2011 -0400
@@ -22,6 +22,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/cai_custom.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/cai_custom.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_chaos.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_chaos.xml Wed Sep 21 04:11:07 2011 -0400
@@ -18,6 +18,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/chaos.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/chaos.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_charge.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_charge.xml Wed Sep 21 04:11:07 2011 -0400
@@ -30,6 +30,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/charge.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/charge.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_checktrans.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_checktrans.xml Wed Sep 21 04:11:07 2011 -0400
@@ -82,6 +82,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/checktrans.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/checktrans.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_chips.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_chips.xml Wed Sep 21 04:11:07 2011 -0400
@@ -25,6 +25,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/chips.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/chips.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_cirdna.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_cirdna.xml Wed Sep 21 04:11:07 2011 -0400
@@ -18,6 +18,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/cirdna.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/cirdna.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_codcmp.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_codcmp.xml Wed Sep 21 04:11:07 2011 -0400
@@ -325,6 +325,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/codcmp.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/codcmp.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_coderet.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_coderet.xml Wed Sep 21 04:11:07 2011 -0400
@@ -68,6 +68,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/coderet.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/coderet.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_compseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_compseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -37,6 +37,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/compseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/compseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_cpgplot.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_cpgplot.xml Wed Sep 21 04:11:07 2011 -0400
@@ -28,6 +28,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/cpgplot.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/cpgplot.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_cpgreport.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_cpgreport.xml Wed Sep 21 04:11:07 2011 -0400
@@ -44,6 +44,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/cpgreport.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/cpgreport.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_cusp.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_cusp.xml Wed Sep 21 04:11:07 2011 -0400
@@ -25,6 +25,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/cusp.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/cusp.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_cutseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_cutseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -67,6 +67,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/cutseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/cutseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_dan.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_dan.xml Wed Sep 21 04:11:07 2011 -0400
@@ -79,6 +79,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/dan.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/dan.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_degapseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_degapseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -53,6 +53,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/degapseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/degapseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_descseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_descseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -67,6 +67,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/descseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/descseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_diffseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_diffseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -59,6 +59,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/diffseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/diffseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_digest.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_digest.xml Wed Sep 21 04:11:07 2011 -0400
@@ -60,6 +60,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/digest.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/digest.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_dotmatcher.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_dotmatcher.xml Wed Sep 21 04:11:07 2011 -0400
@@ -24,6 +24,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/dotmatcher.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/dotmatcher.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_dotpath.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_dotpath.xml Wed Sep 21 04:11:07 2011 -0400
@@ -31,6 +31,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/dotpath.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/dotpath.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_dottup.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_dottup.xml Wed Sep 21 04:11:07 2011 -0400
@@ -25,6 +25,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/dottup.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/dottup.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_dreg.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_dreg.xml Wed Sep 21 04:11:07 2011 -0400
@@ -17,6 +17,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/dreg.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/dreg.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_einverted.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_einverted.xml Wed Sep 21 04:11:07 2011 -0400
@@ -45,6 +45,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/einverted.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/einverted.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_epestfind.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_epestfind.xml Wed Sep 21 04:11:07 2011 -0400
@@ -60,6 +60,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/epestfind.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/epestfind.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_equicktandem.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_equicktandem.xml Wed Sep 21 04:11:07 2011 -0400
@@ -55,6 +55,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/equicktandem.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/equicktandem.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_est2genome.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_est2genome.xml Wed Sep 21 04:11:07 2011 -0400
@@ -98,6 +98,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/est2genome.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/est2genome.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_etandem.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_etandem.xml Wed Sep 21 04:11:07 2011 -0400
@@ -71,7 +71,13 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/etandem.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/etandem.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_extractfeat.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_extractfeat.xml Wed Sep 21 04:11:07 2011 -0400
@@ -92,5 +92,11 @@
You can view the original documentation here_.
.. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/extractfeat.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_extractseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_extractseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -63,6 +63,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/extractseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/extractseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_freak.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_freak.xml Wed Sep 21 04:11:07 2011 -0400
@@ -31,6 +31,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/freak.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/freak.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_fuzznuc.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_fuzznuc.xml Wed Sep 21 04:11:07 2011 -0400
@@ -70,6 +70,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/fuzznuc.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/fuzznuc.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_fuzzpro.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_fuzzpro.xml Wed Sep 21 04:11:07 2011 -0400
@@ -39,6 +39,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/fuzzpro.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/fuzzpro.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_fuzztran.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_fuzztran.xml Wed Sep 21 04:11:07 2011 -0400
@@ -90,6 +90,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/fuzztran.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/fuzztran.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_garnier.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_garnier.xml Wed Sep 21 04:11:07 2011 -0400
@@ -53,6 +53,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/4.0/emboss/apps/garnier.html
+ .. _here: http://emboss.sourceforge.net/apps/release/4.0/emboss/apps/garnier.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_geecee.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_geecee.xml Wed Sep 21 04:11:07 2011 -0400
@@ -19,6 +19,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/geecee.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/geecee.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_getorf.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_getorf.xml Wed Sep 21 04:11:07 2011 -0400
@@ -124,6 +124,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/getorf.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/getorf.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_helixturnhelix.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_helixturnhelix.xml Wed Sep 21 04:11:07 2011 -0400
@@ -58,6 +58,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/helixturnhelix.h…
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/helixturnhelix.h…
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_hmoment.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_hmoment.xml Wed Sep 21 04:11:07 2011 -0400
@@ -27,6 +27,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/hmoment.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/hmoment.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_iep.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_iep.xml Wed Sep 21 04:11:07 2011 -0400
@@ -33,6 +33,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/iep.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/iep.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_infoseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_infoseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -71,6 +71,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/infoseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/infoseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_isochore.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_isochore.xml Wed Sep 21 04:11:07 2011 -0400
@@ -78,5 +78,11 @@
.. image:: ./static/emboss_icons/isochore.png
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
+
</help></tool>
--- a/tools/emboss_5/emboss_lindna.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_lindna.xml Wed Sep 21 04:11:07 2011 -0400
@@ -94,6 +94,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/lindna.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/lindna.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_marscan.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_marscan.xml Wed Sep 21 04:11:07 2011 -0400
@@ -40,6 +40,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/marscan.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/marscan.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_maskfeat.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_maskfeat.xml Wed Sep 21 04:11:07 2011 -0400
@@ -67,6 +67,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/maskfeat.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/maskfeat.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_maskseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_maskseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -67,6 +67,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/maskseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/maskseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_matcher.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_matcher.xml Wed Sep 21 04:11:07 2011 -0400
@@ -52,6 +52,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/matcher.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/matcher.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_megamerger.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_megamerger.xml Wed Sep 21 04:11:07 2011 -0400
@@ -58,6 +58,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/megamerger.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/megamerger.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_merger.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_merger.xml Wed Sep 21 04:11:07 2011 -0400
@@ -71,6 +71,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/merger.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/merger.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_msbar.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_msbar.xml Wed Sep 21 04:11:07 2011 -0400
@@ -112,6 +112,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/msbar.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/msbar.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_needle.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_needle.xml Wed Sep 21 04:11:07 2011 -0400
@@ -121,6 +121,12 @@
#---------------------------------------
#---------------------------------------
-
+
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_newcpgreport.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_newcpgreport.xml Wed Sep 21 04:11:07 2011 -0400
@@ -39,6 +39,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/newcpgreport.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/newcpgreport.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_newcpgseek.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_newcpgseek.xml Wed Sep 21 04:11:07 2011 -0400
@@ -30,6 +30,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/newcpgseek.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/newcpgseek.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_newseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_newseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -67,6 +67,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/newseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/newseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_noreturn.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_noreturn.xml Wed Sep 21 04:11:07 2011 -0400
@@ -26,6 +26,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/noreturn.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/noreturn.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_notseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_notseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -64,6 +64,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/notseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/notseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_nthseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_nthseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -64,6 +64,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/nthseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/nthseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_octanol.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_octanol.xml Wed Sep 21 04:11:07 2011 -0400
@@ -34,5 +34,11 @@
You can view the original documentation here_.
.. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/octanol.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_oddcomp.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_oddcomp.xml Wed Sep 21 04:11:07 2011 -0400
@@ -35,6 +35,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/oddcomp.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/oddcomp.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_palindrome.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_palindrome.xml Wed Sep 21 04:11:07 2011 -0400
@@ -48,6 +48,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/palindrome.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/palindrome.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_pasteseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_pasteseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -68,6 +68,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/pasteseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/pasteseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_patmatdb.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_patmatdb.xml Wed Sep 21 04:11:07 2011 -0400
@@ -44,6 +44,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/patmatdb.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/patmatdb.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_pepcoil.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_pepcoil.xml Wed Sep 21 04:11:07 2011 -0400
@@ -41,6 +41,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/pepcoil.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/pepcoil.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_pepinfo.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_pepinfo.xml Wed Sep 21 04:11:07 2011 -0400
@@ -23,6 +23,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/pepinfo.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/pepinfo.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_pepnet.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_pepnet.xml Wed Sep 21 04:11:07 2011 -0400
@@ -28,6 +28,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/pepnet.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/pepnet.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_pepstats.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_pepstats.xml Wed Sep 21 04:11:07 2011 -0400
@@ -25,6 +25,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/pepstats.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/pepstats.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_pepwheel.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_pepwheel.xml Wed Sep 21 04:11:07 2011 -0400
@@ -40,6 +40,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/pepwheel.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/pepwheel.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_pepwindow.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_pepwindow.xml Wed Sep 21 04:11:07 2011 -0400
@@ -17,6 +17,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/pepwindow.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/pepwindow.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_pepwindowall.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_pepwindowall.xml Wed Sep 21 04:11:07 2011 -0400
@@ -17,6 +17,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/pepwindowall.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/pepwindowall.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_plotcon.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_plotcon.xml Wed Sep 21 04:11:07 2011 -0400
@@ -17,6 +17,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/plotcon.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/plotcon.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_plotorf.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_plotorf.xml Wed Sep 21 04:11:07 2011 -0400
@@ -35,6 +35,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/plotorf.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/plotorf.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_polydot.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_polydot.xml Wed Sep 21 04:11:07 2011 -0400
@@ -43,6 +43,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/polydot.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/polydot.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_preg.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_preg.xml Wed Sep 21 04:11:07 2011 -0400
@@ -16,6 +16,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/preg.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/preg.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_prettyplot.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_prettyplot.xml Wed Sep 21 04:11:07 2011 -0400
@@ -108,6 +108,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/prettyplot.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/prettyplot.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_prettyseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_prettyseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -48,6 +48,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/prettyseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/prettyseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_primersearch.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_primersearch.xml Wed Sep 21 04:11:07 2011 -0400
@@ -28,6 +28,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/primersearch.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/primersearch.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_revseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_revseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -72,6 +72,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/revseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/revseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_seqmatchall.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_seqmatchall.xml Wed Sep 21 04:11:07 2011 -0400
@@ -49,6 +49,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/seqmatchall.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/seqmatchall.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_seqret.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_seqret.xml Wed Sep 21 04:11:07 2011 -0400
@@ -65,6 +65,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/seqret.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/seqret.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_showfeat.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_showfeat.xml Wed Sep 21 04:11:07 2011 -0400
@@ -118,6 +118,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/showfeat.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/showfeat.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_shuffleseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_shuffleseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -57,6 +57,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/shuffleseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/shuffleseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_sigcleave.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_sigcleave.xml Wed Sep 21 04:11:07 2011 -0400
@@ -50,6 +50,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/sigcleave.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/sigcleave.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_sirna.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_sirna.xml Wed Sep 21 04:11:07 2011 -0400
@@ -113,6 +113,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/sirna.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/sirna.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_sixpack.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_sixpack.xml Wed Sep 21 04:11:07 2011 -0400
@@ -157,6 +157,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/sixpack.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/sixpack.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_skipseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_skipseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -54,6 +54,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/skipseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/skipseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_splitter.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_splitter.xml Wed Sep 21 04:11:07 2011 -0400
@@ -74,6 +74,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/splitter.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/splitter.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_supermatcher.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_supermatcher.xml Wed Sep 21 04:11:07 2011 -0400
@@ -59,6 +59,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/supermatcher.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/supermatcher.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_syco.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_syco.xml Wed Sep 21 04:11:07 2011 -0400
@@ -192,6 +192,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/syco.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/syco.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_tcode.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_tcode.xml Wed Sep 21 04:11:07 2011 -0400
@@ -39,6 +39,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/tcode.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/tcode.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_textsearch.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_textsearch.xml Wed Sep 21 04:11:07 2011 -0400
@@ -53,6 +53,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/textsearch.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/textsearch.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_tmap.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_tmap.xml Wed Sep 21 04:11:07 2011 -0400
@@ -34,6 +34,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/tmap.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/tmap.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_tranalign.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_tranalign.xml Wed Sep 21 04:11:07 2011 -0400
@@ -79,6 +79,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/tranalign.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/tranalign.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_transeq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_transeq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -117,6 +117,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/transeq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/transeq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_trimest.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_trimest.xml Wed Sep 21 04:11:07 2011 -0400
@@ -87,6 +87,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/trimest.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/trimest.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_trimseq.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_trimseq.xml Wed Sep 21 04:11:07 2011 -0400
@@ -92,6 +92,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/trimseq.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/trimseq.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_twofeat.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_twofeat.xml Wed Sep 21 04:11:07 2011 -0400
@@ -125,6 +125,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/twofeat.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/twofeat.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
\ No newline at end of file
--- a/tools/emboss_5/emboss_union.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_union.xml Wed Sep 21 04:11:07 2011 -0400
@@ -60,6 +60,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/union.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/union.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_vectorstrip.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_vectorstrip.xml Wed Sep 21 04:11:07 2011 -0400
@@ -77,6 +77,12 @@
<help>
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/vectorstrip.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/vectorstrip.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_water.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_water.xml Wed Sep 21 04:11:07 2011 -0400
@@ -61,6 +61,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/water.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/water.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_wobble.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_wobble.xml Wed Sep 21 04:11:07 2011 -0400
@@ -35,6 +35,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/wobble.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/wobble.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_wordcount.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_wordcount.xml Wed Sep 21 04:11:07 2011 -0400
@@ -30,6 +30,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/wordcount.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/wordcount.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/emboss_5/emboss_wordmatch.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/emboss_5/emboss_wordmatch.xml Wed Sep 21 04:11:07 2011 -0400
@@ -69,6 +69,12 @@
You can view the original documentation here_.
- .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/wordmatch.html
+ .. _here: http://emboss.sourceforge.net/apps/release/5.0/emboss/apps/wordmatch.html
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
</help></tool>
--- a/tools/encode/gencode_partition.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/encode/gencode_partition.xml Wed Sep 21 04:11:07 2011 -0400
@@ -35,5 +35,11 @@
**Note:** Features overlapping more than one partition will take the identity of the lower-numbered partition.
+------
+
+**Citation**
+
+If you use this tool, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
+
</help></tool>
\ No newline at end of file
--- a/tools/encode/random_intervals.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/encode/random_intervals.xml Wed Sep 21 04:11:07 2011 -0400
@@ -54,5 +54,11 @@
**Regions to use** options
* Bounding region of interest based on the dataset build.
+------
+
+**Citation**
+
+If you use this tool, please cite `Blankenberg D, Taylor J, Schenck I, He J, Zhang Y, Ghent M, Veeraraghavan N, Albert I, Miller W, Makova KD, Hardison RC, Nekrutenko A. A framework for collaborative analysis of ENCODE data: making large-scale analyses biologist-friendly. Genome Res. 2007 Jun;17(6):960-4. <http://www.ncbi.nlm.nih.gov/pubmed/17568012>`_
+
</help></tool>
\ No newline at end of file
--- a/tools/evolution/mutate_snp_codon.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/evolution/mutate_snp_codon.xml Wed Sep 21 04:11:07 2011 -0400
@@ -56,5 +56,12 @@
chr1 59373 59376 NM_001005484 0 + ACA ACA Thr ACA 614523 15.11 0 2162384 0.284187729839 585 chr1 59373 59374 rs2691305 0 - A A C/T genomic single unknown 0 0 unknown exact 3 GCA
chr1 59412 59415 NM_001005484 0 + GCG GCG Ala GCG 299495 7.37 0 2820741 0.106176001271 585 chr1 59414 59415 rs2531266 0 + G G C/G genomic single by-submitter 0 0 unknown exact 3 GCC
chr1 59412 59415 NM_001005484 0 + GCG GCG Ala GCG 299495 7.37 0 2820741 0.106176001271 585 chr1 59414 59415 rs55874132 0 + G G C/G genomic single unknown 0 0 coding-synon exact 1 GCC
+
+------
+
+**Citation**
+
+If you use this tool, please cite `Blankenberg D, Taylor J, Nekrutenko A; The Galaxy Team. Making whole genome multiple alignments usable for biologists. Bioinformatics. 2011 Sep 1;27(17):2426-2428. <http://www.ncbi.nlm.nih.gov/pubmed/21775304>`_
+
</help></tool>
--- a/tools/gatk/analyze_covariates.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/gatk/analyze_covariates.xml Wed Sep 21 04:11:07 2011 -0400
@@ -96,5 +96,7 @@
For the underlying tool, please cite `DePristo MA, Banks E, Poplin R, Garimella KV, Maguire JR, Hartl C, Philippakis AA, del Angel G, Rivas MA, Hanna M, McKenna A, Fennell TJ, Kernytsky AM, Sivachenko AY, Cibulskis K, Gabriel SB, Altshuler D, Daly MJ. A framework for variation discovery and genotyping using next-generation DNA sequencing data. Nat Genet. 2011 May;43(5):491-8. <http://www.ncbi.nlm.nih.gov/pubmed/21478889>`_
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/gatk/count_covariates.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/gatk/count_covariates.xml Wed Sep 21 04:11:07 2011 -0400
@@ -431,5 +431,7 @@
For the underlying tool, please cite `DePristo MA, Banks E, Poplin R, Garimella KV, Maguire JR, Hartl C, Philippakis AA, del Angel G, Rivas MA, Hanna M, McKenna A, Fennell TJ, Kernytsky AM, Sivachenko AY, Cibulskis K, Gabriel SB, Altshuler D, Daly MJ. A framework for variation discovery and genotyping using next-generation DNA sequencing data. Nat Genet. 2011 May;43(5):491-8. <http://www.ncbi.nlm.nih.gov/pubmed/21478889>`_
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/gatk/indel_realigner.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/gatk/indel_realigner.xml Wed Sep 21 04:11:07 2011 -0400
@@ -347,5 +347,7 @@
For the underlying tool, please cite `DePristo MA, Banks E, Poplin R, Garimella KV, Maguire JR, Hartl C, Philippakis AA, del Angel G, Rivas MA, Hanna M, McKenna A, Fennell TJ, Kernytsky AM, Sivachenko AY, Cibulskis K, Gabriel SB, Altshuler D, Daly MJ. A framework for variation discovery and genotyping using next-generation DNA sequencing data. Nat Genet. 2011 May;43(5):491-8. <http://www.ncbi.nlm.nih.gov/pubmed/21478889>`_
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/gatk/realigner_target_creator.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/gatk/realigner_target_creator.xml Wed Sep 21 04:11:07 2011 -0400
@@ -301,5 +301,7 @@
For the underlying tool, please cite `DePristo MA, Banks E, Poplin R, Garimella KV, Maguire JR, Hartl C, Philippakis AA, del Angel G, Rivas MA, Hanna M, McKenna A, Fennell TJ, Kernytsky AM, Sivachenko AY, Cibulskis K, Gabriel SB, Altshuler D, Daly MJ. A framework for variation discovery and genotyping using next-generation DNA sequencing data. Nat Genet. 2011 May;43(5):491-8. <http://www.ncbi.nlm.nih.gov/pubmed/21478889>`_
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/gatk/table_recalibration.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/gatk/table_recalibration.xml Wed Sep 21 04:11:07 2011 -0400
@@ -399,5 +399,7 @@
For the underlying tool, please cite `DePristo MA, Banks E, Poplin R, Garimella KV, Maguire JR, Hartl C, Philippakis AA, del Angel G, Rivas MA, Hanna M, McKenna A, Fennell TJ, Kernytsky AM, Sivachenko AY, Cibulskis K, Gabriel SB, Altshuler D, Daly MJ. A framework for variation discovery and genotyping using next-generation DNA sequencing data. Nat Genet. 2011 May;43(5):491-8. <http://www.ncbi.nlm.nih.gov/pubmed/21478889>`_
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/gatk/unified_genotyper.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/gatk/unified_genotyper.xml Wed Sep 21 04:11:07 2011 -0400
@@ -420,5 +420,7 @@
For the underlying tool, please cite `DePristo MA, Banks E, Poplin R, Garimella KV, Maguire JR, Hartl C, Philippakis AA, del Angel G, Rivas MA, Hanna M, McKenna A, Fennell TJ, Kernytsky AM, Sivachenko AY, Cibulskis K, Gabriel SB, Altshuler D, Daly MJ. A framework for variation discovery and genotyping using next-generation DNA sequencing data. Nat Genet. 2011 May;43(5):491-8. <http://www.ncbi.nlm.nih.gov/pubmed/21478889>`_
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/gatk/variant_annotator.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/gatk/variant_annotator.xml Wed Sep 21 04:11:07 2011 -0400
@@ -412,5 +412,7 @@
For the underlying tool, please cite `DePristo MA, Banks E, Poplin R, Garimella KV, Maguire JR, Hartl C, Philippakis AA, del Angel G, Rivas MA, Hanna M, McKenna A, Fennell TJ, Kernytsky AM, Sivachenko AY, Cibulskis K, Gabriel SB, Altshuler D, Daly MJ. A framework for variation discovery and genotyping using next-generation DNA sequencing data. Nat Genet. 2011 May;43(5):491-8. <http://www.ncbi.nlm.nih.gov/pubmed/21478889>`_
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/gatk/variant_apply_recalibration.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/gatk/variant_apply_recalibration.xml Wed Sep 21 04:11:07 2011 -0400
@@ -273,5 +273,7 @@
For the underlying tool, please cite `DePristo MA, Banks E, Poplin R, Garimella KV, Maguire JR, Hartl C, Philippakis AA, del Angel G, Rivas MA, Hanna M, McKenna A, Fennell TJ, Kernytsky AM, Sivachenko AY, Cibulskis K, Gabriel SB, Altshuler D, Daly MJ. A framework for variation discovery and genotyping using next-generation DNA sequencing data. Nat Genet. 2011 May;43(5):491-8. <http://www.ncbi.nlm.nih.gov/pubmed/21478889>`_
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/gatk/variant_combine.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/gatk/variant_combine.xml Wed Sep 21 04:11:07 2011 -0400
@@ -306,6 +306,7 @@
For the underlying tool, please cite `DePristo MA, Banks E, Poplin R, Garimella KV, Maguire JR, Hartl C, Philippakis AA, del Angel G, Rivas MA, Hanna M, McKenna A, Fennell TJ, Kernytsky AM, Sivachenko AY, Cibulskis K, Gabriel SB, Altshuler D, Daly MJ. A framework for variation discovery and genotyping using next-generation DNA sequencing data. Nat Genet. 2011 May;43(5):491-8. <http://www.ncbi.nlm.nih.gov/pubmed/21478889>`_
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
</help></tool>
--- a/tools/gatk/variant_eval.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/gatk/variant_eval.xml Wed Sep 21 04:11:07 2011 -0400
@@ -420,5 +420,7 @@
For the underlying tool, please cite `DePristo MA, Banks E, Poplin R, Garimella KV, Maguire JR, Hartl C, Philippakis AA, del Angel G, Rivas MA, Hanna M, McKenna A, Fennell TJ, Kernytsky AM, Sivachenko AY, Cibulskis K, Gabriel SB, Altshuler D, Daly MJ. A framework for variation discovery and genotyping using next-generation DNA sequencing data. Nat Genet. 2011 May;43(5):491-8. <http://www.ncbi.nlm.nih.gov/pubmed/21478889>`_
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/gatk/variant_filtration.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/gatk/variant_filtration.xml Wed Sep 21 04:11:07 2011 -0400
@@ -334,5 +334,7 @@
For the underlying tool, please cite `DePristo MA, Banks E, Poplin R, Garimella KV, Maguire JR, Hartl C, Philippakis AA, del Angel G, Rivas MA, Hanna M, McKenna A, Fennell TJ, Kernytsky AM, Sivachenko AY, Cibulskis K, Gabriel SB, Altshuler D, Daly MJ. A framework for variation discovery and genotyping using next-generation DNA sequencing data. Nat Genet. 2011 May;43(5):491-8. <http://www.ncbi.nlm.nih.gov/pubmed/21478889>`_
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/gatk/variant_recalibrator.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/gatk/variant_recalibrator.xml Wed Sep 21 04:11:07 2011 -0400
@@ -556,5 +556,7 @@
For the underlying tool, please cite `DePristo MA, Banks E, Poplin R, Garimella KV, Maguire JR, Hartl C, Philippakis AA, del Angel G, Rivas MA, Hanna M, McKenna A, Fennell TJ, Kernytsky AM, Sivachenko AY, Cibulskis K, Gabriel SB, Altshuler D, Daly MJ. A framework for variation discovery and genotyping using next-generation DNA sequencing data. Nat Genet. 2011 May;43(5):491-8. <http://www.ncbi.nlm.nih.gov/pubmed/21478889>`_
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/gatk/variants_validate.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/gatk/variants_validate.xml Wed Sep 21 04:11:07 2011 -0400
@@ -278,5 +278,7 @@
For the underlying tool, please cite `DePristo MA, Banks E, Poplin R, Garimella KV, Maguire JR, Hartl C, Philippakis AA, del Angel G, Rivas MA, Hanna M, McKenna A, Fennell TJ, Kernytsky AM, Sivachenko AY, Cibulskis K, Gabriel SB, Altshuler D, Daly MJ. A framework for variation discovery and genotyping using next-generation DNA sequencing data. Nat Genet. 2011 May;43(5):491-8. <http://www.ncbi.nlm.nih.gov/pubmed/21478889>`_
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/genetrack/genetrack_indexer.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/genetrack/genetrack_indexer.xml Wed Sep 21 04:11:07 2011 -0400
@@ -49,6 +49,12 @@
When shifting the averaging process in GeneTrack is able correct for longer or shorter
than expected fragment sizes as long as the errors are reasonably random.
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/genetrack/genetrack_peak_prediction.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/genetrack/genetrack_peak_prediction.xml Wed Sep 21 04:11:07 2011 -0400
@@ -54,6 +54,12 @@
- **Prediction method** the function used to average nearby values
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/maf/vcf_to_maf_customtrack.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/maf/vcf_to_maf_customtrack.xml Wed Sep 21 04:11:07 2011 -0400
@@ -121,6 +121,11 @@
s CHB+JPT_1.5 0 1 + 1 *------
s CHB+JPT_2.5 0 7 + 7 *GGA***
+------
+
+**Citation**
+
+If you use this tool, please cite `Blankenberg D, Taylor J, Nekrutenko A; The Galaxy Team. Making whole genome multiple alignments usable for biologists. Bioinformatics. 2011 Sep 1;27(17):2426-2428. <http://www.ncbi.nlm.nih.gov/pubmed/21775304>`_
</help></tool>
--- a/tools/meme/fimo.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/meme/fimo.xml Wed Sep 21 04:11:07 2011 -0400
@@ -223,6 +223,13 @@
For detailed information on FIMO, click here_. To view the license_.
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
+
.. _here: http://meme.nbcr.net/meme/fimo-intro.html
.. _license: http://meme.nbcr.net/meme/COPYRIGHT.html
--- a/tools/meme/meme.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/meme/meme.xml Wed Sep 21 04:11:07 2011 -0400
@@ -340,6 +340,12 @@
For detailed information on MEME, click here_. To view the license_.
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
.. _here: http://meme.nbcr.net/meme/meme-intro.html
.. _license: http://meme.nbcr.net/meme/COPYRIGHT.html
--- a/tools/peak_calling/ccat_2_wrapper.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/peak_calling/ccat_2_wrapper.xml Wed Sep 21 04:11:07 2011 -0400
@@ -119,5 +119,12 @@
This tool allows ChIP-seq peak/region calling using CCAT.
View the original CCAT documentation: http://cmb.gis.a-star.edu.sg/ChIPSeq/paperCCAT.htm.
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/peak_calling/ccat_wrapper.py Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/peak_calling/ccat_wrapper.py Wed Sep 21 04:11:07 2011 -0400
@@ -25,6 +25,7 @@
tmp_dir = tempfile.mkdtemp()
try:
+ assert os.path.exists( chrom_info_file ), "The required chromosome length file does not exist."
proc = subprocess.Popen( args="%s %s > %s" % ( CCAT_BINARY, " ".join( map( lambda x: "'%s'" % x, [ input_tag_file, input_control_file, chrom_info_file, input_config_file, project_name ] ) ), output_log_file ), shell=True, cwd=tmp_dir )
proc.wait()
if proc.returncode:
--- a/tools/peak_calling/ccat_wrapper.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/peak_calling/ccat_wrapper.xml Wed Sep 21 04:11:07 2011 -0400
@@ -135,5 +135,12 @@
This tool allows ChIP-seq peak/region calling using CCAT.
View the original CCAT documentation: http://cmb.gis.a-star.edu.sg/ChIPSeq/paperCCAT.htm.
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/peak_calling/macs_wrapper.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/peak_calling/macs_wrapper.xml Wed Sep 21 04:11:07 2011 -0400
@@ -226,5 +226,12 @@
Depending upon selected options, 2 to 6 history items will be created; the first output will be a standard BED file and the last will be an HTML report containing links to download additional files generated by MACS. Up to two each of wig and interval files can be optionally created; the interval files are parsed from the xls output.
View the original MACS documentation: http://liulab.dfci.harvard.edu/MACS/00README.html.
+
+------
+
+**Citation**
+
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
--- a/tools/peak_calling/sicer_wrapper.xml Tue Sep 20 11:31:23 2011 -0400
+++ b/tools/peak_calling/sicer_wrapper.xml Wed Sep 21 04:11:07 2011 -0400
@@ -172,5 +172,7 @@
For the underlying tool, please cite `Zang C, Schones DE, Zeng C, Cui K, Zhao K, Peng W. A clustering approach for identification of enriched domains from histone modification ChIP-Seq data. Bioinformatics. 2009 Aug 1;25(15):1952-8. <http://www.ncbi.nlm.nih.gov/pubmed/19505939>`_
+If you use this tool in Galaxy, please cite Blankenberg D, et al. *In preparation.*
+
</help></tool>
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: Clearer message when converting fasta for custom builds.
by Bitbucket 20 Sep '11
by Bitbucket 20 Sep '11
20 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/ed73683806af/
changeset: ed73683806af
user: jgoecks
date: 2011-09-20 17:31:23
summary: Clearer message when converting fasta for custom builds.
affected #: 1 file (-1 bytes)
--- a/templates/user/dbkeys.mako Tue Sep 20 11:20:13 2011 -0400
+++ b/templates/user/dbkeys.mako Tue Sep 20 11:31:23 2011 -0400
@@ -104,7 +104,7 @@
% if 'count' in dct:
${dct['count']}
% else:
- working
+ ?
% endif
</td><td><form action="dbkeys" method="post"><input type="hidden" name="key" value="${key}" /><input type="submit" name="delete" value="Delete" /></form></td>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new changesets in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/3342e9df3cd2/
changeset: 3342e9df3cd2
user: jgoecks
date: 2011-09-20 17:19:44
summary: Use fasta HDAs to specify custom builds. Do automatic conversions from fasta to 2bit and len; also, do conversion from len to linecount so that chrom/contig count is available. Finally, refactor 'compute fasta length' code out of tools and into converters.
affected #: 10 files (-1 bytes)
--- a/datatypes_conf.xml.sample Tue Sep 20 10:45:23 2011 -0400
+++ b/datatypes_conf.xml.sample Tue Sep 20 11:19:44 2011 -0400
@@ -135,6 +135,7 @@
<datatype extension="tabular" type="galaxy.datatypes.tabular:Tabular" display_in_upload="true"/><datatype extension="twobit" type="galaxy.datatypes.binary:TwoBit" mimetype="application/octet-stream" display_in_upload="true"/><datatype extension="txt" type="galaxy.datatypes.data:Text" display_in_upload="true"/>
+ <datatype extension="linecount" type="galaxy.datatypes.data:LineCount" display_in_upload="false"/><datatype extension="memexml" type="galaxy.datatypes.xml:MEMEXml" mimetype="application/xml" display_in_upload="true"/><datatype extension="cisml" type="galaxy.datatypes.xml:CisML" mimetype="application/xml" display_in_upload="true"/><datatype extension="blastxml" type="galaxy.datatypes.xml:BlastXml" mimetype="application/xml" display_in_upload="true"/>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/datatypes/converters/fasta_to_2bit.xml Tue Sep 20 11:19:44 2011 -0400
@@ -0,0 +1,13 @@
+<tool id="CONVERTER_fasta_to_2bit" name="Convert FASTA to 2bit" version="1.0.0">
+ <!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
+ <!-- Used on the metadata edit page. -->
+ <command>faToTwoBit $input $output</command>
+ <inputs>
+ <param name="input" type="data" format="fasta" label="Fasta file"/>
+ </inputs>
+ <outputs>
+ <data name="output" format="twobit"/>
+ </outputs>
+ <help>
+ </help>
+</tool>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/datatypes/converters/fasta_to_len.py Tue Sep 20 11:19:44 2011 -0400
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+"""
+Input: fasta, int
+Output: tabular
+Return titles with lengths of corresponding seq
+"""
+
+import sys, os
+
+assert sys.version_info[:2] >= ( 2, 4 )
+
+def compute_fasta_length( fasta_file, out_file, keep_first_char ):
+
+ infile = fasta_file
+ out = open( out_file, 'w')
+ keep_first_char = int( keep_first_char )
+
+ fasta_title = ''
+ seq_len = 0
+
+ # number of char to keep in the title
+ if keep_first_char == 0:
+ keep_first_char = None
+ else:
+ keep_first_char += 1
+
+ first_entry = True
+
+ for line in open( infile ):
+ line = line.strip()
+ if not line or line.startswith( '#' ):
+ continue
+ if line[0] == '>':
+ if first_entry == False:
+ out.write( "%s\t%d\n" % ( fasta_title[ 1:keep_first_char ], seq_len ) )
+ else:
+ first_entry = False
+ fasta_title = line
+ seq_len = 0
+ else:
+ seq_len += len(line)
+
+ # last fasta-entry
+ out.write( "%s\t%d\n" % ( fasta_title[ 1:keep_first_char ], seq_len ) )
+ out.close()
+
+if __name__ == "__main__" :
+ compute_fasta_length( sys.argv[1], sys.argv[2], sys.argv[3] )
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/datatypes/converters/fasta_to_len.xml Tue Sep 20 11:19:44 2011 -0400
@@ -0,0 +1,13 @@
+<tool id="CONVERTER_fasta_to_len" name="Convert FASTA to len file" version="1.0.0">
+ <!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
+ <!-- Used on the metadata edit page. -->
+ <command interpreter="python">fasta_to_len.py $input $output 0</command>
+ <inputs>
+ <param name="input" type="data" format="fasta" label="Fasta file"/>
+ </inputs>
+ <outputs>
+ <data name="output" format="len"/>
+ </outputs>
+ <help>
+ </help>
+</tool>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/datatypes/converters/len_to_linecount.xml Tue Sep 20 11:19:44 2011 -0400
@@ -0,0 +1,13 @@
+<tool id="CONVERTER_len_to_linecount" name="Convert Len file to Linecount" version="1.0.0">
+ <!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
+ <!-- Used on the metadata edit page. -->
+ <command>wc -l $input | awk '{print $1}' > $output </command>
+ <inputs>
+ <param name="input" type="data" format="len" label="Fasta file"/>
+ </inputs>
+ <outputs>
+ <data name="output" format="linecount"/>
+ </outputs>
+ <help>
+ </help>
+</tool>
--- a/lib/galaxy/datatypes/data.py Tue Sep 20 10:45:23 2011 -0400
+++ b/lib/galaxy/datatypes/data.py Tue Sep 20 11:19:44 2011 -0400
@@ -446,6 +446,13 @@
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+class LineCount( Text ):
+ """
+ Dataset contains a single line with a single integer that denotes the
+ line count for a related dataset. Used for custom builds.
+ """
+ pass
+
class Newick( Text ):
pass
--- a/lib/galaxy/web/controllers/user.py Tue Sep 20 10:45:23 2011 -0400
+++ b/lib/galaxy/web/controllers/user.py Tue Sep 20 11:19:44 2011 -0400
@@ -1165,6 +1165,9 @@
@web.expose
@web.require_login()
def dbkeys( self, trans, **kwds ):
+ #
+ # Process arguments and add/delete build.
+ #
user = trans.user
message = None
lines_skipped = 0
@@ -1178,57 +1181,79 @@
else:
dbkeys = from_json_string(user.preferences['dbkeys'])
if 'delete' in kwds:
+ # Delete a build.
key = kwds.get('key', '')
if key and key in dbkeys:
del dbkeys[key]
elif 'add' in kwds:
- name = kwds.get('name', '')
- key = kwds.get('key', '')
- len_file = kwds.get('len_file', None)
- if getattr(len_file, "file", None): # Check if it's a FieldStorage object
- len_text = len_file.file.read()
- else:
- len_text = kwds.get('len_text', '')
- if not name or not key or not len_text:
+ # Add new custom build.
+ name = kwds.get('name', '')
+ key = kwds.get('key', '')
+ dataset_id = kwds.get('dataset_id', '')
+ if not name or not key or not dataset_id:
message = "You must specify values for all the fields."
elif key in dbkeys:
message = "There is already a custom build with that key. Delete it first if you want to replace it."
else:
- # Create new len file
- new_len = trans.app.model.HistoryDatasetAssociation( extension="len", create_dataset=True, sa_session=trans.sa_session )
- trans.sa_session.add( new_len )
- new_len.name = name
- new_len.visible = False
- new_len.state = trans.app.model.Job.states.OK
- new_len.info = "custom build .len file"
- trans.sa_session.flush()
- counter = 0
- f = open(new_len.file_name, "w")
- # LEN files have format:
- # <chrom_name><tab><chrom_length>
- for line in len_text.split("\n"):
- lst = line.strip().rsplit(None, 1) # Splits at the last whitespace in the line
- if not lst or len(lst) < 2:
- lines_skipped += 1
- continue
- chrom, length = lst[0], lst[1]
- try:
- length = int(length)
- except ValueError:
- lines_skipped += 1
- continue
- counter += 1
- f.write("%s\t%s\n" % (chrom, length))
- f.close()
- dbkeys[key] = { "name": name, "len": new_len.id, "count": counter }
+ dataset_id = trans.security.decode_id( dataset_id )
+ dbkeys[key] = { "name": name, "fasta": dataset_id }
+ # Save builds.
+ # TODO: use database table to save builds.
user.preferences['dbkeys'] = to_json_string(dbkeys)
trans.sa_session.flush()
+
+ #
+ # Display custom builds page.
+ #
+
+ # Add chrom/contig count to dbkeys dict.
+ updated = False
+ for key, attributes in dbkeys.items():
+ if 'count' in attributes:
+ # Already have count, so do nothing.
+ continue
+
+ # Get len file.
+ fasta_dataset = trans.app.model.HistoryDatasetAssociation.get( attributes[ 'fasta' ] )
+ len_dataset = fasta_dataset.get_converted_dataset( trans, "len" )
+ # HACK: need to request dataset again b/c get_converted_dataset()
+ # doesn't return dataset (as it probably should).
+ len_dataset = fasta_dataset.get_converted_dataset( trans, "len" )
+ if len_dataset.state == trans.app.model.Job.states.ERROR:
+ # Can't use len dataset.
+ continue
+
+ # Get chrom count file.
+ # NOTE: this conversion doesn't work well with set_metadata_externally=False
+ # because the conversion occurs before metadata can be set; the
+ # dataset is marked as deleted and a subsequent conversion is run.
+ chrom_count_dataset = len_dataset.get_converted_dataset( trans, "linecount" )
+ if not chrom_count_dataset or chrom_count_dataset.state != trans.app.model.Job.states.OK:
+ # No valid linecount dataset.
+ continue
+ else:
+ # Set chrom count.
+ chrom_count = int( open( chrom_count_dataset.file_name ).readline() )
+ attributes[ 'count' ] = chrom_count
+ updated = True
+
+ if updated:
+ user.preferences['dbkeys'] = to_json_string(dbkeys)
+ trans.sa_session.flush()
+
+
+ # Potential genome data for custom builds is limited to fasta datasets in current history for now.
+ fasta_hdas = trans.sa_session.query( model.HistoryDatasetAssociation ) \
+ .filter_by( history=trans.history, extension="fasta", deleted=False ) \
+ .order_by( model.HistoryDatasetAssociation.hid.desc() )
+
return trans.fill_template( 'user/dbkeys.mako',
user=user,
dbkeys=dbkeys,
message=message,
installed_len_files=self.installed_len_files,
lines_skipped=lines_skipped,
+ fasta_hdas=fasta_hdas,
use_panels=kwds.get( 'use_panels', None ) )
@web.expose
@web.require_login()
--- a/templates/user/dbkeys.mako Tue Sep 20 10:45:23 2011 -0400
+++ b/templates/user/dbkeys.mako Tue Sep 20 11:19:44 2011 -0400
@@ -103,6 +103,8 @@
## </pre>
% if 'count' in dct:
${dct['count']}
+ % else:
+ working
% endif
</td><td><form action="dbkeys" method="post"><input type="hidden" name="key" value="${key}" /><input type="submit" name="delete" value="Delete" /></form></td>
@@ -133,10 +135,12 @@
<input type="text" id="key" name="key" /></div><div class="form-row">
- <label for="len_file">Upload .len file:</label>
- <input type="file" id="len_file" name="len_file" /><br />
- <label for="len_text">Or enter/paste length info below:</label>
- <textarea id="len_text" name="len_text" cols="30" rows="8"></textarea>
+ <label for="len_file">Build Genome:</label>
+ <select name="dataset_id">
+ %for dataset in fasta_hdas:
+ <option value="${trans.security.encode_id( dataset.id )}">${dataset.hid}: ${dataset.name}</option>
+ %endfor
+ </select></div><div class="form-row"><input type="submit" name="add" value="Submit"/></div>
--- a/tools/fasta_tools/fasta_compute_length.py Tue Sep 20 10:45:23 2011 -0400
+++ b/tools/fasta_tools/fasta_compute_length.py Tue Sep 20 11:19:44 2011 -0400
@@ -1,47 +1,9 @@
#!/usr/bin/env python
"""
-Input: fasta, int
-Output: tabular
-Return titles with lengths of corresponding seq
+Uses fasta_to_len converter code.
"""
-import sys, os
+import sys
+from galaxy.datatypes.converters.fasta_to_len import compute_fasta_length
-assert sys.version_info[:2] >= ( 2, 4 )
-
-def __main__():
-
- infile = sys.argv[1]
- out = open( sys.argv[2], 'w')
- keep_first_char = int( sys.argv[3] )
-
- fasta_title = ''
- seq_len = 0
-
- # number of char to keep in the title
- if keep_first_char == 0:
- keep_first_char = None
- else:
- keep_first_char += 1
-
- first_entry = True
-
- for line in open( infile ):
- line = line.strip()
- if not line or line.startswith( '#' ):
- continue
- if line[0] == '>':
- if first_entry == False:
- out.write( "%s\t%d\n" % ( fasta_title[ 1:keep_first_char ], seq_len ) )
- else:
- first_entry = False
- fasta_title = line
- seq_len = 0
- else:
- seq_len += len(line)
-
- # last fasta-entry
- out.write( "%s\t%d\n" % ( fasta_title[ 1:keep_first_char ], seq_len ) )
- out.close()
-
-if __name__ == "__main__" : __main__()
\ No newline at end of file
+compute_fasta_length( sys.argv[1], sys.argv[2], sys.argv[3])
\ No newline at end of file
http://bitbucket.org/galaxy/galaxy-central/changeset/e21eb7138be8/
changeset: e21eb7138be8
user: jgoecks
date: 2011-09-20 17:20:13
summary: Merge
affected #: 2 files (-1 bytes)
--- a/lib/galaxy/web/base/controller.py Tue Sep 20 11:19:44 2011 -0400
+++ b/lib/galaxy/web/base/controller.py Tue Sep 20 11:20:13 2011 -0400
@@ -2751,9 +2751,7 @@
def browse_tool_shed( self, trans, **kwd ):
tool_shed_url = kwd[ 'tool_shed_url' ]
galaxy_url = trans.request.host
- # Set the galayurl cookie so we can get back here from the remote tool shed.
- trans.set_cookie( galaxy_url, name='toolshedgalaxyurl' )
- url = '%s/repository/browse_downloadable_repositories?webapp=community' % ( tool_shed_url )
+ url = '%s/repository/browse_downloadable_repositories?galaxy_url=%s&webapp=community' % ( tool_shed_url, galaxy_url )
return trans.response.send_redirect( url )
@web.expose
@web.require_admin
--- a/lib/galaxy/webapps/community/controllers/repository.py Tue Sep 20 11:19:44 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/repository.py Tue Sep 20 11:20:13 2011 -0400
@@ -262,6 +262,11 @@
return self.category_list_grid( trans, **kwd )
@web.expose
def browse_downloadable_repositories( self, trans, **kwd ):
+ # Set the toolshedgalaxyurl cookie so we can get back
+ # to the calling local Galaxy instance.
+ galaxy_url = kwd.get( 'galaxy_url', None )
+ if galaxy_url:
+ trans.set_cookie( galaxy_url, name='toolshedgalaxyurl' )
repository_id = kwd.get( 'id', None )
if 'operation' in kwd:
operation = kwd[ 'operation' ].lower()
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/29e9f87731ec/
changeset: 29e9f87731ec
user: greg
date: 2011-09-20 17:17:27
summary: Tweak tool shed cookie handling.
affected #: 2 files (-1 bytes)
--- a/lib/galaxy/web/base/controller.py Tue Sep 20 10:45:23 2011 -0400
+++ b/lib/galaxy/web/base/controller.py Tue Sep 20 11:17:27 2011 -0400
@@ -2751,9 +2751,7 @@
def browse_tool_shed( self, trans, **kwd ):
tool_shed_url = kwd[ 'tool_shed_url' ]
galaxy_url = trans.request.host
- # Set the galayurl cookie so we can get back here from the remote tool shed.
- trans.set_cookie( galaxy_url, name='toolshedgalaxyurl' )
- url = '%s/repository/browse_downloadable_repositories?webapp=community' % ( tool_shed_url )
+ url = '%s/repository/browse_downloadable_repositories?galaxy_url=%s&webapp=community' % ( tool_shed_url, galaxy_url )
return trans.response.send_redirect( url )
@web.expose
@web.require_admin
--- a/lib/galaxy/webapps/community/controllers/repository.py Tue Sep 20 10:45:23 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/repository.py Tue Sep 20 11:17:27 2011 -0400
@@ -262,6 +262,11 @@
return self.category_list_grid( trans, **kwd )
@web.expose
def browse_downloadable_repositories( self, trans, **kwd ):
+ # Set the toolshedgalaxyurl cookie so we can get back
+ # to the calling local Galaxy instance.
+ galaxy_url = kwd.get( 'galaxy_url', None )
+ if galaxy_url:
+ trans.set_cookie( galaxy_url, name='toolshedgalaxyurl' )
repository_id = kwd.get( 'id', None )
if 'operation' in kwd:
operation = kwd[ 'operation' ].lower()
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

20 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/af1aaff959c4/
changeset: af1aaff959c4
user: greg
date: 2011-09-20 16:45:23
summary: Fix for bug introduced in the last change set.
affected #: 1 file (-1 bytes)
--- a/lib/galaxy/webapps/community/controllers/repository.py Tue Sep 20 10:38:30 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/repository.py Tue Sep 20 10:45:23 2011 -0400
@@ -1254,7 +1254,6 @@
action='preview_tools_in_changeset',
repository_id=repository_id,
changeset_revision=changeset_revision,
- galaxy_url=galaxy_url,
message=message,
status='error' ) )
return trans.response.send_redirect( web.url_for( controller='repository',
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/b13ab23c7d8e/
changeset: b13ab23c7d8e
user: greg
date: 2011-09-20 16:38:30
summary: Add baseline support for using Fabric scripts for automatically installing tool dependencies on a local Galaxy instance when repositories are installed from a Galaxy tool shed, and persist the url to the local Galaxy instance in a cookie named toolshedgalaxyurl when installing a tool shed repository to a local Galaxy instance.
affected #: 12 files (-1 bytes)
--- a/lib/galaxy/config.py Mon Sep 19 16:07:53 2011 -0400
+++ b/lib/galaxy/config.py Tue Sep 20 10:38:30 2011 -0400
@@ -119,9 +119,12 @@
self.ftp_upload_site = kwargs.get( 'ftp_upload_site', None )
self.allow_library_path_paste = kwargs.get( 'allow_library_path_paste', False )
self.disable_library_comptypes = kwargs.get( 'disable_library_comptypes', '' ).lower().split( ',' )
- # Location for dependencies
+ # Location for tool dependencies.
if 'tool_dependency_dir' in kwargs:
self.tool_dependency_dir = resolve_path( kwargs.get( "tool_dependency_dir" ), self.root )
+ # Setting the following flag to true will ultimately cause tool dependencies
+ # to be located in the shell environment and used by the job that is executing
+ # the tool.
self.use_tool_dependencies = True
else:
self.tool_dependency_dir = None
--- a/lib/galaxy/datatypes/assembly.py Mon Sep 19 16:07:53 2011 -0400
+++ b/lib/galaxy/datatypes/assembly.py Tue Sep 20 10:38:30 2011 -0400
@@ -143,7 +143,6 @@
def __init__( self, **kwd ):
Html.__init__( self, **kwd )
- log.debug( "Velvet log info %s" % 'JJ __init__')
self.add_composite_file( 'Sequences', mimetype = 'text/html', description = 'Sequences', substitute_name_with_metadata = None, is_binary = False )
self.add_composite_file( 'Roadmaps', mimetype = 'text/html', description = 'Roadmaps', substitute_name_with_metadata = None, is_binary = False )
self.add_composite_file( 'Log', mimetype = 'text/html', description = 'Log', optional = 'True', substitute_name_with_metadata = None, is_binary = False )
--- a/lib/galaxy/tools/__init__.py Mon Sep 19 16:07:53 2011 -0400
+++ b/lib/galaxy/tools/__init__.py Tue Sep 20 10:38:30 2011 -0400
@@ -227,12 +227,11 @@
id = self.app.security.decode_id( workflow_id )
stored = self.app.model.context.query( self.app.model.StoredWorkflow ).get( id )
return stored.latest_workflow
-
def init_dependency_manager( self ):
- self.dependency_manager = None
if self.app.config.use_tool_dependencies:
self.dependency_manager = DependencyManager( [ self.app.config.tool_dependency_dir ] )
-
+ else:
+ self.dependency_manager = None
@property
def sa_session( self ):
"""
@@ -341,12 +340,17 @@
"""
Represents an external requirement that must be available for the tool to
run (for example, a program, package, or library). Requirements can
- optionally assert a specific version
+ optionally assert a specific version, or reference a command to execute a
+ fabric script. If fabric is used, the type is 'fabfile' and the version
+ attribute is not used since the fabric script includes all necessary
+ information for automatic dependency installation.
"""
- def __init__( self ):
- self.name = None
- self.type = None
- self.version = None
+ def __init__( self, name=None, type=None, version=None, fabfile=None, method=None ):
+ self.name = name
+ self.type = type
+ self.version = version
+ self.fabfile = fabfile
+ self.method = method
class Tool:
"""
@@ -882,10 +886,21 @@
self.requirements
"""
for requirement_elem in requirements_elem.findall( 'requirement' ):
- requirement = ToolRequirement()
- requirement.name = util.xml_text( requirement_elem )
- requirement.type = requirement_elem.get( "type", "package" )
- requirement.version = requirement_elem.get( "version" )
+ name = util.xml_text( requirement_elem )
+ type = requirement_elem.get( "type", "package" )
+ if type == 'fabfile':
+ # The fabric script will include all necessary information for
+ # automatically installing the tool dependencies.
+ fabfile = requirement_elem.get( "fabfile" )
+ method = requirement_elem.get( "method" )
+ version = None
+ else:
+ # For backward compatibility, requirements tag sets should not require the
+ # use of a fabric script.
+ version = requirement_elem.get( "version" )
+ fabfile = None
+ method = None
+ requirement = ToolRequirement( name=name, type=type, version=version, fabfile=fabfile, method=method )
self.requirements.append( requirement )
def check_workflow_compatible( self ):
--- a/lib/galaxy/tools/deps/__init__.py Mon Sep 19 16:07:53 2011 -0400
+++ b/lib/galaxy/tools/deps/__init__.py Tue Sep 20 10:38:30 2011 -0400
@@ -18,11 +18,10 @@
and should each contain a file 'env.sh' which can be sourced to make the
dependency available in the current shell environment.
"""
-
def __init__( self, base_paths=[] ):
"""
- Create a new dependency manager looking for packages under the
- paths listed in `base_paths`.
+ Create a new dependency manager looking for packages under the paths listed
+ in `base_paths`. The default base path is app.config.tool_dependency_dir.
"""
self.base_paths = []
for base_path in base_paths:
@@ -31,19 +30,17 @@
if not os.path.isdir( base_path ):
log.warn( "Path '%s' is not directory, ignoring", base_path )
self.base_paths.append( os.path.abspath( base_path ) )
-
def find_dep( self, name, version=None ):
"""
Attempt to find a dependency named `name` at version `version`. If
version is None, return the "default" version as determined using a
symbolic link (if found). Returns a triple of:
- env_script, base_path, real_version
+ env_script, base_path, real_version
"""
if version is None:
return self._find_dep_default( name )
else:
return self._find_dep_versioned( name, version )
-
def _find_dep_versioned( self, name, version ):
for base_path in self.base_paths:
path = os.path.join( base_path, name, version )
@@ -52,7 +49,6 @@
return script, path, version
else:
return None, None, None
-
def _find_dep_default( self, name ):
version = None
for base_path in self.base_paths:
@@ -65,5 +61,3 @@
return script, real_path, real_version
else:
return None, None, None
-
-
--- a/lib/galaxy/web/base/controller.py Mon Sep 19 16:07:53 2011 -0400
+++ b/lib/galaxy/web/base/controller.py Tue Sep 20 10:38:30 2011 -0400
@@ -2749,10 +2749,11 @@
@web.expose
@web.require_admin
def browse_tool_shed( self, trans, **kwd ):
- tool_shed_name = kwd[ 'tool_shed_name' ]
tool_shed_url = kwd[ 'tool_shed_url' ]
galaxy_url = trans.request.host
- url = '%s/repository/browse_downloadable_repositories?tool_shed_name=%s&galaxy_url=%s&webapp=community' % ( tool_shed_url, tool_shed_name, galaxy_url )
+ # Set the galayurl cookie so we can get back here from the remote tool shed.
+ trans.set_cookie( galaxy_url, name='toolshedgalaxyurl' )
+ url = '%s/repository/browse_downloadable_repositories?webapp=community' % ( tool_shed_url )
return trans.response.send_redirect( url )
@web.expose
@web.require_admin
@@ -2784,8 +2785,8 @@
status = 'error'
else:
os.makedirs( clone_dir )
+ log.debug( 'Cloning %s...' % repository_clone_url )
cmd = 'hg clone %s' % repository_clone_url
- log.debug( 'Cloning: %s' % repository_clone_url )
tmp_name = tempfile.NamedTemporaryFile().name
tmp_stderr = open( tmp_name, 'wb' )
os.chdir( clone_dir )
@@ -2795,7 +2796,7 @@
tmp_stderr.close()
if returncode == 0:
repo_files_dir = os.path.join( clone_dir, repository_name )
- log.debug( 'Updating cloned repository to revision: %s' % changeset_revision )
+ log.debug( 'Updating cloned repository to revision "%s"...' % changeset_revision )
cmd = 'hg update -r %s' % changeset_revision
tmp_name = tempfile.NamedTemporaryFile().name
tmp_stderr = open( tmp_name, 'wb' )
@@ -2831,6 +2832,39 @@
# We have an inavlid .xml file, so not a tool config.
log.debug( "Ignoring invalid tool config (%s). Error: %s" % ( str( relative_path ), str( e ) ) )
if repository_tools_tups:
+ # Look at each tool to see if it includes a "requirement" that refers to
+ # a fabric script. For those that do, execute the fabric script to install
+ # tool dependencies.
+ for repository_tools_tup in repository_tools_tups:
+ tup_path, repository_tool = repository_tools_tup
+ for requirement in repository_tool.requirements:
+ if requirement.type == 'fabfile':
+ log.debug( 'Executing fabric script to install dependencies for tool "%s"...' % repository_tool.name )
+ fabfile = requirement.fabfile
+ method = requirement.method
+ # Find the relative path to the fabfile.
+ relative_fabfile_path = None
+ for root, dirs, files in os.walk( repo_files_dir ):
+ for name in files:
+ if name == fabfile:
+ relative_fabfile_path = os.path.join( root, name )
+ break
+ if relative_fabfile_path:
+ # cmd will look something like: fab -f fabfile.py install_bowtie
+ cmd = 'fab -f %s %s' % ( relative_fabfile_path, method )
+ tmp_name = tempfile.NamedTemporaryFile().name
+ tmp_stderr = open( tmp_name, 'wb' )
+ os.chdir( repo_files_dir )
+ proc = subprocess.Popen( cmd, shell=True, stderr=tmp_stderr.fileno() )
+ returncode = proc.wait()
+ os.chdir( current_working_dir )
+ tmp_stderr.close()
+ if returncode != 0:
+ # TODO: do something more here than logging the problem.
+ tmp_stderr = open( tmp_name, 'rb' )
+ error = tmp_stderr.read()
+ tmp_stderr.close()
+ log.debug( 'Problem installing dependencies for tool "%s"\n%s' % ( repository_tool.name, error ) )
# Generate an in-memory tool conf section that includes the new tools.
new_tool_section = self.__generate_tool_panel_section( repository_name,
repository_clone_url,
--- a/lib/galaxy/webapps/community/controllers/common.py Mon Sep 19 16:07:53 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/common.py Tue Sep 20 10:38:30 2011 -0400
@@ -171,9 +171,21 @@
repository = get_repository( trans, id )
tool_requirements = []
for tr in tool.requirements:
- requirement_dict = dict( name=tr.name,
- type=tr.type,
- version=tr.version )
+ name=tr.name
+ type=tr.type
+ if type == 'fabfile':
+ version = None
+ fabfile = tr.fabfile
+ method = tr.method
+ else:
+ version = tr.version
+ fabfile = None
+ method = None
+ requirement_dict = dict( name=name,
+ type=type,
+ version=version,
+ fabfile=fabfile,
+ method=method )
tool_requirements.append( requirement_dict )
tool_tests = []
if tool.tests:
@@ -335,13 +347,17 @@
trans.sa_session.flush()
else:
message = "Changeset revision '%s' includes no tools or exported workflows for which metadata can be set." % str( changeset_revision )
- status = "done"
+ status = "error"
else:
# change_set is None
message = "Repository does not include changeset revision '%s'." % str( changeset_revision )
status = 'error'
if invalid_files:
- message = "Metadata cannot be defined for change set revision '%s'. Correct the following problems and reset metadata.<br/>" % str( changeset_revision )
+ if metadata_dict:
+ message = "Metadata was defined for some items in change set revision '%s'. " % str( changeset_revision )
+ message += "If the following files are Galaxy tool configs or exported Galaxy workflows, correct the problems and reset metadata.<br/>"
+ else:
+ message = "Metadata cannot be defined for change set revision '%s'. Correct the following problems and reset metadata.<br/>" % str( changeset_revision )
for itc_tup in invalid_files:
tool_file = itc_tup[0]
exception_msg = itc_tup[1]
@@ -527,7 +543,7 @@
ToolClass = Tool
return ToolClass( config_file, root, trans.app )
return None
-def build_changeset_revision_select_field( trans, repository, selected_value=None, add_id_to_name=True, galaxy_url=None ):
+def build_changeset_revision_select_field( trans, repository, selected_value=None, add_id_to_name=True ):
"""
Build a SelectField whose options are the changeset_revision
strings of all downloadable_revisions of the received repository.
@@ -541,15 +557,9 @@
options.append( ( revision_label, changeset_revision ) )
refresh_on_change_values.append( changeset_revision )
if add_id_to_name:
- if galaxy_url:
- name = '%s_changeset_revision_%d' % ( galaxy_url, repository.id )
- else:
- name = 'changeset_revision_%d' % repository.id
+ name = 'changeset_revision_%d' % repository.id
else:
- if galaxy_url:
- name = '%s_changeset_revision' % galaxy_url
- else:
- name = 'changeset_revision'
+ name = 'changeset_revision'
select_field = SelectField( name=name,
refresh_on_change=True,
refresh_on_change_values=refresh_on_change_values )
--- a/lib/galaxy/webapps/community/controllers/repository.py Mon Sep 19 16:07:53 2011 -0400
+++ b/lib/galaxy/webapps/community/controllers/repository.py Tue Sep 20 10:38:30 2011 -0400
@@ -122,7 +122,6 @@
return 'yes'
return ''
# Grid definition
- galaxy_url = None
title = "Repositories"
model_class = model.Repository
template='/webapps/community/repository/grid.mako'
@@ -192,12 +191,11 @@
Display a SelectField whose options are the changeset_revision
strings of all downloadable_revisions of this repository.
"""
- select_field = build_changeset_revision_select_field( trans,
- repository,
- galaxy_url=grid.galaxy_url )
+ select_field = build_changeset_revision_select_field( trans, repository )
if len( select_field.options ) > 1:
return select_field.get_html()
return repository.revision
+ title = "Downloadable repositories"
columns = [
RepositoryListGrid.NameColumn( "Name",
key="name",
@@ -264,9 +262,7 @@
return self.category_list_grid( trans, **kwd )
@web.expose
def browse_downloadable_repositories( self, trans, **kwd ):
- tool_shed_name = kwd.get( 'tool_shed_name', None )
repository_id = kwd.get( 'id', None )
- galaxy_url = kwd.get( 'galaxy_url', None )
if 'operation' in kwd:
operation = kwd[ 'operation' ].lower()
if operation == "preview_tools_in_changeset":
@@ -274,8 +270,7 @@
return trans.response.send_redirect( web.url_for( controller='repository',
action='preview_tools_in_changeset',
repository_id=repository_id,
- changeset_revision=repository.tip,
- galaxy_url=galaxy_url ) )
+ changeset_revision=repository.tip ) )
# The changeset_revision_select_field in the RepositoryListGrid performs a refresh_on_change
# which sends in request parameters like changeset_revison_1, changeset_revision_2, etc. One
@@ -292,31 +287,10 @@
return trans.response.send_redirect( web.url_for( controller='repository',
action='preview_tools_in_changeset',
repository_id=trans.security.encode_id( repository.id ),
- changeset_revision=v,
- galaxy_url=galaxy_url ) )
- elif k.find( changset_revision_str ) > 0:
- # Keys look like: 'localhost:8763_changeset_revision_3' and values: '4ef2cf631604'.
- items = k.split( '_%s' % changset_revision_str )
- galaxy_url = items[0]
- repository_id = trans.security.encode_id( int( items[1] ) )
- repository = get_repository( trans, repository_id )
- if repository.tip != v:
- return trans.response.send_redirect( web.url_for( controller='repository',
- action='preview_tools_in_changeset',
- repository_id=trans.security.encode_id( repository.id ),
- changeset_revision=v,
- galaxy_url=galaxy_url ) )
-
- if tool_shed_name:
- title = "%s downloadable repositories" % tool_shed_name
- else:
- title = "Downloadable repositories"
- self.downloadable_repository_list_grid.title = title
- self.downloadable_repository_list_grid.galaxy_url = galaxy_url
+ changeset_revision=v ) )
url_args = dict( action='browse_downloadable_repositories',
operation='preview_tools_in_changeset',
- repository_id=repository_id,
- galaxy_url=galaxy_url )
+ repository_id=repository_id )
self.downloadable_repository_list_grid.operations = [ grids.GridOperation( "Preview and install tools",
url_args=url_args,
allow_multiple=False,
@@ -329,7 +303,6 @@
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
- galaxy_url = util.restore_text( params.get( 'galaxy_url', '' ) )
repository = get_repository( trans, repository_id )
changeset_revision = util.restore_text( params.get( 'changeset_revision', repository.tip ) )
repository_metadata = get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
@@ -348,7 +321,6 @@
revision_label=revision_label,
changeset_revision_select_field=changeset_revision_select_field,
metadata=metadata,
- galaxy_url=galaxy_url,
display_for_install=True,
message=message,
status=status )
@@ -357,7 +329,7 @@
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
- galaxy_url = util.restore_text( params.get( 'galaxy_url', '' ) )
+ galaxy_url = trans.get_cookie( name='toolshedgalaxyurl' )
repository = get_repository( trans, repository_id )
changeset_revision = util.restore_text( params.get( 'changeset_revision', repository.tip ) )
# Redirect back to local Galaxy to perform install.
@@ -1232,7 +1204,6 @@
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
- galaxy_url = util.restore_text( params.get( 'galaxy_url', '' ) )
display_for_install = util.string_as_bool( params.get( 'display_for_install', False ) )
repository = get_repository( trans, repository_id )
repo = hg.repository( get_configured_ui(), repository.repo_path )
@@ -1274,7 +1245,6 @@
tool_state=tool_state,
is_malicious=is_malicious,
display_for_install=display_for_install,
- galaxy_url=galaxy_url,
message=message,
status=status )
except Exception, e:
--- a/templates/admin/select_tool_panel_section.mako Mon Sep 19 16:07:53 2011 -0400
+++ b/templates/admin/select_tool_panel_section.mako Tue Sep 20 10:38:30 2011 -0400
@@ -16,7 +16,7 @@
or concerns.
</div><br/>
-<div class="errormessage">
+<div class="warningmessage">
Installation may take a while, depending upon the size of the repository contents. Wait until a message is displayed in your
browser after clicking the <b>Install</b> button below.
</div>
--- a/templates/webapps/community/repository/common.mako Mon Sep 19 16:07:53 2011 -0400
+++ b/templates/webapps/community/repository/common.mako Tue Sep 20 10:38:30 2011 -0400
@@ -83,7 +83,7 @@
hg clone <a href="${clone_str}">${clone_str}</a></%def>
-<%def name="render_repository_tools_and_workflows( metadata, can_set_metadata=False, display_for_install=False, galaxy_url=None )">
+<%def name="render_repository_tools_and_workflows( metadata, can_set_metadata=False, display_for_install=False )">
%if metadata or can_set_metadata:
<p/><div class="toolForm">
@@ -111,12 +111,12 @@
<tr><td><div style="float: left; margin-left: 1px;" class="menubutton split popup" id="tool-${tool_dict[ 'id' ].replace( ' ', '_' )}-popup">
- <a class="view-info" href="${h.url_for( controller='repository', action='display_tool', repository_id=trans.security.encode_id( repository.id ), tool_config=tool_dict[ 'tool_config' ], changeset_revision=changeset_revision, display_for_install=display_for_install, galaxy_url=galaxy_url )}">
+ <a class="view-info" href="${h.url_for( controller='repository', action='display_tool', repository_id=trans.security.encode_id( repository.id ), tool_config=tool_dict[ 'tool_config' ], changeset_revision=changeset_revision, display_for_install=display_for_install )}">
${tool_dict[ 'name' ]}
</a></div><div popupmenu="tool-${tool_dict[ 'id' ].replace( ' ', '_' )}-popup">
- <a class="action-button" href="${h.url_for( controller='repository', action='view_tool_metadata', repository_id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision, tool_id=tool_dict[ 'id' ], display_for_install=display_for_install, galaxy_url=galaxy_url )}">View tool metadata</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_tool_metadata', repository_id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision, tool_id=tool_dict[ 'id' ], display_for_install=display_for_install )}">View tool metadata</a></div></td><td>${tool_dict[ 'description' ]}</td>
--- a/templates/webapps/community/repository/preview_tools_in_changeset.mako Mon Sep 19 16:07:53 2011 -0400
+++ b/templates/webapps/community/repository/preview_tools_in_changeset.mako Tue Sep 20 10:38:30 2011 -0400
@@ -64,7 +64,7 @@
<br/><br/><ul class="manage-table-actions">
- <a class="action-button" href="${h.url_for( controller='repository', action='install_repository_revision', repository_id=trans.security.encode_id( repository.id ), webapp='community', changeset_revision=changeset_revision, galaxy_url=galaxy_url )}">Install to local Galaxy</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='install_repository_revision', repository_id=trans.security.encode_id( repository.id ), webapp='community', changeset_revision=changeset_revision )}">Install to local Galaxy</a></ul>
%if message:
@@ -75,7 +75,7 @@
<div class="toolFormTitle">Repository ${repository.name}</div><div class="toolFormBody">
%if len( changeset_revision_select_field.options ) > 1:
- <form name="change_revision" id="change_revision" action="${h.url_for( controller='repository', action='preview_tools_in_changeset', repository_id=trans.security.encode_id( repository.id ), galaxy_url=galaxy_url )}" method="post" >
+ <form name="change_revision" id="change_revision" action="${h.url_for( controller='repository', action='preview_tools_in_changeset', repository_id=trans.security.encode_id( repository.id ) )}" method="post" ><div class="form-row"><%
if changeset_revision == repository.tip:
@@ -98,4 +98,4 @@
</div></div><p/>
-${render_repository_tools_and_workflows( metadata, display_for_install=display_for_install, galaxy_url=galaxy_url )}
+${render_repository_tools_and_workflows( metadata, display_for_install=display_for_install )}
--- a/templates/webapps/community/repository/tool_form.mako Mon Sep 19 16:07:53 2011 -0400
+++ b/templates/webapps/community/repository/tool_form.mako Tue Sep 20 10:38:30 2011 -0400
@@ -111,7 +111,7 @@
<br/><br/><ul class="manage-table-actions">
%if display_for_install:
- <a class="action-button" href="${h.url_for( controller='repository', action='install_repository_revision', repository_id=trans.security.encode_id( repository.id ), webapp='community', changeset_revision=changeset_revision, galaxy_url=galaxy_url )}">Install to local Galaxy</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='install_repository_revision', repository_id=trans.security.encode_id( repository.id ), webapp='community', changeset_revision=changeset_revision )}">Install to local Galaxy</a>
%else:
%if is_new:
<a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
--- a/templates/webapps/galaxy/admin/index.mako Mon Sep 19 16:07:53 2011 -0400
+++ b/templates/webapps/galaxy/admin/index.mako Tue Sep 20 10:38:30 2011 -0400
@@ -70,7 +70,7 @@
<div class="toolSectionBody"><div class="toolSectionBg">
%for name, url in trans.app.tool_shed_registry.tool_sheds.items():
- <div class="toolTitle"><a href="${h.url_for( controller='admin', action='browse_tool_shed', tool_shed_name=name, tool_shed_url=url )}" target="galaxy_main">${name}</a></div>
+ <div class="toolTitle"><a href="${h.url_for( controller='admin', action='browse_tool_shed', tool_shed_url=url )}" target="galaxy_main">${name}</a></div>
%endfor
</div></div>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: jgoecks: Trackster: (a) remove child tracks, which are replaced with track groups and (b) preserve and restore track ordering, which was broken in 732ad7ebde0c.
by Bitbucket 19 Sep '11
by Bitbucket 19 Sep '11
19 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/a76e32124ad8/
changeset: a76e32124ad8
user: jgoecks
date: 2011-09-19 22:07:53
summary: Trackster: (a) remove child tracks, which are replaced with track groups and (b) preserve and restore track ordering, which was broken in 732ad7ebde0c.
affected #: 5 files (-1 bytes)
--- a/lib/galaxy/web/base/controller.py Mon Sep 19 11:59:09 2011 -0400
+++ b/lib/galaxy/web/base/controller.py Mon Sep 19 16:07:53 2011 -0400
@@ -195,8 +195,7 @@
"dataset_id": trans.security.encode_id( dataset.id ),
"prefs": prefs,
"filters": track_data_provider.get_filters(),
- "tool": get_tool_def( trans, dataset ),
- "is_child": t.get('is_child', False)
+ "tool": get_tool_def( trans, dataset )
} )
config = { "title": visualization.title, "vis_id": trans.security.encode_id( visualization.id ),
--- a/lib/galaxy/web/controllers/tracks.py Mon Sep 19 11:59:09 2011 -0400
+++ b/lib/galaxy/web/controllers/tracks.py Mon Sep 19 16:07:53 2011 -0400
@@ -573,8 +573,7 @@
"hda_ldda": track.get('hda_ldda', "hda"),
"name": track['name'],
"track_type": track['track_type'],
- "prefs": track['prefs'],
- "is_child": track.get('is_child', False)
+ "prefs": track['prefs']
} )
bookmarks = decoded_payload[ 'bookmarks' ]
vis_rev.config = { "tracks": tracks, "bookmarks": bookmarks }
--- a/static/scripts/trackster.js Mon Sep 19 11:59:09 2011 -0400
+++ b/static/scripts/trackster.js Mon Sep 19 16:07:53 2011 -0400
@@ -723,6 +723,22 @@
$(window).trigger("resize");
this.update_intro_div();
},
+ /** JSONify view. */
+ to_json: function() {
+ var
+ view = this,
+ jsonified_drawables = [];
+ this.viewport_container.children(".track,.group").each(function() {
+ // Get object ID.
+ var id = $(this).attr("id");
+ id = parseInt( id.slice(id.lastIndexOf("_") + 1) );
+
+ // JSONify drawable.
+ jsonified_drawables.push(view.tracks[id].to_json());
+ });
+
+ return jsonified_drawables;
+ },
/** Show or hide intro div depending on view state. */
update_intro_div: function() {
if (this.num_tracks === 0) {
@@ -2030,35 +2046,8 @@
this.tool = (tool_dict !== undefined && obj_length(tool_dict) > 0 ? new Tool(this, tool_dict) : undefined);
this.is_overview = false;
- //
- // TODO: Right now there is only the notion of a parent track and multiple child tracks. However,
- // a more general notion of a 'track group' is probably needed and can be easily created using
- // the code already in place for parent/child tracks. The view would then manage track groups, and
- // each track group could be managed on its own.
- //
- this.parent_track = parent_track;
- this.child_tracks = [];
-
if (track.hidden) { return; }
-
- //
- // If track has parent:
- // -replace drag handle with child-track icon button; (TODO: eventually, we'll want to be able
- // to make a set of child tracks dragable.)
- // -remove tool b/c child tracks cannot have tools.
- //
- if (this.parent_track) {
- this.header_div.find(".draghandle").removeClass('draghandle').addClass('child-track-icon').addClass('icon-button');
- this.parent_element.addClass("child-track");
- this.tool = undefined;
- }
-
- //
- // Child tracks container setup.
- //
- track.child_tracks_container = $("<div/>").addClass("child-tracks-container").hide();
- track.container_div.append(track.child_tracks_container);
-
+
//
// Create filters div.
//
@@ -2103,6 +2092,18 @@
};
extend(TiledTrack.prototype, Track.prototype, {
/**
+ * Convert track to JSON object.
+ */
+ to_json: function() {
+ return {
+ "track_type": this.get_type(),
+ "name": this.name,
+ "hda_ldda": this.hda_ldda,
+ "dataset_id": this.dataset_id,
+ "prefs": this.prefs
+ };
+ },
+ /**
* Change track's mode.
*/
change_mode: function(name) {
@@ -2208,19 +2209,10 @@
//
// Remove option.
//
-
- // Need to either remove track from view or from parent.
- var parent_obj = view;
- var no_tracks_fn = function() { $("#no-tracks").show(); };
- if (this.parent_track) {
- // Track is child track.
- parent_obj = this.parent_track;
- no_tracks_fn = function() {};
- }
track_dropdown.Remove = function() {
- parent_obj.remove_track(track);
+ view.remove_track(track);
if (parent_obj.num_tracks === 0) {
- no_tracks_fn();
+ $("#no-tracks").show();
}
};
@@ -2331,10 +2323,6 @@
if (all_tiles_drawn) {
track.postdraw_actions(drawn_tiles, width, w_scale, clear_after);
}
- // Draw child tracks.
- for (var i = 0; i < this.child_tracks.length; i++) {
- this.child_tracks[i].request_draw(force, clear_after);
- }
},
/**
* Actions to be taken after draw has been completed. Draw is completed when all tiles have been
@@ -2511,26 +2499,6 @@
region = (chrom !== undefined && low !== undefined && high !== undefined ?
chrom + ":" + low + "-" + high : "all");
return " - region=[" + region + "], parameters=[" + track.tool.get_param_values().join(", ") + "]";
- },
- /**
- * Add a child track to this track.
- */
- add_track: function(child_track) {
- child_track.track_id = this.track_id + "_" + this.child_tracks.length;
- child_track.container_div.attr('id', 'track_' + child_track.track_id);
- this.child_tracks_container.append(child_track.container_div);
- moveable( child_track.container_div, '.child-track-icon' );
- if (!$(this.child_tracks_container).is(":visible")) {
- this.child_tracks_container.show();
- }
- this.child_tracks.push(child_track);
- this.view.has_changes = true;
- },
- /**
- * Remove a child track from this track.
- */
- remove_track: function(child_track) {
- child_track.container_div.fadeOut('slow', function() { $(this).remove(); });
}
});
--- a/static/scripts/trackster_ui.js Mon Sep 19 11:59:09 2011 -0400
+++ b/static/scripts/trackster_ui.js Mon Sep 19 16:07:53 2011 -0400
@@ -39,8 +39,7 @@
var track_from_dict = function(track_dict) {
return new addable_track_types[track_dict.track_type](
track_dict.name, view, track_dict.hda_ldda, track_dict.dataset_id,
- track_dict.prefs, track_dict.filters, track_dict.tool
- /* TODO: ( track_dict.is_child ? parent_track : undefined */ );
+ track_dict.prefs, track_dict.filters, track_dict.tool);
};
/**
@@ -57,7 +56,6 @@
var track_config, track, parent_track, parent_obj;
for (var i = 0; i < tracks_config.length; i++) {
track_config = tracks_config[i];
- // TODO: set parent for child track:
track = track_from_dict(track_config);
parent_obj = view;
if (track_config.is_child) {
--- a/templates/tracks/browser.mako Mon Sep 19 11:59:09 2011 -0400
+++ b/templates/tracks/browser.mako Mon Sep 19 16:07:53 2011 -0400
@@ -205,24 +205,8 @@
// Show saving dialog box
show_modal("Saving...", "<img src='${h.url_for('/static/images/yui/rel_interstitial_loading.gif')}'/>");
- // TODO: make save into its own function.
-
// Save tracks.
- var saved_tracks = [], tracks;
- for (var i = 0; i < view.tracks.length; i++) {
- track = view.tracks[i];
-
- // Add track.
- saved_tracks.push({
- "track_type": track.get_type(),
- "name": track.name,
- "hda_ldda": track.hda_ldda,
- "dataset_id": track.dataset_id,
- "prefs": track.prefs,
- // TODO: remove parent-child relationships in favor of a group.
- "is_child": false
- });
- };
+ var saved_tracks = view.to_json();
// Save bookmarks.
var bookmarks = [];
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: enable tools that produce BED output to be used in visual analytics framework. Enable cluster tool in Trackster.
by Bitbucket 19 Sep '11
by Bitbucket 19 Sep '11
19 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/af6ed2f06f35/
changeset: af6ed2f06f35
user: jgoecks
date: 2011-09-19 17:59:09
summary: Trackster: enable tools that produce BED output to be used in visual analytics framework. Enable cluster tool in Trackster.
affected #: 3 files (-1 bytes)
--- a/lib/galaxy/visualization/tracks/data_providers.py Mon Sep 19 10:24:11 2011 -0400
+++ b/lib/galaxy/visualization/tracks/data_providers.py Mon Sep 19 11:59:09 2011 -0400
@@ -135,6 +135,88 @@
{ 'name' : attrs[ 'name' ], 'type' : column_types[viz_col_index], \
'index' : attrs[ 'index' ] } )
return filters
+
+class BedDataProvider( TracksDataProvider ):
+ """
+ Abstract class that processes BED data from text format to payload format.
+
+ Payload format: [ uid (offset), start, end, name, strand, thick_start, thick_end, blocks ]
+ """
+
+ def get_iterator( self, chrom, start, end ):
+ raise "Unimplemented Method"
+
+ def get_data( self, chrom, start, end, start_val=0, max_vals=None, **kwargs ):
+ iterator = self.get_iterator( chrom, start, end )
+ return self.process_data( iterator, start_val, max_vals, **kwargs )
+
+ def process_data( self, iterator, start_val=0, max_vals=None, **kwargs ):
+ """
+ Provides
+ """
+ # Build data to return. Payload format is:
+ # [ <guid/offset>, <start>, <end>, <name>, <score>, <strand>, <thick_start>,
+ # <thick_end>, <blocks> ]
+ #
+ # First three entries are mandatory, others are optional.
+ #
+ filter_cols = from_json_string( kwargs.get( "filter_cols", "[]" ) )
+ no_detail = ( "no_detail" in kwargs )
+ rval = []
+ message = None
+ for count, line in enumerate( iterator ):
+ if count < start_val:
+ continue
+ if max_vals and count-start_val >= max_vals:
+ message = ERROR_MAX_VALS % ( max_vals, "features" )
+ break
+ # TODO: can we use column metadata to fill out payload?
+ # TODO: use function to set payload data
+
+ feature = line.split()
+ length = len(feature)
+ # Unique id is just a hash of the line
+ payload = [ hash(line), int(feature[1]), int(feature[2]) ]
+
+ if no_detail:
+ rval.append( payload )
+ continue
+
+ # Simpler way to add stuff, but type casting is not done.
+ # Name, score, strand, thick start, thick end.
+ #end = min( len( feature ), 8 )
+ #payload.extend( feature[ 3:end ] )
+
+ # Name, strand, thick start, thick end.
+ if length >= 4:
+ payload.append(feature[3])
+ if length >= 6:
+ payload.append(feature[5])
+ if length >= 8:
+ payload.append(int(feature[6]))
+ payload.append(int(feature[7]))
+
+ # Blocks.
+ if length >= 12:
+ block_sizes = [ int(n) for n in feature[10].split(',') if n != '']
+ block_starts = [ int(n) for n in feature[11].split(',') if n != '' ]
+ blocks = zip( block_sizes, block_starts )
+ payload.append( [ ( int(feature[1]) + block[1], int(feature[1]) + block[1] + block[0] ) for block in blocks ] )
+
+ # Score (filter data)
+ if length >= 5 and filter_cols and filter_cols[0] == "Score":
+ payload.append( float(feature[4]) )
+
+ rval.append( payload )
+
+ return { 'data': rval, 'message': message }
+
+ def write_data_to_file( self, chrom, start, end, filename ):
+ iterator = self.get_iterator( chrom, start, end )
+ out = open( filename, "w" )
+ for line in iterator:
+ out.write( "%s\n" % line )
+ out.close()
class SummaryTreeDataProvider( TracksDataProvider ):
"""
@@ -573,78 +655,7 @@
results.append( payload )
return { 'data': results, 'message': message }
-
-class BedDataProvider( TabixDataProvider ):
- """
- Payload format: [ uid (offset), start, end, name, strand, thick_start, thick_end, blocks ]
- """
-
- def process_data( self, iterator, start_val=0, max_vals=sys.maxint, **kwargs ):
- #
- # Build data to return. Payload format is:
- # [ <guid/offset>, <start>, <end>, <name>, <score>, <strand>, <thick_start>,
- # <thick_end>, <blocks> ]
- #
- # First three entries are mandatory, others are optional.
- #
- filter_cols = from_json_string( kwargs.get( "filter_cols", "[]" ) )
- no_detail = ( "no_detail" in kwargs )
- rval = []
- message = None
- for count, line in enumerate( iterator ):
- if count < start_val:
- continue
- if count-start_val >= max_vals:
- message = ERROR_MAX_VALS % ( max_vals, "features" )
- break
- # TODO: can we use column metadata to fill out payload?
- # TODO: use function to set payload data
-
- feature = line.split()
- length = len(feature)
- # Unique id is just a hash of the line
- payload = [ hash(line), int(feature[1]), int(feature[2]) ]
-
- if no_detail:
- rval.append( payload )
- continue
-
- # Simpler way to add stuff, but type casting is not done.
- # Name, score, strand, thick start, thick end.
- #end = min( len( feature ), 8 )
- #payload.extend( feature[ 3:end ] )
-
- # Name, strand, thick start, thick end.
- if length >= 4:
- payload.append(feature[3])
- if length >= 6:
- payload.append(feature[5])
- if length >= 8:
- payload.append(int(feature[6]))
- payload.append(int(feature[7]))
-
- # Blocks.
- if length >= 12:
- block_sizes = [ int(n) for n in feature[10].split(',') if n != '']
- block_starts = [ int(n) for n in feature[11].split(',') if n != '' ]
- blocks = zip( block_sizes, block_starts )
- payload.append( [ ( int(feature[1]) + block[1], int(feature[1]) + block[1] + block[0] ) for block in blocks ] )
-
- # Score (filter data)
- if length >= 5 and filter_cols and filter_cols[0] == "Score":
- payload.append( float(feature[4]) )
- rval.append( payload )
-
- return { 'data': rval, 'message': message }
-
- def write_data_to_file( self, chrom, start, end, filename ):
- iterator = self.get_iterator( chrom, start, end )
- out = open( filename, "w" )
- for line in iterator:
- out.write( "%s\n" % line )
- out.close()
-
class VcfDataProvider( TabixDataProvider ):
"""
VCF data provider for the Galaxy track browser.
@@ -685,7 +696,7 @@
Provide data from GFF file.
NOTE: this data provider does not use indices, and hence will be very slow
- for large datasets.
+ for large datasets.
"""
def get_data( self, chrom, start, end, start_val=0, max_vals=sys.maxint, **kwargs ):
start, end = int( start ), int( end )
@@ -710,6 +721,30 @@
offset += feature.raw_size
return { 'data': results, 'message': message }
+
+class BedTabixDataProvider( TabixDataProvider, BedDataProvider ):
+ """
+ Provides data from a BED file indexed via tabix.
+ """
+ pass
+
+class RawBedDataProvider( BedDataProvider ):
+ """
+ Provide data from BED file.
+
+ NOTE: this data provider does not use indices, and hence will be very slow
+ for large datasets.
+ """
+
+ def get_iterator( self, chrom, start, end ):
+ def line_filter_iter():
+ for line in open( self.original_dataset.file_name ):
+ feature = line.split()
+ feature_chrom, feature_start, feature_end = feature[ 0:3 ]
+ if feature_chrom != chrom or feature_start > end or feature_end < start:
+ continue
+ yield line
+ return line_filter_iter()
#
# Helper methods.
@@ -719,7 +754,7 @@
# type. First key is converted dataset type; if result is another dict, second key
# is original dataset type. TODO: This needs to be more flexible.
dataset_type_name_to_data_provider = {
- "tabix": { Vcf: VcfDataProvider, Bed: BedDataProvider, "default" : TabixDataProvider },
+ "tabix": { Vcf: VcfDataProvider, Bed: BedTabixDataProvider, "default" : TabixDataProvider },
"interval_index": IntervalIndexDataProvider,
"bai": BamDataProvider,
"summary_tree": SummaryTreeDataProvider,
--- a/lib/galaxy/web/controllers/tracks.py Mon Sep 19 10:24:11 2011 -0400
+++ b/lib/galaxy/web/controllers/tracks.py Mon Sep 19 11:59:09 2011 -0400
@@ -397,7 +397,7 @@
def raw_data( self, trans, dataset_id, chrom, low, high, **kwargs ):
"""
Uses original (raw) dataset to return data. This method is useful
- when the dataset is not yet indexed and hence using /data would
+ when the dataset is not yet indexed and hence using data would
be slow because indexes need to be created.
"""
@@ -409,10 +409,15 @@
# Return data.
data = None
+ # TODO: for raw data requests, map dataset type to provider using dict in data_providers.py
if isinstance( dataset.datatype, Gff ):
data = GFFDataProvider( original_dataset=dataset ).get_data( chrom, low, high, **kwargs )
data[ 'dataset_type' ] = 'interval_index'
data[ 'extra_info' ] = None
+ if isinstance( dataset.datatype, Bed ):
+ data = RawBedDataProvider( original_dataset=dataset ).get_data( chrom, low, high, **kwargs )
+ data[ 'dataset_type' ] = 'interval_index'
+ data[ 'extra_info' ] = None
return data
@web.json
--- a/tools/new_operations/cluster.xml Mon Sep 19 10:24:11 2011 -0400
+++ b/tools/new_operations/cluster.xml Mon Sep 19 11:59:09 2011 -0400
@@ -1,5 +1,6 @@
<tool id="gops_cluster_1" name="Cluster"><description>the intervals of a dataset</description>
+ <trackster_conf/><command interpreter="python">gops_cluster.py $input1 $output -1 ${input1.metadata.chromCol},${input1.metadata.startCol},${input1.metadata.endCol},${input1.metadata.strandCol} -d $distance -m $minregions -o $returntype</command><inputs><param format="interval" name="input1" type="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: Improve sorting and filtering in 'add to browser' grid.
by Bitbucket 19 Sep '11
by Bitbucket 19 Sep '11
19 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/b3eaa7291f56/
changeset: b3eaa7291f56
user: jgoecks
date: 2011-09-19 16:24:11
summary: Improve sorting and filtering in 'add to browser' grid.
affected #: 1 file (-1 bytes)
--- a/lib/galaxy/web/controllers/tracks.py Mon Sep 19 08:49:00 2011 -0400
+++ b/lib/galaxy/web/controllers/tracks.py Mon Sep 19 10:24:11 2011 -0400
@@ -148,17 +148,17 @@
template = "/tracks/add_to_viz.mako"
async_template = "/page/select_items_grid_async.mako"
model_class = model.Visualization
- default_filter = { "deleted" : "False" , "shared" : "All" }
- default_sort_key = "title"
+ default_sort_key = "-update_time"
use_async = True
use_paging = False
columns = [
grids.TextColumn( "Title", key="title", model_class=model.Visualization, filterable="standard" ),
- grids.TextColumn( "Dbkey", key="dbkey", model_class=model.Visualization )
+ grids.TextColumn( "Dbkey", key="dbkey", model_class=model.Visualization ),
+ grids.GridColumn( "Last Updated", key="update_time", format=time_ago )
]
def build_initial_query( self, trans, **kwargs ):
- return trans.sa_session.query( self.model_class )
+ return trans.sa_session.query( self.model_class ).filter( self.model_class.deleted == False )
def apply_query_filter( self, trans, query, **kwargs ):
return query.filter( self.model_class.user_id == trans.user.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: jgoecks: Trackster: reinstate width for tool panel that was inadverntently removed in dbc0cf838411.
by Bitbucket 19 Sep '11
by Bitbucket 19 Sep '11
19 Sep '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/3fe0b1d568a1/
changeset: 3fe0b1d568a1
user: jgoecks
date: 2011-09-19 14:49:00
summary: Trackster: reinstate width for tool panel that was inadverntently removed in dbc0cf838411.
affected #: 2 files (-1 bytes)
--- a/static/june_2007_style/blue/trackster.css Mon Sep 19 07:22:23 2011 -0400
+++ b/static/june_2007_style/blue/trackster.css Mon Sep 19 08:49:00 2011 -0400
@@ -42,6 +42,7 @@
.nav-labeltrack{border-top:solid #999 1px;border-bottom:solid #333 1px;}
input{font:10px verdana;}
.dynamic-tool,.filters{margin-left:0.25em;padding-bottom:0.5em;}
+.dynamic-tool{width:410px;}
.filters>.sliders,.display-controls{float:left;margin:1em;}
.sliders{width:410px;}
.display-controls{border-left:solid 2px #DDDDDD;padding-left:1em}
--- a/static/june_2007_style/trackster.css.tmpl Mon Sep 19 07:22:23 2011 -0400
+++ b/static/june_2007_style/trackster.css.tmpl Mon Sep 19 08:49:00 2011 -0400
@@ -246,6 +246,9 @@
margin-left: 0.25em;
padding-bottom:0.5em;
}
+.dynamic-tool {
+ width:410px;
+}
.filters > .sliders, .display-controls {
float: left;
margin: 1em;
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/aa0e69109d1b/
changeset: aa0e69109d1b
user: james_taylor
date: 2011-09-19 13:22:23
summary: Pack trackster script
affected #: 1 file (-1 bytes)
--- a/static/scripts/packed/trackster.js Mon Sep 19 00:07:24 2011 -0400
+++ b/static/scripts/packed/trackster.js Mon Sep 19 07:22:23 2011 -0400
@@ -1,1 +1,1 @@
-var class_module=function(b,a){var c=function(){var f=arguments[0];for(var e=1;e<arguments.length;e++){var d=arguments[e];for(key in d){f[key]=d[key]}}return f};a.extend=c};var requestAnimationFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b,a){window.setTimeout(b,1000/60)}})();var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=BEFORE}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var trackster_module=function(f,W){var p=f("class").extend,r=f("slotting"),K=f("painters");var ad=function(ae,af){this.document=ae;this.default_font=af!==undefined?af:"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")};p(ad.prototype,{load_pattern:function(ae,ai){var af=this.patterns,ag=this.dummy_context,ah=new Image();ah.src=image_path+ai;ah.onload=function(){af[ae]=ag.createPattern(ah,"repeat")}},get_pattern:function(ae){return this.patterns[ae]},new_canvas:function(){var ae=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(ae)}ae.manager=this;return ae}});var m=function(ae,ag,ah){ah=".group";var af={};ae.bind("drag",{handle:"."+ag,relative:true},function(an,ao){var aq=$(this).parent(),al=aq.children(),ak,aj,ap,ai,am;aj=$(this).parents(ah);if(aj.length!==0){ap=aj.position().top;ai=ap+aj.outerHeight();if(ao.offsetY<ap){$(this).insertBefore(aj);return}else{if(ao.offsetY>ai){$(this).insertAfter(aj);return}}}aj=null;for(am=0;am<al.length;am++){ak=$(al.get(am));ap=ak.position().top;ai=ap+ak.outerHeight();if(ak.is(ah)&&this!==ak.get(0)&&ao.offsetY>=ap&&ao.offsetY<=ai){if(ao.offsetY-ap<ai-ao.offsetY){ak.find(".content-div").prepend(this)}else{ak.find(".content-div").append(this)}return}}for(am=0;am<al.length;am++){if(ao.offsetY<$(al.get(am)).position().top){break}}if(am===al.length){if(this!==al.get(am-1)){aq.append(this)}}else{if(this!==al.get(am)){$(this).insertBefore(al.get(am))}}}).bind("dragstart",function(){af["border-top"]=ae.css("border-top");af["border-bottom"]=ae.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(af)})};W.moveable=m;var ac=16,F=9,D=20,R=F+2,z=100,H=12000,P=200,C=5,u=10,J=5000,v=100,n="There was an error in indexing this dataset. ",I="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",s="Currently indexing... please wait",x="Tool cannot be rerun: ",a="Loading data...",X="Ready for display",d=10,t=5,B=5;function w(ae){return Math.round(ae*1000)/1000}var c=function(ae){this.num_elements=ae;this.clear()};p(c.prototype,{get:function(af){var ae=this.key_ary.indexOf(af);if(ae!==-1){if(this.obj_cache[af].stale){this.key_ary.splice(ae,1);delete this.obj_cache[af]}else{this.move_key_to_end(af,ae)}}return this.obj_cache[af]},set:function(af,ag){if(!this.obj_cache[af]){if(this.key_ary.length>=this.num_elements){var ae=this.key_ary.shift();delete this.obj_cache[ae]}this.key_ary.push(af)}this.obj_cache[af]=ag;return ag},move_key_to_end:function(af,ae){this.key_ary.splice(ae,1);this.key_ary.push(af)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var Q=function(af,ae,ag){c.call(this,af);this.track=ae;this.subset=(ag!==undefined?ag:true)};p(Q.prototype,c.prototype,{load_data:function(an,ai,al,af,ak){var am=this.track.view.chrom,ah={chrom:am,low:an,high:ai,mode:al,resolution:af,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(ah,ak);if(this.track.filters_manager){var ao=[];var ae=this.track.filters_manager.filters;for(var aj=0;aj<ae.length;aj++){ao[ao.length]=ae[aj].name}ah.filter_cols=JSON.stringify(ao)}var ag=this;return $.getJSON(this.track.data_url,ah,function(ap){ag.set_data(an,ai,al,ap)})},get_data:function(ae,ai,aj,af,ah){var ag=this.get_data_from_cache(ae,ai,aj);if(ag){return ag}ag=this.load_data(ae,ai,aj,af,ah);this.set_data(ae,ai,aj,ag);return ag},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(am,ah,al,ag,ak,ai){var an=this.get_data_from_cache(am,ah,al);if(!an){console.log("ERROR: no current data for: ",this.track,am,ah,al,ag,ak);return}an.stale=true;var af=am;if(ai===this.DEEP_DATA_REQ){$.extend(ak,{start_val:an.data.length+1})}else{if(ai===this.BROAD_DATA_REQ){af=an.data[an.data.length-1][2]+1}}var ae=this,aj=this.load_data(af,ah,al,ag,ak);new_data_available=$.Deferred();this.set_data(am,ah,al,new_data_available);$.when(aj).then(function(ao){if(ao.data){ao.data=an.data.concat(ao.data);if(ao.message){ao.message=ao.message.replace(/[0-9]+/,ao.data.length)}}ae.set_data(am,ah,al,ao);new_data_available.resolve(ao)});return new_data_available},get_data_from_cache:function(ae,af,ag){return this.get(this.gen_key(ae,af,ag))},set_data:function(af,ag,ah,ae){return this.set(this.gen_key(af,ag,ah),ae)},gen_key:function(ae,ag,ah){var af=ae+"_"+ag+"_"+ah;return af},split_key:function(ae){return ae.split("_")}});var G=function(af,ae,ag){Q.call(this,af,ae,ag)};p(G.prototype,Q.prototype,c.prototype,{load_data:function(ag,ae,ai,aj,af,ah){if(af>1){return}return Q.prototype.load_data.call(this,ag,ae,ai,aj,af,ah)}});var ab=function(ae,ah,ag,af,ai){this.container=ae;this.chrom=null;this.vis_id=ag;this.dbkey=af;this.title=ah;this.tracks=[];this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init(ai);this.canvas_manager=new ad(ae.get(0).ownerDocument);this.reset()};p(ab.prototype,{init:function(ai){var ag=this.container,ae=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ag);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ag);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ag);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var ah=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_tracks()});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var af=function(aj){if(aj.type==="focusout"||(aj.keyCode||aj.which)===13||(aj.keyCode||aj.which)===27){if((aj.keyCode||aj.which)!==27){ae.go_to($(this).val())}$(this).hide();$(this).val("");ae.location_span.show();ae.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",af).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.click(function(){ae.location_span.hide();ae.chrom_select.hide();ae.nav_input.val(ae.chrom+":"+ae.low+"-"+ae.high);ae.nav_input.css("display","inline-block");ae.nav_input.select();ae.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a id='zoom-out' />").click(function(){ae.zoom_out();ae.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){ae.zoom_in();ae.request_redraw()}).appendTo(this.nav_controls);this.load_chroms({low:0},ai);this.chrom_select.bind("change",function(){ae.change_chrom(ae.chrom_select.val())});this.content_div.click(function(aj){$(this).find("input").trigger("blur")});this.content_div.bind("dblclick",function(aj){ae.zoom_in(aj.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(aj,ak){this.current_x=ak.offsetX}).bind("drag",function(aj,al){var am=al.offsetX-this.current_x;this.current_x=al.offsetX;var ak=Math.round(am/ae.viewport_container.width()*(ae.max_high-ae.max_low));ae.move_delta(-ak)});this.overview_close.click(function(){ae.reset_overview()});this.viewport_container.bind("draginit",function(aj,ak){if(aj.clientX>ae.viewport_container.width()-16){return false}}).bind("dragstart",function(aj,ak){ak.original_low=ae.low;ak.current_height=aj.clientY;ak.current_x=ak.offsetX}).bind("drag",function(al,an){var aj=$(this);var ao=an.offsetX-an.current_x;var ak=aj.scrollTop()-(al.clientY-an.current_height);aj.scrollTop(ak);an.current_height=al.clientY;an.current_x=an.offsetX;var am=Math.round(ao/ae.viewport_container.width()*(ae.high-ae.low));ae.move_delta(am)}).bind("mousewheel",function(al,an,ak,aj){if(ak){var am=Math.round(-ak/ae.viewport_container.width()*(ae.high-ae.low));ae.move_delta(am)}});this.top_labeltrack.bind("dragstart",function(aj,ak){return $("<div />").css({height:ae.content_div.height()+ae.top_labeltrack.height()+ae.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(an,ao){$(ao.proxy).css({left:Math.min(an.pageX,ao.startX),width:Math.abs(an.pageX-ao.startX)});var ak=Math.min(an.pageX,ao.startX)-ae.container.offset().left,aj=Math.max(an.pageX,ao.startX)-ae.container.offset().left,am=(ae.high-ae.low),al=ae.viewport_container.width();ae.update_location(Math.round(ak/al*am)+ae.low,Math.round(aj/al*am)+ae.low)}).bind("dragend",function(ao,ap){var ak=Math.min(ao.pageX,ap.startX),aj=Math.max(ao.pageX,ap.startX),am=(ae.high-ae.low),al=ae.viewport_container.width(),an=ae.low;ae.low=Math.round(ak/al*am)+an;ae.high=Math.round(aj/al*am)+an;$(ap.proxy).remove();ae.request_redraw()});this.add_label_track(new aa(this,this.top_labeltrack));this.add_label_track(new aa(this,this.nav_labeltrack));$(window).bind("resize",function(){ae.resize_window()});$(document).bind("redraw",function(){ae.redraw()});this.reset();$(window).trigger("resize");this.update_intro_div()},update_intro_div:function(){if(this.num_tracks===0){this.intro_div.show()}else{this.intro_div.hide()}},update_location:function(ae,af){this.location_span.text(commatize(ae)+" - "+commatize(af));this.nav_input.val(this.chrom+":"+commatize(ae)+"-"+commatize(af))},load_chroms:function(af,ag){af.num=v;$.extend(af,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var ae=this;$.ajax({url:chrom_url,data:af,dataType:"json",success:function(ai){if(ai.chrom_info.length===0){alert("Invalid chromosome: "+af.chrom);return}if(ai.reference){ae.add_label_track(new A(ae))}ae.chrom_data=ai.chrom_info;var al='<option value="">Select Chrom/Contig</option>';for(var ak=0,ah=ae.chrom_data.length;ak<ah;ak++){var aj=ae.chrom_data[ak].chrom;al+='<option value="'+aj+'">'+aj+"</option>"}if(ai.prev_chroms){al+='<option value="previous">Previous '+v+"</option>"}if(ai.next_chroms){al+='<option value="next">Next '+v+"</option>"}ae.chrom_select.html(al);if(ag){ag()}ae.chrom_start_index=ai.start_index},error:function(){alert("Could not load chroms for this dbkey:",ae.dbkey)}})},change_chrom:function(ai,af,ak){if(!ai||ai==="None"){return}var ah=this;if(ai==="previous"){ah.load_chroms({low:this.chrom_start_index-v});return}if(ai==="next"){ah.load_chroms({low:this.chrom_start_index+v});return}var aj=$.grep(ah.chrom_data,function(am,an){return am.chrom===ai})[0];if(aj===undefined){ah.load_chroms({chrom:ai},function(){ah.change_chrom(ai,af,ak)});return}else{if(ai!==ah.chrom){ah.chrom=ai;ah.chrom_select.val(ah.chrom);ah.max_high=aj.len-1;ah.reset();ah.request_redraw(true);for(var al=0,ae=ah.tracks.length;al<ae;al++){var ag=ah.tracks[al];if(ag.init){ag.init()}}}if(af!==undefined&&ak!==undefined){ah.low=Math.max(af,0);ah.high=Math.min(ak,ah.max_high)}ah.reset_overview();ah.request_redraw()}},go_to:function(ai){var am=this,ae,ah,af=ai.split(":"),ak=af[0],al=af[1];if(al!==undefined){try{var aj=al.split("-");ae=parseInt(aj[0].replace(/,/g,""),10);ah=parseInt(aj[1].replace(/,/g,""),10)}catch(ag){return false}}am.change_chrom(ak,ae,ah)},move_fraction:function(ag){var ae=this;var af=ae.high-ae.low;this.move_delta(ag*af)},move_delta:function(ag){var ae=this;var af=ae.high-ae.low;if(ae.low-ag<ae.max_low){ae.low=ae.max_low;ae.high=ae.max_low+af}else{if(ae.high-ag>ae.max_high){ae.high=ae.max_high;ae.low=ae.max_high-af}else{ae.high-=ag;ae.low-=ag}}ae.request_redraw()},add_track:function(ae){ae.view=this;ae.track_id=this.track_id_counter;this.tracks.push(ae);if(ae.init){ae.init()}ae.container_div.attr("id","track_"+ae.track_id);m(ae.container_div,ae.drag_handle_class);this.track_id_counter+=1;this.num_tracks+=1;this.has_changes=true;this.update_intro_div()},add_label_track:function(ae){ae.view=this;this.label_tracks.push(ae)},remove_track:function(af){this.has_changes=true;delete this.tracks[this.tracks.indexOf(af)];this.num_tracks-=1;var ae=this;af.container_div.fadeOut("slow",function(){$(this).remove();ae.update_intro_div()})},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(am,ae,al,af){var ak=this,ai=(af?[af]:ak.tracks),ag;var af;for(var aj=0;aj<ai.length;aj++){af=ai[aj];ag=-1;for(var ah=0;ah<ak.tracks_to_be_redrawn.length;ah++){if(ak.tracks_to_be_redrawn[ah][0]===af){ag=ah;break}}if(ag<0){ak.tracks_to_be_redrawn.push([af,ae,al])}else{ak.tracks_to_be_redrawn[aj][1]=ae;ak.tracks_to_be_redrawn[aj][2]=al}}requestAnimationFrame(function(){ak._redraw(am)})},_redraw:function(ao){var al=this.low,ah=this.high;if(al<this.max_low){al=this.max_low}if(ah>this.max_high){ah=this.max_high}var an=this.high-this.low;if(this.high!==0&&an<this.min_separation){ah=al+this.min_separation}this.low=Math.floor(al);this.high=Math.ceil(ah);this.resolution=Math.pow(C,Math.ceil(Math.log((this.high-this.low)/P)/Math.log(C)));this.zoom_res=Math.pow(u,Math.max(0,Math.ceil(Math.log(this.resolution,u)/Math.log(u))));var ae=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ak=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ap=13;this.overview_box.css({left:ae,width:Math.max(ap,ak)}).show();if(ak<ap){this.overview_box.css("left",ae-(ap-ak)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ae,width:ak})}this.update_location(this.low,this.high);if(!ao){var ag,af,am;for(var ai=0,aj=this.tracks_to_be_redrawn.length;ai<aj;ai++){ag=this.tracks_to_be_redrawn[ai][0];af=this.tracks_to_be_redrawn[ai][1];am=this.tracks_to_be_redrawn[ai][2];if(ag&&ag.enabled){ag._draw(af,am)}}this.tracks_to_be_redrawn=[];for(ai=0,aj=this.label_tracks.length;ai<aj;ai++){this.label_tracks[ai]._draw()}}},zoom_in:function(af,ag){if(this.max_high===0||this.high-this.low<this.min_separation){return}var ah=this.high-this.low,ai=ah/2+this.low,ae=(ah/this.zoom_factor)/2;if(af){ai=af/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ai-ae);this.high=Math.round(ai+ae);this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var af=this.high-this.low,ag=af/2+this.low,ae=(af*this.zoom_factor)/2;this.low=Math.round(ag-ae);this.high=Math.round(ag+ae);this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.request_redraw()},set_overview:function(ae){$.when(ae.get_overview_tile()).then(function(af){view.overview_viewport.find(".track-tile").remove();view.overview_close.show();view.overview_viewport.append(af.canvas);view.overview_highlight.show().height(af.canvas.height());view.overview_viewport.height(af.canvas.height()+view.overview_box.outerHeight());view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=ae;ae.set_is_overview(true)});view.has_changes=true},reset_overview:function(){this.overview_viewport.find(".track-tile").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide();view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=null}});var q=function(ag,ak){this.track=ag;this.name=ak.name;this.params=[];var ar=ak.params;for(var ah=0;ah<ar.length;ah++){var am=ar[ah],af=am.name,aq=am.label,ai=unescape(am.html),at=am.value,ao=am.type;if(ao==="number"){this.params[this.params.length]=new g(af,aq,ai,at,am.min,am.max)}else{if(ao=="select"){this.params[this.params.length]=new M(af,aq,ai,at)}else{console.log("WARNING: unrecognized tool parameter type:",af,ao)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(av){av.stopPropagation()}).click(function(av){av.stopPropagation()}).bind("dblclick",function(av){av.stopPropagation()});var ap=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var an=this.params;var al=this;$.each(this.params,function(aw,az){var ay=$("<div>").addClass("param-row").appendTo(al.parent_div);var av=$("<div>").addClass("param-label").text(az.label).appendTo(ay);var ax=$("<div/>").addClass("slider").html(az.html).appendTo(ay);ax.find(":input").val(az.value);$("<div style='clear: both;'/>").appendTo(ay)});this.parent_div.find("input").click(function(){$(this).select()});var au=$("<div>").addClass("param-row").appendTo(this.parent_div);var aj=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(au);var ae=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(au);var al=this;ae.click(function(){al.run_on_region()});aj.click(function(){al.run_on_dataset()})};p(q.prototype,{get_param_values_dict:function(){var ae={};this.parent_div.find(":input").each(function(){var af=$(this).attr("name"),ag=$(this).val();ae[af]=JSON.stringify(ag)});return ae},get_param_values:function(){var af=[];var ae={};this.parent_div.find(":input").each(function(){var ag=$(this).attr("name"),ah=$(this).val();if(ag){af[af.length]=ah}});return af},run_on_dataset:function(){var ae=this;ae.run({dataset_id:this.track.original_dataset_id,tool_id:ae.name},null,function(af){show_modal(ae.name+" is Running",ae.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ae={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},ag=this.track,af=ae.tool_id+ag.tool_region_and_parameters_str(ae.chrom,ae.low,ae.high),ah;if(ag instanceof e){ah=new T(af,view,ag.hda_ldda,undefined,{},{},ag);ah.change_mode(ag.mode)}this.track.add_track(ah);ah.content_div.text("Starting job.");this.run(ae,ah,function(ai){ah.dataset_id=ai.dataset_id;ah.content_div.text("Running job.");ah.init()})},run:function(af,ag,ah){$.extend(af,this.get_param_values_dict());var ae=function(){$.getJSON(rerun_tool_url,af,function(ai){if(ai==="no converter"){ag.container_div.addClass("error");ag.content_div.text(I)}else{if(ai.error){ag.container_div.addClass("error");ag.content_div.text(x+ai.message)}else{if(ai==="pending"){ag.container_div.addClass("pending");ag.content_div.text("Converting input data so that it can be used quickly with tool.");setTimeout(ae,2000)}else{ah(ai)}}}})};ae()}});var M=function(af,ae,ag,ah){this.name=af;this.label=ae;this.html=ag;this.value=ah};var g=function(ag,af,ai,aj,ah,ae){M.call(this,ag,af,ai,aj);this.min=ah;this.max=ae};var h=function(af,ae,ag,ah){this.name=af;this.index=ae;this.tool_id=ag;this.tool_exp_name=ah};var U=function(af,ae,ag,ah){h.call(this,af,ae,ag,ah);this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.min=Number.MAX_VALUE;this.max=-Number.MAX_VALUE;this.container=null;this.slider=null;this.slider_label=null};p(U.prototype,{applies_to:function(ae){if(ae.length>this.index){return true}return false},keep:function(ae){if(!this.applies_to(ae)){return true}var af=parseFloat(ae[this.index]);return(isNaN(af)||(af>=this.low&&af<=this.high))},update_attrs:function(af){var ae=false;if(!this.applies_to(af)){return ae}if(af[this.index]<this.min){this.min=Math.floor(af[this.index]);ae=true}if(af[this.index]>this.max){this.max=Math.ceil(af[this.index]);ae=true}return ae},update_ui_elt:function(){if(this.min!=this.max){this.container.show()}else{this.container.hide()}var ag=function(aj,ah){var ai=ah-aj;return(ai<=2?0.01:1)};var af=this.slider.slider("option","min"),ae=this.slider.slider("option","max");if(this.min<af||this.max>ae){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",ag(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var Z=function(ao,av){this.track=ao;this.filters=[];for(var ap=0;ap<av.length;ap++){var aq=av[ap],aw=aq.name,ae=aq.type,ah=aq.index,au=aq.tool_id,at=aq.tool_exp_name;if(ae==="int"||ae==="float"){this.filters[ap]=new U(aw,ah,au,at)}else{console.log("ERROR: unsupported filter: ",aw,ae)}}var ai=function(ax,ay,az){ax.click(function(){var aA=ay.text();max=parseFloat(az.slider("option","max")),input_size=(max<=1?4:max<=1000000?max.toString().length:6),multi_value=false;if(az.slider("option","values")){input_size=2*input_size+1;multi_value=true}ay.text("");$("<input type='text'/>").attr("size",input_size).attr("maxlength",input_size).attr("value",aA).appendTo(ay).focus().select().click(function(aB){aB.stopPropagation()}).blur(function(){$(this).remove();ay.text(aA)}).keyup(function(aF){if(aF.keyCode===27){$(this).trigger("blur")}else{if(aF.keyCode===13){var aD=az.slider("option","min"),aB=az.slider("option","max"),aE=function(aG){return(isNaN(aG)||aG>aB||aG<aD)},aC=$(this).val();if(!multi_value){aC=parseFloat(aC);if(aE(aC)){alert("Parameter value must be in the range ["+aD+"-"+aB+"]");return $(this)}}else{aC=aC.split("-");aC=[parseFloat(aC[0]),parseFloat(aC[1])];if(aE(aC[0])||aE(aC[1])){alert("Parameter value must be in the range ["+aD+"-"+aB+"]");return $(this)}}az.slider((multi_value?"values":"value"),aC)}}})})};this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(ax){ax.stopPropagation()}).click(function(ax){ax.stopPropagation()}).bind("dblclick",function(ax){ax.stopPropagation()}).bind("keydown",function(ax){ax.stopPropagation()});var ar=$("<div/>").addClass("sliders").appendTo(this.parent_div);var am=this;$.each(this.filters,function(aA,aC){aC.container=$("<div/>").addClass("slider-row").appendTo(ar);var aB=$("<div/>").addClass("elt-label").appendTo(aC.container);var az=$("<span/>").addClass("slider-name").text(aC.name+" ").appendTo(aB);var ay=$("<span/>");var aE=$("<span/>").addClass("slider-value").appendTo(aB).append("[").append(ay).append("]");var ax=$("<div/>").addClass("slider").appendTo(aC.container);aC.control_element=$("<div/>").attr("id",aC.name+"-filter-control").appendTo(ax);var aD=[0,0];aC.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(aG,aH){var aF=aH.values;ay.text(aF[0]+"-"+aF[1]);aC.low=aF[0];aC.high=aF[1];am.track.request_draw(true,true)},change:function(aF,aG){aC.control_element.slider("option","slide").call(aC.control_element,aF,aG)}});aC.slider=aC.control_element;aC.slider_label=ay;ai(aE,ay,aC.control_element);$("<div style='clear: both;'/>").appendTo(aC.container)});if(this.filters.length!==0){var aj=$("<div/>").addClass("param-row").appendTo(ar);var al=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(aj);var ag=this;al.click(function(){ag.run_on_dataset()})}var an=$("<div/>").addClass("display-controls").appendTo(this.parent_div),ak=$("<span/>").addClass("elt-label").text("Transparency:").appendTo(an),af=$("<select/>").attr("name","alpha_dropdown").appendTo(an);this.alpha_filter=null;$("<option/>").attr("value",-1).text("== None ==").appendTo(af);for(var ap=0;ap<this.filters.length;ap++){$("<option/>").attr("value",ap).text(this.filters[ap].name).appendTo(af)}af.change(function(){$(this).children("option:selected").each(function(){var ax=parseInt($(this).val());am.alpha_filter=(ax>=0?am.filters[ax]:null);am.track.request_draw(true,true)})});$("<div style='clear: both;'/>").appendTo(this.parent_div)};p(Z.prototype,{reset_filters:function(){for(var ae=0;ae<this.filters.length;ae++){filter=this.filters[ae];filter.slider.slider("option","values",[filter.min,filter.max])}this.alpha_filter=null},run_on_dataset:function(){var am=function(aq,ao,ap){if(!(ao in aq)){aq[ao]=ap}return aq[ao]};var ag={},ae,af,ah;for(var ai=0;ai<this.filters.length;ai++){ae=this.filters[ai];if(ae.tool_id){if(ae.min!=ae.low){af=am(ag,ae.tool_id,[]);af[af.length]=ae.tool_exp_name+" >= "+ae.low}if(ae.max!=ae.high){af=am(ag,ae.tool_id,[]);af[af.length]=ae.tool_exp_name+" <= "+ae.high}}}var ak=[];for(var an in ag){ak[ak.length]=[an,ag[an]]}var al=ak.length;(function aj(av,ar){var ap=ar[0],aq=ap[0],au=ap[1],at="("+au.join(") and (")+")",ao={cond:at,input:av,target_dataset_id:av,tool_id:aq},ar=ar.slice(1);$.getJSON(run_tool_url,ao,function(aw){if(aw.error){show_modal("Filter Dataset","Error running tool "+aq,{Close:hide_modal})}else{if(ar.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{aj(aw.dataset_id,ar)}}})})(this.track.dataset_id,ak)}});var N=function(af,ae){K.AlphaGenerator.call(this,ae);this.filter=af};N.prototype.gen_alpha=function(ae){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_alpha}return((parseFloat(ae[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var Y=function(ae){this.track=ae.track;this.params=ae.params;this.values={};if(ae.saved_values){this.restore_values(ae.saved_values)}this.onchange=ae.onchange};p(Y.prototype,{restore_values:function(ae){var af=this;$.each(this.params,function(ag,ah){if(ae[ah.key]!==undefined){af.values[ah.key]=ae[ah.key]}else{af.values[ah.key]=ah.default_value}})},build_form:function(){var af=this;var ae=$("<div />");$.each(this.params,function(aj,ah){if(!ah.hidden){var ag="param_"+aj;var al=af.values[ah.key];var ao=$("<div class='form-row' />").appendTo(ae);ao.append($("<label />").attr("for",ag).text(ah.label+":"));if(ah.type==="bool"){ao.append($('<input type="checkbox" />').attr("id",ag).attr("name",ag).attr("checked",al))}else{if(ah.type==="text"){ao.append($('<input type="text"/>').attr("id",ag).val(al).click(function(){$(this).select()}))}else{if(ah.type==="color"){var ak=$("<input />").attr("id",ag).attr("name",ag).val(al);var am=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var ai=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(am);var an=$("<div/>").appendTo(ai).farbtastic({width:100,height:100,callback:ak,color:al});$("<div />").append(ak).append(am).appendTo(ao).bind("click",function(ap){am.css({left:$(this).position().left+($(ak).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){am.hide();$(document).unbind("click.color-picker")});ap.stopPropagation()})}else{ao.append($("<input />").attr("id",ag).attr("name",ag).val(al))}}}}});return ae},update_from_form:function(ae){var ag=this;var af=false;$.each(this.params,function(ah,aj){if(!aj.hidden){var ak="param_"+ah;var ai=ae.find("#"+ak).val();if(aj.type==="float"){ai=parseFloat(ai)}else{if(aj.type==="int"){ai=parseInt(ai)}else{if(aj.type==="bool"){ai=ae.find("#"+ak).is(":checked")}}}if(ai!==ag.values[aj.key]){ag.values[aj.key]=ai;af=true}}});if(af){this.onchange()}}});var b=function(ag,af,ae,ah){this.index=ag;this.low=ag*P*af;this.high=(ag+1)*P*af;this.resolution=af;this.canvas=$("<div class='track-tile'/>").append(ae);this.data=ah;this.stale=false};var l=function(ag,af,ae,ah,ai){b.call(this,ag,af,ae,ah);this.max_val=ai};var O=function(ag,af,ae,ai,ah){b.call(this,ag,af,ae,ai);this.message=ah};var o=function(af,ae){this.name=af;this.view=ae;this.parent_element=ae.viewport_container};o.prototype.request_draw=function(){};o.prototype.draw=function(){};var y=function(af,ae){o.call(this,af,ae);this.members=[];this.drag_handle_class="group-handle";this.container_div=$("<div/>").addClass("group").appendTo(this.parent_element);this.container_div.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("group-name").text(this.name).appendTo(this.container_div);this.content_div=$("<div/>").addClass("content-div").appendTo(this.container_div)};p(y.prototype,o.prototype,{request_draw:function(af,ae){},draw:function(){}});var j=function(af,ae,ai,ag,ah){this.name=af;this.view=ae;this.parent_element=ai;this.data_url=(ag?ag:default_data_url);this.data_url_extra_params={};this.data_query_wait=(ah?ah:J);this.dataset_check_url=converted_datasets_state_url;this.drag_handle_class="draghandle";this.container_div=$("<div />").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)};p(j.prototype,{get_type:function(){if(this instanceof aa){return"LabelTrack"}else{if(this instanceof A){return"ReferenceTrack"}else{if(this instanceof k){return"LineTrack"}else{if(this instanceof V){return"ReadTrack"}else{if(this instanceof T){return"ToolDataFeatureTrack"}else{if(this instanceof S){return"VcfTrack"}else{if(this instanceof e){return"FeatureTrack"}}}}}}}return""},init:function(){var ae=this;ae.enabled=false;ae.tile_cache.clear();ae.data_manager.clear();ae.initial_canvas=undefined;ae.content_div.css("height","auto");ae.container_div.removeClass("nodata error pending");if(!ae.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:ae.hda_ldda,dataset_id:ae.dataset_id,chrom:ae.view.chrom},function(af){if(!af||af==="error"||af.kind==="error"){ae.container_div.addClass("error");ae.content_div.text(n);if(af.message){var ah=ae.view.tracks.indexOf(ae);var ag=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+af.message+"</pre>",{Close:hide_modal})});ae.content_div.append(ag)}}else{if(af==="no converter"){ae.container_div.addClass("error");ae.content_div.text(I)}else{if(af==="no data"||(af.data!==undefined&&(af.data===null||af.data.length===0))){ae.container_div.addClass("nodata");ae.content_div.text(E)}else{if(af==="pending"){ae.container_div.addClass("pending");ae.content_div.text(s);setTimeout(function(){ae.init()},ae.data_query_wait)}else{if(af.status==="data"){if(af.valid_chroms){ae.valid_chroms=af.valid_chroms;ae.make_name_popup_menu()}ae.content_div.text(X);if(ae.view.chrom){ae.content_div.text("");ae.content_div.css("height",ae.height_px+"px");ae.enabled=true;$.when(ae.predraw_init()).done(function(){ae.container_div.removeClass("nodata error pending");ae.request_draw()})}}}}}}})},predraw_init:function(){},set_name:function(ae){this.old_name=this.name;this.name=ae;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)}});var L=function(al,aj,am){var af=this,an=af.view;this.filters_manager=(al!==undefined?new Z(this,al):undefined);this.filters_available=false;this.filters_visible=false;this.tool=(aj!==undefined&&obj_length(aj)>0?new q(this,aj):undefined);this.is_overview=false;this.parent_track=am;this.child_tracks=[];if(af.hidden){return}if(this.parent_track){this.header_div.find(".draghandle").removeClass("draghandle").addClass("child-track-icon").addClass("icon-button");this.parent_element.addClass("child-track");this.tool=undefined}af.child_tracks_container=$("<div/>").addClass("child-tracks-container").hide();af.container_div.append(af.child_tracks_container);if(this.filters_manager){this.filters_div=this.filters_manager.parent_div;this.header_div.after(this.filters_div)}if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}if(af.display_modes!==undefined){if(af.mode_div===undefined){af.mode_div=$("<div class='right-float menubutton popup' />").appendTo(af.header_div);var ag=(af.track_config&&af.track_config.values.mode?af.track_config.values.mode:af.display_modes[0]);af.mode=ag;af.mode_div.text(ag);var ae={};for(var ah=0,ak=af.display_modes.length;ah<ak;ah++){var ai=af.display_modes[ah];ae[ai]=function(ao){return function(){af.change_mode(ao)}}(ai)}make_popupmenu(af.mode_div,ae)}else{af.mode_div.hide()}}this.make_name_popup_menu()};p(L.prototype,j.prototype,{change_mode:function(af){var ae=this;ae.mode_div.text(af);ae.mode=af;ae.track_config.values.mode=af;ae.tile_cache.clear();ae.request_draw()},make_name_popup_menu:function(){var af=this;var ae={};ae[(this.is_overview?"Hide overview":"Set as overview")]=function(){if(af.is_overview){af.view.reset_overview()}else{af.view.set_overview(af)}};ae["Edit configuration"]=function(){var al=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},aj=function(){af.track_config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ak=function(am){if((am.keyCode||am.which)===27){al()}else{if((am.keyCode||am.which)===13){aj()}}};$(window).bind("keypress.check_enter_esc",ak);show_modal("Configure Track",af.track_config.build_form(),{Cancel:al,OK:aj})};if(af.filters_available>0){var ai=(af.filters_div.is(":visible")?"Hide filters":"Show filters");ae[ai]=function(){af.filters_visible=(af.filters_div.is(":visible"));if(af.filters_visible){af.filters_manager.reset_filters()}af.filters_div.toggle();af.make_name_popup_menu()}}if(af.tool){var ai=(af.dynamic_tool_div.is(":visible")?"Hide tool":"Show tool");ae[ai]=function(){if(!af.dynamic_tool_div.is(":visible")){af.set_name(af.name+af.tool_region_and_parameters_str())}else{menu_option_text="Show dynamic tool";af.revert_name()}af.dynamic_tool_div.toggle();af.make_name_popup_menu()}}if(af.valid_chroms){ae["List chrom/contigs with data"]=function(){show_modal("Chrom/contigs with data","<p>"+af.valid_chroms.join("<br/>")+"</p>",{Close:function(){hide_modal()}})}}var ag=view;var ah=function(){$("#no-tracks").show()};if(this.parent_track){ag=this.parent_track;ah=function(){}}ae.Remove=function(){ag.remove_track(af);if(ag.num_tracks===0){ah()}};make_popupmenu(af.name_div,ae)},set_is_overview:function(ae){this.is_overview=ae;this.make_name_popup_menu()},get_overview_tile:function(){var ae=this;view=ae.view,resolution=Math.pow(C,Math.ceil(Math.log((view.max_high-view.max_low)/P)/Math.log(C))),view_width=view.container.width(),w_scale=view_width/(view.max_high-view.max_low),overview_tile=$.Deferred();$.when(ae.data_manager.get_data(view.max_low,view.max_high,"Auto",resolution,ae.data_url_extra_params)).then(function(af){var ah=ae._gen_tile_cache_key(view_width,w_scale,0),aj=ae.tile_cache.get(ah);if(!aj){aj=ae.draw_tile(af,"Auto",resolution,0,w_scale);ae.tile_cache.set(ah,aj)}var am=$(aj.canvas.find("canvas")),ai=am.clone(),al=am.get(0).getContext("2d"),ag=ai.get(0).getContext("2d"),ak=al.getImageData(0,0,al.canvas.width,al.canvas.height);ag.putImageData(ak,-ae.left_offset,(aj.data.dataset_type==="summary_tree"?R:0));new_tile=new b(-1,resolution,ai);overview_tile.resolve(new_tile)});return overview_tile},_gen_tile_cache_key:function(af,ag,ae){return af+"_"+ag+"_"+ae},request_draw:function(af,ae){this.view.request_redraw(false,af,ae,this)},_draw:function(ag,ap){if(!this.dataset_id){return}var ao=this.view.low,ak=this.view.high,am=ak-ao,ah=this.view.container.width(),at=ah/am,aj=this.view.resolution,ar=$("<div style='position: relative;'></div>");if(!ap){this.content_div.children().remove()}this.content_div.append(ar);this.max_height=0;var af=Math.floor(ao/aj/P);var an=true;var aq=[];var ae=0;while((af*P*aj)<ak){tile=this.draw_helper(ag,ah,af,aj,ar,at);if(tile){aq.push(tile)}else{an=false}af+=1;ae++}var ai=this;if(an){ai.postdraw_actions(aq,ah,at,ap)}for(var al=0;al<this.child_tracks.length;al++){this.child_tracks[al].request_draw(ag,ap)}},postdraw_actions:function(ai,aj,ak,ae){var ag=this;var ah=false;for(var af=0;af<ai.length;af++){if(ai[af].message){ah=true;break}}if(ah){for(var af=0;af<ai.length;af++){tile=ai[af];if(!tile.message){tile.canvas.css("padding-top",D)}}}},draw_helper:function(af,ag,ah,ak,aq,av,ar,al){var ai=this,ap=this._gen_tile_cache_key(ag,av,ah),am=ah*P*ak,au=am+P*ak;var an=(af?undefined:ai.tile_cache.get(ap));if(an){ai.show_tile(an,aq,av);return an}var ao=function(aw){return("isResolved" in aw)};var aj=true;var ae=ai.data_manager.get_data(am,au,ai.mode,ak,ai.data_url_extra_params);if(ao(ae)){aj=false}var at;if(view.reference_track&&av>view.canvas_manager.char_width_px){at=view.reference_track.data_manager.get_data(am,au,ai.mode,ak,view.reference_track.data_url_extra_params);if(ao(at)){aj=false}}if(aj){p(ae,al);var an=ai.draw_tile(ae,ai.mode,ak,ah,av,at);ai.tile_cache.set(ap,an);if(an!==undefined){ai.show_tile(an,aq,av)}return an}$.when(ae,at).then(function(){view.request_redraw()});return null},show_tile:function(al,an,ao){var ag=this,af=al.canvas,ak=af;if(al.message){var ap=$("<div/>"),am=$("<div/>").addClass("tile-message").text(al.message).css({height:D-1,width:al.canvas.width}).appendTo(ap),ai=$("<a href='javascript:void(0);'/>").addClass("icon more-down").appendTo(am),ae=$("<a href='javascript:void(0);'/>").addClass("icon more-across").appendTo(am);ap.append(af);ak=ap;ai.click(function(){al.stale=true;ag.data_manager.get_more_data(al.low,al.high,ag.mode,al.resolution,{},ag.data_manager.DEEP_DATA_REQ);ag.request_draw()}).dblclick(function(aq){aq.stopPropagation()});ae.click(function(){al.stale=true;ag.data_manager.get_more_data(al.low,al.high,ag.mode,al.resolution,{},ag.data_manager.BROAD_DATA_REQ);ag.request_draw()}).dblclick(function(aq){aq.stopPropagation()})}var aj=this.view.high-this.view.low,ah=(al.low-this.view.low)*ao;if(this.left_offset){ah-=this.left_offset}ak.css({position:"absolute",top:0,left:ah,height:""});an.append(ak);ag.max_height=Math.max(ag.max_height,ak.height());ag.content_div.css("height",ag.max_height+"px");an.children().css("height",ag.max_height+"px")},tool_region_and_parameters_str:function(ag,ae,ah){var af=this,ai=(ag!==undefined&&ae!==undefined&&ah!==undefined?ag+":"+ae+"-"+ah:"all");return" - region=["+ai+"], parameters=["+af.tool.get_param_values().join(", ")+"]"},add_track:function(ae){ae.track_id=this.track_id+"_"+this.child_tracks.length;ae.container_div.attr("id","track_"+ae.track_id);this.child_tracks_container.append(ae.container_div);m(ae.container_div,".child-track-icon");if(!$(this.child_tracks_container).is(":visible")){this.child_tracks_container.show()}this.child_tracks.push(ae);this.view.has_changes=true},remove_track:function(ae){ae.container_div.fadeOut("slow",function(){$(this).remove()})}});var aa=function(ae,af){this.hidden=true;j.call(this,null,ae,af);this.container_div.addClass("label-track")};p(aa.prototype,j.prototype,{_draw:function(){var ag=this.view,ah=ag.high-ag.low,ak=Math.floor(Math.pow(10,Math.floor(Math.log(ah)/Math.log(10)))),ae=Math.floor(ag.low/ak)*ak,ai=this.view.container.width(),af=$("<div style='position: relative; height: 1.3em;'></div>");while(ae<ag.high){var aj=(ae-ag.low)/ah*ai;af.append($("<div class='label'>"+commatize(ae)+"</div>").css({position:"absolute",left:aj-1}));ae+=ak}this.content_div.children(":first").remove();this.content_div.append(af)}});var A=function(ae){this.hidden=true;j.call(this,null,ae,ae.top_labeltrack);L.call(this);ae.reference_track=this;this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url;this.data_url_extra_params={dbkey:ae.dbkey};this.data_manager=new G(B,this,false);this.tile_cache=new c(t)};p(A.prototype,L.prototype,{draw_tile:function(ao,ak,aj,af,ap){var ai=this,ag=P*aj;if(ap>this.view.canvas_manager.char_width_px){if(ao===null){ai.content_div.css("height","0px");return}var ah=this.view.canvas_manager.new_canvas();var an=ah.getContext("2d");ah.width=Math.ceil(ag*ap+ai.left_offset);ah.height=ai.height_px;an.font=an.canvas.manager.default_font;an.textAlign="center";for(var al=0,am=ao.length;al<am;al++){var ae=Math.round(al*ap);an.fillText(ao[al],ae+ai.left_offset,10)}return new b(af,aj,ah,ao)}this.content_div.css("height","0px")}});var k=function(ai,ag,aj,ae,ah){var af=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";j.call(this,ai,ag,ag.viewport_container);L.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=aj;this.dataset_id=ae;this.original_dataset_id=ae;this.data_manager=new Q(B,this);this.tile_cache=new c(t);this.left_offset=0;this.track_config=new Y({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ai},{key:"color",label:"Color",type:"color",default_value:"black"},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.height_px,hidden:true}],saved_values:ah,onchange:function(){af.set_name(af.prefs.name);af.vertical_range=af.prefs.max_value-af.prefs.min_value;$("#linetrack_"+af.track_id+"_minval").text(af.prefs.min_value);$("#linetrack_"+af.track_id+"_maxval").text(af.prefs.max_value);af.tile_cache.clear();af.request_draw()}});this.prefs=this.track_config.values;this.height_px=this.track_config.values.height;this.vertical_range=this.track_config.values.max_value-this.track_config.values.min_value;this.add_resize_handle()};p(k.prototype,L.prototype,{add_resize_handle:function(){var ae=this;var ah=false;var ag=false;var af=$("<div class='track-resize'>");$(ae.container_div).hover(function(){ah=true;af.show()},function(){ah=false;if(!ag){af.hide()}});af.hide().bind("dragstart",function(ai,aj){ag=true;aj.original_height=$(ae.content_div).height()}).bind("drag",function(aj,ak){var ai=Math.min(Math.max(ak.original_height+ak.deltaY,ae.min_height_px),ae.max_height_px);$(ae.content_div).css("height",ai);ae.height_px=ai;ae.request_draw(true)}).bind("dragend",function(ai,aj){ae.tile_cache.clear();ag=false;if(!ah){af.hide()}ae.track_config.values.height=ae.height_px}).appendTo(ae.container_div)},predraw_init:function(){var ae=this,af=ae.view.tracks.indexOf(ae);ae.vertical_range=undefined;return $.getJSON(ae.data_url,{stats:true,chrom:ae.view.chrom,low:null,high:null,hda_ldda:ae.hda_ldda,dataset_id:ae.dataset_id},function(ag){ae.container_div.addClass("line-track");var ai=ag.data;if(isNaN(parseFloat(ae.prefs.min_value))||isNaN(parseFloat(ae.prefs.max_value))){ae.prefs.min_value=ai.min;ae.prefs.max_value=ai.max;$("#track_"+af+"_minval").val(ae.prefs.min_value);$("#track_"+af+"_maxval").val(ae.prefs.max_value)}ae.vertical_range=ae.prefs.max_value-ae.prefs.min_value;ae.total_frequency=ai.total_frequency;ae.container_div.find(".yaxislabel").remove();var aj=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+af+"_minval").text(w(ae.prefs.min_value));var ah=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+af+"_maxval").text(w(ae.prefs.max_value));ah.css({position:"absolute",top:"24px",left:"10px"});ah.prependTo(ae.container_div);aj.css({position:"absolute",bottom:"2px",left:"10px"});aj.prependTo(ae.container_div)})},draw_tile:function(ap,aj,ai,af,ao){if(this.vertical_range===undefined){return}var ak=af*P*ai,ah=P*ai,ae=Math.ceil(ah*ao),am=this.height_px;var ag=this.view.canvas_manager.new_canvas();ag.width=ae,ag.height=am;var an=ag.getContext("2d");var al=new K.LinePainter(ap.data,ak,ak+ah,this.prefs,aj);al.draw(an,ae,am);return new b(af,ai,ag,ap.data)}});var e=function(ae,aj,ai,am,al,ag,ah,ak){var af=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];this.track_config=new Y({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ae},{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:al,onchange:function(){af.set_name(af.prefs.name);af.tile_cache.clear();af.request_draw()}});this.prefs=this.track_config.values;j.call(this,ae,aj,aj.viewport_container);L.call(this,ag,ah,ak);this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=ai;this.dataset_id=am;this.original_dataset_id=am;this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.inc_slots={};this.start_end_dct={};this.tile_cache=new c(d);this.data_manager=new Q(20,this);this.left_offset=200;this.painter=K.LinkedFeaturePainter};p(e.prototype,L.prototype,{postdraw_actions:function(au,ae,av,at){L.prototype.postdraw_actions.call(this,au,at);var ah=this;if(at){var aj=ah.content_div.children();var ak=false;for(var ai=aj.length-1,ao=0;ai>=ao;ai--){var ag=$(aj[ai]);if(ak){ag.remove()}else{if(ag.children().length!==0){ak=true}}}}if(ah.mode=="Histogram"){var an=-1;for(var ai=0;ai<au.length;ai++){var ar=au[ai].max_val;if(ar>an){an=ar}}for(var ai=0;ai<au.length;ai++){var aq=au[ai];if(aq.max_val!==an){aq.canvas.remove();ah.draw_helper(true,ae,aq.index,aq.resolution,aq.canvas.parent(),av,[],{max:an})}}}if(ah.filters_manager){var af=ah.filters_manager.filters;for(var am=0;am<af.length;am++){af[am].update_ui_elt()}var al=false,ap;for(var ai=0;ai<au.length;ai++){if(au[ai].data.length){ap=au[ai].data[0];for(var am=0;am<af.length;am++){if(af[am].applies_to(ap)){al=true;break}}}}if(ah.filters_available!==al){ah.filters_available=al;if(!ah.filters_available){ah.filters_div.hide()}ah.make_name_popup_menu()}}},update_auto_mode:function(ae){if(this.mode=="Auto"){if(ae=="no_detail"){ae="feature spans"}else{if(ae=="summary_tree"){ae="coverage histogram"}}this.mode_div.text("Auto ("+ae+")")}},incremental_slots:function(ai,af,ah){var ag=this.view.canvas_manager.dummy_context,ae=this.inc_slots[ai];if(!ae||(ae.mode!==ah)){ae=new (r.FeatureSlotter)(ai,ah==="Pack",z,function(aj){return ag.measureText(aj)});ae.mode=ah;this.inc_slots[ai]=ae}return ae.slot_features(af)},get_summary_tree_data:function(ai,al,ag,au){if(au>ag-al){au=ag-al}var ap=Math.floor((ag-al)/au),at=[],ah=0;var aj=0,ak=0,ao,ar=0,am=[],aq,an;var af=function(ax,aw,ay,av){ax[0]=aw+ay*av;ax[1]=aw+(ay+1)*av};while(ar<au&&aj!==ai.length){var ae=false;for(;ar<au&&!ae;ar++){af(am,al,ar,ap);for(ak=aj;ak<ai.length;ak++){ao=ai[ak].slice(1,3);if(is_overlap(ao,am)){ae=true;break}}if(ae){break}}data_start_index=ak;at[at.length]=aq=[am[0],0];for(;ak<ai.length;ak++){ao=ai[ak].slice(1,3);if(is_overlap(ao,am)){aq[1]++}else{break}}if(aq[1]>ah){ah=aq[1]}ar++}return{max:ah,delta:ap,data:at}},draw_tile:function(ar,av,aA,aE,an,ah){var ax=this,aG=aE*P*aA,af=(aE+1)*P*aA,au=af-aG,ay=Math.ceil(au*an),aK=25,ai=this.left_offset,at,aj;if(av==="Auto"){if(ar.dataset_type==="summary_tree"){av=ar.dataset_type}else{if(ar.extra_info==="no_detail"){av="no_detail"}else{var aJ=ar.data;if(this.view.high-this.view.low>H){av="Squish"}else{av="Pack"}}}this.update_auto_mode(av)}if(av==="summary_tree"||av==="Histogram"){aj=this.summary_draw_height;this.container_div.find(".yaxislabel").remove();var ae=$("<div />").addClass("yaxislabel");ae.text(ar.max);ae.css({position:"absolute",top:"24px",left:"10px",color:this.prefs.label_color});ae.prependTo(this.container_div);var ag=this.view.canvas_manager.new_canvas();ag.width=ay+ai;ag.height=aj+R;if(ar.dataset_type!="summary_tree"){var ao=this.get_summary_tree_data(ar.data,aG,af,200);if(ar.max){ao.max=ar.max}ar=ao}var aH=new K.SummaryTreePainter(ar,aG,af,this.prefs);var az=ag.getContext("2d");az.translate(ai,R);aH.draw(az,ay,aj);return new l(aE,aA,ag,ar.data,ar.max)}var at,al=1;if(av==="no_detail"||av==="Squish"||av==="Pack"){al=this.incremental_slots(an,ar.data,av);at=this.inc_slots[an].slots}var am=[];if(ar.data){var ap=this.filters_manager.filters;for(var aB=0,aD=ar.data.length;aB<aD;aB++){var ak=ar.data[aB];var aC=false;var aq;for(var aF=0,aI=ap.length;aF<aI;aF++){aq=ap[aF];aq.update_attrs(ak);if(!aq.keep(ak)){aC=true;break}}if(!aC){am.push(ak)}}}var aw=(this.filters_manager.alpha_filter?new N(this.filters_manager.alpha_filter):null);var aH=new (this.painter)(am,aG,af,this.prefs,av,aw,ah);var aj=Math.max(ac,aH.get_required_height(al));var ag=this.view.canvas_manager.new_canvas();ag.width=ay+ai;ag.height=aj;var az=ag.getContext("2d");az.fillStyle=this.prefs.block_color;az.font=az.canvas.manager.default_font;az.textAlign="right";this.container_div.find(".yaxislabel").remove();if(ar.data){az.translate(ai,0);aH.draw(az,ay,aj,at)}return new O(aE,aA,ag,ar.data,ar.message)}});var S=function(ah,af,aj,ae,ag,ai){e.call(this,ah,af,aj,ae,ag,ai);this.painter=K.VariantPainter};p(S.prototype,L.prototype,e.prototype);var V=function(ah,af,aj,ae,ag,ai){e.call(this,ah,af,aj,ae,ag,ai);this.track_config=new Y({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ah},{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ag,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.track_config.values;this.painter=K.ReadPainter;this.make_name_popup_menu()};p(V.prototype,L.prototype,e.prototype);var T=function(ai,ag,ak,ae,ah,aj,af){e.call(this,ai,ag,ak,ae,ah,aj,{},af);this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};p(T.prototype,L.prototype,e.prototype,{predraw_init:function(){var af=this;var ae=function(){if(af.data_manager.size()===0){setTimeout(ae,300)}else{af.data_url=default_data_url;af.data_query_wait=J;af.dataset_state_url=converted_datasets_state_url;$.getJSON(af.dataset_state_url,{dataset_id:af.dataset_id,hda_ldda:af.hda_ldda},function(ag){})}};ae()}});W.View=ab;W.DrawableCollection=y;W.LineTrack=k;W.FeatureTrack=e;W.ReadTrack=V};var slotting_module=function(c,b){var e=c("class").extend;var d=2,a=5;b.FeatureSlotter=function(j,h,f,g){this.slots={};this.start_end_dct={};this.w_scale=j;this.include_label=h;this.max_rows=f;this.measureText=g};e(b.FeatureSlotter.prototype,{slot_features:function(m){var p=this.w_scale,s=this.slots,h=this.start_end_dct,y=[],A=[],n=0,z=this.max_rows;for(var w=0,x=m.length;w<x;w++){var l=m[w],o=l[0];if(s[o]!==undefined){n=Math.max(n,s[o]);A.push(s[o])}else{y.push(w)}}var q=function(G,H){for(var F=0;F<=z;F++){var D=false,I=h[F];if(I!==undefined){for(var C=0,E=I.length;C<E;C++){var B=I[C];if(H>B[0]&&G<B[1]){D=true;break}}}if(!D){return F}}return -1};for(var w=0,x=y.length;w<x;w++){var l=m[y[w]],o=l[0],u=l[1],f=l[2],r=l[3],g=Math.floor(u*p),k=Math.ceil(f*p),v=this.measureText(r).width,j;if(r!==undefined&&this.include_label){v+=(d+a);if(g-v>=0){g-=v;j="left"}else{k+=v;j="right"}}var t=q(g,k);if(t>=0){if(h[t]===undefined){h[t]=[]}h[t].push([g,k]);s[o]=t;n=Math.max(n,t)}else{}}return n+1}})};var painters_module=function(k,x){var u=k("class").extend;var p=function(I,A,G,z,F,D){if(D===undefined){D=4}var C=z-A;var B=F-G;var E=Math.floor(Math.sqrt(C*C+B*B)/D);var J=C/E;var H=B/E;var y;for(y=0;y<E;y++,A+=J,G+=H){if(y%2!==0){continue}I.fillRect(A,G,D,1)}};var q=function(B,A,z,E){var D=A-E/2,C=A+E/2,F=z-Math.sqrt(E*3/2);B.beginPath();B.moveTo(D,F);B.lineTo(C,F);B.lineTo(A,z);B.lineTo(D,F);B.strokeStyle=this.fillStyle;B.fill();B.stroke();B.closePath()};var g=function(y){this.default_alpha=(y?y:1)};g.prototype.gen_alpha=function(y){return this.default_alpha};var n=function(A,C,y,z,B){this.data=A;this.view_start=C;this.view_end=y;this.prefs=u({},this.default_prefs,z);this.mode=B};n.prototype.default_prefs={};var v=function(A,C,y,z,B){n.call(this,A,C,y,z,B)};v.prototype.default_prefs={show_counts:false};v.prototype.draw=function(M,z,L){var E=this.view_start,O=this.view_end-this.view_start,N=z/O;var J=this.data.data,I=this.data.delta,G=this.data.max,B=L;delta_x_px=Math.ceil(I*N);M.save();for(var C=0,D=J.length;C<D;C++){var H=Math.floor((J[C][0]-E)*N);var F=J[C][1];if(!F){continue}var K=F/G*L;if(F!==0&&K<1){K=1}M.fillStyle=this.prefs.block_color;M.fillRect(H,B-K,delta_x_px,K);var A=4;if(this.prefs.show_counts&&(M.measureText(F).width+A)<delta_x_px){M.fillStyle=this.prefs.label_color;M.textAlign="center";M.fillText(F,H+(delta_x_px/2),10)}}M.restore()};var c=function(y,C,E,F,A){n.call(this,y,C,E,F,A);if(this.prefs.min_value===undefined){var G=Infinity;for(var z=0,B=this.data.length;z<B;z++){G=Math.min(G,this.data[z][1])}this.prefs.min_value=G}if(this.prefs.max_value===undefined){var D=-Infinity;for(var z=0,B=this.data.length;z<B;z++){D=Math.max(D,this.data[z][1])}this.prefs.max_value=D}};c.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};c.prototype.draw=function(N,M,K){var F=false,H=this.prefs.min_value,D=this.prefs.max_value,J=D-H,z=K,A=this.view_start,L=this.view_end-this.view_start,B=M/L,I=this.mode,T=this.data;N.save();var U=Math.round(K+H/J*K);if(I!=="Intensity"){N.fillStyle="#aaa";N.fillRect(0,U,M,1)}N.beginPath();var R,E,C;if(T.length>1){C=Math.ceil((T[1][0]-T[0][0])*B)}else{C=10}for(var O=0,P=T.length;O<P;O++){N.fillStyle=this.prefs.color;R=Math.round((T[O][0]-A)*B);E=T[O][1];var Q=false,G=false;if(E===null){if(F&&I==="Filled"){N.lineTo(R,z)}F=false;continue}if(E<H){G=true;E=H}else{if(E>D){Q=true;E=D}}if(I==="Histogram"){E=Math.round(E/J*z);N.fillRect(R,U,C,-E)}else{if(I==="Intensity"){E=255-Math.floor((E-H)/J*255);N.fillStyle="rgb("+E+","+E+","+E+")";N.fillRect(R,0,C,z)}else{E=Math.round(z-(E-H)/J*z);if(F){N.lineTo(R,E)}else{F=true;if(I==="Filled"){N.moveTo(R,z);N.lineTo(R,E)}else{N.moveTo(R,E)}}}}N.fillStyle=this.prefs.overflow_color;if(Q||G){var S;if(I==="Histogram"||I==="Intensity"){S=C}else{R-=2;S=4}if(Q){N.fillRect(R,0,S,3)}if(G){N.fillRect(R,z-3,S,3)}}N.fillStyle=this.prefs.color}if(I==="Filled"){if(F){N.lineTo(R,U);N.lineTo(0,U)}N.fill()}else{N.stroke()}N.restore()};var o=function(B,D,y,A,C,z){n.call(this,B,D,y,A,C);this.alpha_generator=(z?z:new g())};o.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};u(o.prototype,{get_required_height:function(z){var y=y_scale=this.get_row_height(),A=this.mode;if(A==="no_detail"||A==="Squish"||A==="Pack"){y=z*y_scale}return y+Math.max(Math.round(y_scale/2),5)},draw:function(K,B,J,G){var E=this.data,H=this.view_start,L=this.view_end;K.save();K.fillStyle=this.prefs.block_color;K.textAlign="right";var O=this.view_end-this.view_start,N=B/O,A=this.get_row_height();for(var D=0,F=E.length;D<F;D++){var M=E[D],C=M[0],y=M[1],z=M[2],I=(G&&G[C]!==undefined?G[C]:null);if((y<L&&z>H)&&(this.mode=="Dense"||I!==null)){this.draw_element(K,this.mode,M,I,H,L,N,A,B)}}K.restore()},draw_element:function(E,A,G,C,B,D,F,z,y){console.log("WARNING: Unimplemented function.")}});var d=10,j=3,m=5,w=10,f=1,s=3,e=3,a=9,l=2,h="#ccc";var r=function(B,D,y,A,C,z){o.call(this,B,D,y,A,C,z)};u(r.prototype,o.prototype,{get_row_height:function(){var z=this.mode,y;if(z==="Dense"){y=d}else{if(z==="no_detail"){y=j}else{if(z==="Squish"){y=m}else{y=w}}}return y},draw_element:function(K,D,S,F,M,ac,ag,ah,y){var P=S[0],ae=S[1],W=S[2],N=S[3],X=Math.floor(Math.max(0,(ae-M)*ag)),L=Math.ceil(Math.min(y,Math.max(0,(W-M)*ag))),V=(D==="Dense"?0:(0+F))*ah,J,aa,O=null,ai=null,B=this.prefs.block_color,Z=this.prefs.label_color;K.globalAlpha=this.alpha_generator.gen_alpha(S);if(D=="Dense"){F=1}if(D==="no_detail"){K.fillStyle=B;K.fillRect(X,V+5,L-X,f)}else{var I=S[4],U=S[5],Y=S[6],C=S[7];if(U&&Y){O=Math.floor(Math.max(0,(U-M)*ag));ai=Math.ceil(Math.min(y,Math.max(0,(Y-M)*ag)))}var af,Q;if(D==="Squish"||D==="Dense"){af=1;Q=e}else{af=5;Q=a}if(!C){if(S.strand){if(S.strand==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand_inv")}else{if(S.strand==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand_inv")}}}else{K.fillStyle=B}K.fillRect(X,V,L-X,Q)}else{var H,R;if(D==="Squish"||D==="Dense"){K.fillStyle=h;H=V+Math.floor(e/2)+1;R=1}else{if(I){var H=V;var R=Q;if(I==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand")}else{if(I==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand")}}}else{K.fillStyle=h;H+=(e/2)+1;R=1}}K.fillRect(X,H,L-X,R);for(var ad=0,A=C.length;ad<A;ad++){var E=C[ad],z=Math.floor(Math.max(0,(E[0]-M)*ag)),T=Math.ceil(Math.min(y,Math.max((E[1]-M)*ag)));if(z>T){continue}K.fillStyle=B;K.fillRect(z,V+(Q-af)/2+1,T-z,af);if(O!==undefined&&Y>U&&!(z>ai||T<O)){var ab=Math.max(z,O),G=Math.min(T,ai);K.fillRect(ab,V+1,G-ab,Q);if(C.length==1&&D=="Pack"){if(I==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand_inv")}else{if(I==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand_inv")}}if(ab+14<G){ab+=2;G-=2}K.fillRect(ab,V+1,G-ab,Q)}}}}if(D==="Pack"&&ae>M){K.fillStyle=Z;if(M===0&&X-K.measureText(N).width<0){K.textAlign="left";K.fillText(N,L+l,V+8)}else{K.textAlign="right";K.fillText(N,X-l,V+8)}}}K.globalAlpha=1}});var b=function(B,D,y,A,C,z){o.call(this,B,D,y,A,C,z)};u(b.prototype,o.prototype,{draw_element:function(R,M,G,C,U,A,J,S,P){var G=data[i],I=G[0],Q=G[1],B=G[2],L=G[3],E=Math.floor(Math.max(0,(Q-U)*J)),H=Math.ceil(Math.min(P,Math.max(0,(B-U)*J))),D=(M==="Dense"?0:(0+C))*S,y,V,z=null,K=null;if(no_label){R.fillStyle=block_color;R.fillRect(E+left_offset,D+5,H-E,1)}else{var T=G[4],O=G[5],F=G[6];y=9;V=1;R.fillRect(E+left_offset,D,H-E,y);if(M!=="Dense"&&L!==undefined&&Q>U){R.fillStyle=label_color;if(U===0&&E-R.measureText(L).width<0){R.textAlign="left";R.fillText(L,H+2+left_offset,D+8)}else{R.textAlign="right";R.fillText(L,E-2+left_offset,D+8)}R.fillStyle=block_color}var N=T+" / "+O;if(Q>U&&R.measureText(N).width<(H-E)){R.fillStyle="white";R.textAlign="center";R.fillText(N,left_offset+E+(H-E)/2,D+8);R.fillStyle=block_color}}}});var t=function(C,E,y,B,D,z,A){o.call(this,C,E,y,B,D,z);this.ref_seq=A};t.prototype.default_prefs=u({},o.prototype.default_prefs,{show_insertions:false});u(t.prototype,o.prototype,{get_row_height:function(){var y,z=this.mode;if(z==="Dense"){y=d}else{if(z==="Squish"){y=m}else{y=w;if(this.prefs.show_insertions){y*=2}}}return y},draw_read:function(U,P,L,Z,A,T,I,F,E){U.textAlign="center";var S=this,z=[Z,A],O=0,V=0,R=0;ref_seq=this.ref_seq,char_width_px=U.canvas.manager.char_width_px;var ae=[];if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){R=Math.round(L/2)}if(!I){I=[[0,F.length]]}for(var M=0,X=I.length;M<X;M++){var J=I[M],B="MIDNSHP=X"[J[0]],N=J[1];if(B==="H"||B==="S"){O-=N}var G=T+O,ad=Math.floor(Math.max(0,(G-Z)*L)),H=Math.floor(Math.max(0,(G+N-Z)*L));if(ad===H){H+=1}switch(B){case"H":break;case"S":case"M":case"=":if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(R>0){U.fillStyle=this.prefs.block_color;U.fillRect(ad-R,E+1,H-ad,9);U.fillStyle=h;for(var ab=0,y=Q.length;ab<y;ab++){if(this.prefs.show_differences&&ref_seq){var K=ref_seq[G-Z+ab];if(!K||K.toLowerCase()===Q[ab].toLowerCase()){continue}}if(G+ab>=Z&&G+ab<=A){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac,E+9)}}}else{U.fillStyle=this.prefs.block_color;U.fillRect(ad,E+4,H-ad,e)}}V+=N;O+=N;break;case"N":U.fillStyle=h;U.fillRect(ad-R,E+5,H-ad,1);O+=N;break;case"D":U.fillStyle="red";U.fillRect(ad-R,E+4,H-ad,3);O+=N;break;case"P":break;case"I":var Y=ad-R;if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(this.prefs.show_insertions){var D=ad-(H-ad)/2;if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){U.fillStyle="yellow";U.fillRect(D-R,E-9,H-ad,9);ae[ae.length]={type:"triangle",data:[Y,E+4,5]};U.fillStyle=h;switch(seq_tile_overlap){case (OVERLAP_START):Q=Q.slice(Z-G);break;case (OVERLAP_END):Q=Q.slice(0,G-A);break;case (CONTAINED_BY):break;case (CONTAINS):Q=Q.slice(Z-G,G-A);break}for(var ab=0,y=Q.length;ab<y;ab++){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac-(H-ad)/2,E)}}else{U.fillStyle="yellow";U.fillRect(D,E+(this.mode!=="Dense"?2:5),H-ad,(P!=="Dense"?e:s))}}else{if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){ae[ae.length]={type:"text",data:[Q.length,Y,E+9]}}else{}}}V+=N;break;case"X":V+=N;break}}U.fillStyle="yellow";var aa,C,af;for(var W=0;W<ae.length;W++){aa=ae[W];C=aa.type;af=aa.data;if(C==="text"){U.save();U.font="bold "+U.font;U.fillText(af[0],af[1],af[2]);U.restore()}else{if(C=="triangle"){q(U,af[0],af[1],af[2])}}}},draw_element:function(R,M,E,B,U,z,I,S,P){var H=E[0],Q=E[1],A=E[2],J=E[3],D=Math.floor(Math.max(0,(Q-U)*I)),F=Math.ceil(Math.min(P,Math.max(0,(A-U)*I))),C=(M==="Dense"?0:(0+B))*S,V=this.prefs.block_color,G=this.prefs.label_color,O=0;if((M==="Pack"||this.mode==="Auto")&&I>R.canvas.manager.char_width_px){var O=Math.round(I/2)}R.fillStyle=V;if(E[5] instanceof Array){var N=Math.floor(Math.max(0,(E[4][0]-U)*I)),L=Math.ceil(Math.min(P,Math.max(0,(E[4][1]-U)*I))),K=Math.floor(Math.max(0,(E[5][0]-U)*I)),y=Math.ceil(Math.min(P,Math.max(0,(E[5][1]-U)*I)));if(E[4][1]>=U&&E[4][0]<=z&&E[4][2]){this.draw_read(R,M,I,U,z,E[4][0],E[4][2],E[4][3],C)}if(E[5][1]>=U&&E[5][0]<=z&&E[5][2]){this.draw_read(R,M,I,U,z,E[5][0],E[5][2],E[5][3],C)}if(K>L){R.fillStyle=h;p(R,L-O,C+5,K-O,C+5)}}else{R.fillStyle=V;this.draw_read(R,M,I,U,z,Q,E[4],E[5],C)}if(M==="Pack"&&Q>U){R.fillStyle=this.prefs.label_color;var T=1;if(T===0&&D-R.measureText(J).width<0){R.textAlign="left";R.fillText(J,F+l-O,C+8)}else{R.textAlign="right";R.fillText(J,D-l-O,C+8)}R.fillStyle=V}}});x.AlphaGenerator=g;x.SummaryTreePainter=v;x.LinePainter=c;x.LinkedFeaturePainter=r;x.ReadPainter=t;x.VariantPainter=b};(function(d){var c={};var b=function(e){return c[e]};var a=function(f,g){var e={};g(b,e);c[f]=e};a("class",class_module);a("slotting",slotting_module);a("painters",painters_module);a("trackster",trackster_module);for(key in c.trackster){d[key]=c.trackster[key]}})(window);
\ No newline at end of file
+var class_module=function(b,a){var c=function(){var f=arguments[0];for(var e=1;e<arguments.length;e++){var d=arguments[e];for(key in d){f[key]=d[key]}}return f};a.extend=c};var requestAnimationFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b,a){window.setTimeout(b,1000/60)}})();var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=BEFORE}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var trackster_module=function(f,W){var p=f("class").extend,r=f("slotting"),K=f("painters");var ad=function(ae,af){this.document=ae;this.default_font=af!==undefined?af:"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")};p(ad.prototype,{load_pattern:function(ae,ai){var af=this.patterns,ag=this.dummy_context,ah=new Image();ah.src=image_path+ai;ah.onload=function(){af[ae]=ag.createPattern(ah,"repeat")}},get_pattern:function(ae){return this.patterns[ae]},new_canvas:function(){var ae=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(ae)}ae.manager=this;return ae}});var m=function(ae,ag,ah){ah=".group";var af={};ae.bind("drag",{handle:"."+ag,relative:true},function(an,ao){var aq=$(this).parent(),al=aq.children(),ak,aj,ap,ai,am;aj=$(this).parents(ah);if(aj.length!==0){ap=aj.position().top;ai=ap+aj.outerHeight();if(ao.offsetY<ap){$(this).insertBefore(aj);return}else{if(ao.offsetY>ai){$(this).insertAfter(aj);return}}}aj=null;for(am=0;am<al.length;am++){ak=$(al.get(am));ap=ak.position().top;ai=ap+ak.outerHeight();if(ak.is(ah)&&this!==ak.get(0)&&ao.offsetY>=ap&&ao.offsetY<=ai){if(ao.offsetY-ap<ai-ao.offsetY){ak.find(".content-div").prepend(this)}else{ak.find(".content-div").append(this)}return}}for(am=0;am<al.length;am++){if(ao.offsetY<$(al.get(am)).position().top){break}}if(am===al.length){if(this!==al.get(am-1)){aq.append(this)}}else{if(this!==al.get(am)){$(this).insertBefore(al.get(am))}}}).bind("dragstart",function(){af["border-top"]=ae.css("border-top");af["border-bottom"]=ae.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(af)})};W.moveable=m;var ac=16,F=9,D=20,R=F+2,z=100,H=12000,P=200,C=5,u=10,J=5000,v=100,n="There was an error in indexing this dataset. ",I="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",s="Currently indexing... please wait",x="Tool cannot be rerun: ",a="Loading data...",X="Ready for display",d=10,t=5,B=5;function w(ae){return Math.round(ae*1000)/1000}var c=function(ae){this.num_elements=ae;this.clear()};p(c.prototype,{get:function(af){var ae=this.key_ary.indexOf(af);if(ae!==-1){if(this.obj_cache[af].stale){this.key_ary.splice(ae,1);delete this.obj_cache[af]}else{this.move_key_to_end(af,ae)}}return this.obj_cache[af]},set:function(af,ag){if(!this.obj_cache[af]){if(this.key_ary.length>=this.num_elements){var ae=this.key_ary.shift();delete this.obj_cache[ae]}this.key_ary.push(af)}this.obj_cache[af]=ag;return ag},move_key_to_end:function(af,ae){this.key_ary.splice(ae,1);this.key_ary.push(af)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var Q=function(af,ae,ag){c.call(this,af);this.track=ae;this.subset=(ag!==undefined?ag:true)};p(Q.prototype,c.prototype,{load_data:function(an,ai,al,af,ak){var am=this.track.view.chrom,ah={chrom:am,low:an,high:ai,mode:al,resolution:af,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(ah,ak);if(this.track.filters_manager){var ao=[];var ae=this.track.filters_manager.filters;for(var aj=0;aj<ae.length;aj++){ao[ao.length]=ae[aj].name}ah.filter_cols=JSON.stringify(ao)}var ag=this;return $.getJSON(this.track.data_url,ah,function(ap){ag.set_data(an,ai,al,ap)})},get_data:function(ae,ai,aj,af,ah){var ag=this.get_data_from_cache(ae,ai,aj);if(ag){return ag}ag=this.load_data(ae,ai,aj,af,ah);this.set_data(ae,ai,aj,ag);return ag},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(am,ah,al,ag,ak,ai){var an=this.get_data_from_cache(am,ah,al);if(!an){console.log("ERROR: no current data for: ",this.track,am,ah,al,ag,ak);return}an.stale=true;var af=am;if(ai===this.DEEP_DATA_REQ){$.extend(ak,{start_val:an.data.length+1})}else{if(ai===this.BROAD_DATA_REQ){af=(an.max_high?an.max_high:an.data[an.data.length-1][2])+1}}var ae=this,aj=this.load_data(af,ah,al,ag,ak);new_data_available=$.Deferred();this.set_data(am,ah,al,new_data_available);$.when(aj).then(function(ao){if(ao.data){ao.data=an.data.concat(ao.data);if(ao.max_low){ao.max_low=an.max_low}if(ao.message){ao.message=ao.message.replace(/[0-9]+/,ao.data.length)}}ae.set_data(am,ah,al,ao);new_data_available.resolve(ao)});return new_data_available},get_data_from_cache:function(ae,af,ag){return this.get(this.gen_key(ae,af,ag))},set_data:function(af,ag,ah,ae){return this.set(this.gen_key(af,ag,ah),ae)},gen_key:function(ae,ag,ah){var af=ae+"_"+ag+"_"+ah;return af},split_key:function(ae){return ae.split("_")}});var G=function(af,ae,ag){Q.call(this,af,ae,ag)};p(G.prototype,Q.prototype,c.prototype,{load_data:function(ag,ae,ai,aj,af,ah){if(af>1){return}return Q.prototype.load_data.call(this,ag,ae,ai,aj,af,ah)}});var ab=function(ae,ah,ag,af,ai){this.container=ae;this.chrom=null;this.vis_id=ag;this.dbkey=af;this.title=ah;this.tracks=[];this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init(ai);this.canvas_manager=new ad(ae.get(0).ownerDocument);this.reset()};p(ab.prototype,{init:function(ai){var ag=this.container,ae=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ag);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ag);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ag);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var ah=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_tracks()});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var af=function(aj){if(aj.type==="focusout"||(aj.keyCode||aj.which)===13||(aj.keyCode||aj.which)===27){if((aj.keyCode||aj.which)!==27){ae.go_to($(this).val())}$(this).hide();$(this).val("");ae.location_span.show();ae.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",af).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.click(function(){ae.location_span.hide();ae.chrom_select.hide();ae.nav_input.val(ae.chrom+":"+ae.low+"-"+ae.high);ae.nav_input.css("display","inline-block");ae.nav_input.select();ae.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a id='zoom-out' />").click(function(){ae.zoom_out();ae.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){ae.zoom_in();ae.request_redraw()}).appendTo(this.nav_controls);this.load_chroms({low:0},ai);this.chrom_select.bind("change",function(){ae.change_chrom(ae.chrom_select.val())});this.content_div.click(function(aj){$(this).find("input").trigger("blur")});this.content_div.bind("dblclick",function(aj){ae.zoom_in(aj.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(aj,ak){this.current_x=ak.offsetX}).bind("drag",function(aj,al){var am=al.offsetX-this.current_x;this.current_x=al.offsetX;var ak=Math.round(am/ae.viewport_container.width()*(ae.max_high-ae.max_low));ae.move_delta(-ak)});this.overview_close.click(function(){ae.reset_overview()});this.viewport_container.bind("draginit",function(aj,ak){if(aj.clientX>ae.viewport_container.width()-16){return false}}).bind("dragstart",function(aj,ak){ak.original_low=ae.low;ak.current_height=aj.clientY;ak.current_x=ak.offsetX}).bind("drag",function(al,an){var aj=$(this);var ao=an.offsetX-an.current_x;var ak=aj.scrollTop()-(al.clientY-an.current_height);aj.scrollTop(ak);an.current_height=al.clientY;an.current_x=an.offsetX;var am=Math.round(ao/ae.viewport_container.width()*(ae.high-ae.low));ae.move_delta(am)}).bind("mousewheel",function(al,an,ak,aj){if(ak){var am=Math.round(-ak/ae.viewport_container.width()*(ae.high-ae.low));ae.move_delta(am)}});this.top_labeltrack.bind("dragstart",function(aj,ak){return $("<div />").css({height:ae.content_div.height()+ae.top_labeltrack.height()+ae.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(an,ao){$(ao.proxy).css({left:Math.min(an.pageX,ao.startX),width:Math.abs(an.pageX-ao.startX)});var ak=Math.min(an.pageX,ao.startX)-ae.container.offset().left,aj=Math.max(an.pageX,ao.startX)-ae.container.offset().left,am=(ae.high-ae.low),al=ae.viewport_container.width();ae.update_location(Math.round(ak/al*am)+ae.low,Math.round(aj/al*am)+ae.low)}).bind("dragend",function(ao,ap){var ak=Math.min(ao.pageX,ap.startX),aj=Math.max(ao.pageX,ap.startX),am=(ae.high-ae.low),al=ae.viewport_container.width(),an=ae.low;ae.low=Math.round(ak/al*am)+an;ae.high=Math.round(aj/al*am)+an;$(ap.proxy).remove();ae.request_redraw()});this.add_label_track(new aa(this,this.top_labeltrack));this.add_label_track(new aa(this,this.nav_labeltrack));$(window).bind("resize",function(){ae.resize_window()});$(document).bind("redraw",function(){ae.redraw()});this.reset();$(window).trigger("resize");this.update_intro_div()},update_intro_div:function(){if(this.num_tracks===0){this.intro_div.show()}else{this.intro_div.hide()}},update_location:function(ae,af){this.location_span.text(commatize(ae)+" - "+commatize(af));this.nav_input.val(this.chrom+":"+commatize(ae)+"-"+commatize(af))},load_chroms:function(af,ag){af.num=v;$.extend(af,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var ae=this;$.ajax({url:chrom_url,data:af,dataType:"json",success:function(ai){if(ai.chrom_info.length===0){alert("Invalid chromosome: "+af.chrom);return}if(ai.reference){ae.add_label_track(new A(ae))}ae.chrom_data=ai.chrom_info;var al='<option value="">Select Chrom/Contig</option>';for(var ak=0,ah=ae.chrom_data.length;ak<ah;ak++){var aj=ae.chrom_data[ak].chrom;al+='<option value="'+aj+'">'+aj+"</option>"}if(ai.prev_chroms){al+='<option value="previous">Previous '+v+"</option>"}if(ai.next_chroms){al+='<option value="next">Next '+v+"</option>"}ae.chrom_select.html(al);if(ag){ag()}ae.chrom_start_index=ai.start_index},error:function(){alert("Could not load chroms for this dbkey:",ae.dbkey)}})},change_chrom:function(ai,af,ak){if(!ai||ai==="None"){return}var ah=this;if(ai==="previous"){ah.load_chroms({low:this.chrom_start_index-v});return}if(ai==="next"){ah.load_chroms({low:this.chrom_start_index+v});return}var aj=$.grep(ah.chrom_data,function(am,an){return am.chrom===ai})[0];if(aj===undefined){ah.load_chroms({chrom:ai},function(){ah.change_chrom(ai,af,ak)});return}else{if(ai!==ah.chrom){ah.chrom=ai;ah.chrom_select.val(ah.chrom);ah.max_high=aj.len-1;ah.reset();ah.request_redraw(true);for(var al=0,ae=ah.tracks.length;al<ae;al++){var ag=ah.tracks[al];if(ag.init){ag.init()}}}if(af!==undefined&&ak!==undefined){ah.low=Math.max(af,0);ah.high=Math.min(ak,ah.max_high)}ah.reset_overview();ah.request_redraw()}},go_to:function(ai){var am=this,ae,ah,af=ai.split(":"),ak=af[0],al=af[1];if(al!==undefined){try{var aj=al.split("-");ae=parseInt(aj[0].replace(/,/g,""),10);ah=parseInt(aj[1].replace(/,/g,""),10)}catch(ag){return false}}am.change_chrom(ak,ae,ah)},move_fraction:function(ag){var ae=this;var af=ae.high-ae.low;this.move_delta(ag*af)},move_delta:function(ag){var ae=this;var af=ae.high-ae.low;if(ae.low-ag<ae.max_low){ae.low=ae.max_low;ae.high=ae.max_low+af}else{if(ae.high-ag>ae.max_high){ae.high=ae.max_high;ae.low=ae.max_high-af}else{ae.high-=ag;ae.low-=ag}}ae.request_redraw()},add_track:function(ae){ae.view=this;ae.track_id=this.track_id_counter;this.tracks.push(ae);if(ae.init){ae.init()}ae.container_div.attr("id","track_"+ae.track_id);m(ae.container_div,ae.drag_handle_class);this.track_id_counter+=1;this.num_tracks+=1;this.has_changes=true;this.update_intro_div()},add_label_track:function(ae){ae.view=this;this.label_tracks.push(ae)},remove_track:function(af){this.has_changes=true;this.tracks.splice(this.tracks.indexOf(af),1);this.num_tracks-=1;var ae=this;af.container_div.fadeOut("slow",function(){$(this).remove();ae.update_intro_div()})},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(am,ae,al,af){var ak=this,ai=(af?[af]:ak.tracks),ag;var af;for(var aj=0;aj<ai.length;aj++){af=ai[aj];ag=-1;for(var ah=0;ah<ak.tracks_to_be_redrawn.length;ah++){if(ak.tracks_to_be_redrawn[ah][0]===af){ag=ah;break}}if(ag<0){ak.tracks_to_be_redrawn.push([af,ae,al])}else{ak.tracks_to_be_redrawn[aj][1]=ae;ak.tracks_to_be_redrawn[aj][2]=al}}requestAnimationFrame(function(){ak._redraw(am)})},_redraw:function(ao){var al=this.low,ah=this.high;if(al<this.max_low){al=this.max_low}if(ah>this.max_high){ah=this.max_high}var an=this.high-this.low;if(this.high!==0&&an<this.min_separation){ah=al+this.min_separation}this.low=Math.floor(al);this.high=Math.ceil(ah);this.resolution=Math.pow(C,Math.ceil(Math.log((this.high-this.low)/P)/Math.log(C)));this.zoom_res=Math.pow(u,Math.max(0,Math.ceil(Math.log(this.resolution,u)/Math.log(u))));var ae=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ak=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ap=13;this.overview_box.css({left:ae,width:Math.max(ap,ak)}).show();if(ak<ap){this.overview_box.css("left",ae-(ap-ak)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ae,width:ak})}this.update_location(this.low,this.high);if(!ao){var ag,af,am;for(var ai=0,aj=this.tracks_to_be_redrawn.length;ai<aj;ai++){ag=this.tracks_to_be_redrawn[ai][0];af=this.tracks_to_be_redrawn[ai][1];am=this.tracks_to_be_redrawn[ai][2];if(ag&&ag.enabled){ag._draw(af,am)}}this.tracks_to_be_redrawn=[];for(ai=0,aj=this.label_tracks.length;ai<aj;ai++){this.label_tracks[ai]._draw()}}},zoom_in:function(af,ag){if(this.max_high===0||this.high-this.low<this.min_separation){return}var ah=this.high-this.low,ai=ah/2+this.low,ae=(ah/this.zoom_factor)/2;if(af){ai=af/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ai-ae);this.high=Math.round(ai+ae);this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var af=this.high-this.low,ag=af/2+this.low,ae=(af*this.zoom_factor)/2;this.low=Math.round(ag-ae);this.high=Math.round(ag+ae);this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.request_redraw()},set_overview:function(ae){$.when(ae.get_overview_tile()).then(function(af){view.overview_viewport.find(".track-tile").remove();view.overview_close.show();view.overview_viewport.append(af.canvas);view.overview_highlight.show().height(af.canvas.height());view.overview_viewport.height(af.canvas.height()+view.overview_box.outerHeight());view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=ae;ae.set_is_overview(true)});view.has_changes=true},reset_overview:function(){this.overview_viewport.find(".track-tile").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide();view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=null}});var q=function(ag,ak){this.track=ag;this.name=ak.name;this.params=[];var ar=ak.params;for(var ah=0;ah<ar.length;ah++){var am=ar[ah],af=am.name,aq=am.label,ai=unescape(am.html),at=am.value,ao=am.type;if(ao==="number"){this.params[this.params.length]=new g(af,aq,ai,at,am.min,am.max)}else{if(ao=="select"){this.params[this.params.length]=new M(af,aq,ai,at)}else{console.log("WARNING: unrecognized tool parameter type:",af,ao)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(av){av.stopPropagation()}).click(function(av){av.stopPropagation()}).bind("dblclick",function(av){av.stopPropagation()});var ap=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var an=this.params;var al=this;$.each(this.params,function(aw,az){var ay=$("<div>").addClass("param-row").appendTo(al.parent_div);var av=$("<div>").addClass("param-label").text(az.label).appendTo(ay);var ax=$("<div/>").addClass("slider").html(az.html).appendTo(ay);ax.find(":input").val(az.value);$("<div style='clear: both;'/>").appendTo(ay)});this.parent_div.find("input").click(function(){$(this).select()});var au=$("<div>").addClass("param-row").appendTo(this.parent_div);var aj=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(au);var ae=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(au);var al=this;ae.click(function(){al.run_on_region()});aj.click(function(){al.run_on_dataset()})};p(q.prototype,{get_param_values_dict:function(){var ae={};this.parent_div.find(":input").each(function(){var af=$(this).attr("name"),ag=$(this).val();ae[af]=JSON.stringify(ag)});return ae},get_param_values:function(){var af=[];var ae={};this.parent_div.find(":input").each(function(){var ag=$(this).attr("name"),ah=$(this).val();if(ag){af[af.length]=ah}});return af},run_on_dataset:function(){var ae=this;ae.run({dataset_id:this.track.original_dataset_id,tool_id:ae.name},null,function(af){show_modal(ae.name+" is Running",ae.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ae={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},ag=this.track,af=ae.tool_id+ag.tool_region_and_parameters_str(ae.chrom,ae.low,ae.high),ah;if(ag instanceof e){ah=new T(af,view,ag.hda_ldda,undefined,{},{},ag);ah.change_mode(ag.mode)}this.track.view.add_track(ah);ah.content_div.text("Starting job.");this.run(ae,ah,function(ai){ah.dataset_id=ai.dataset_id;ah.content_div.text("Running job.");ah.init()})},run:function(af,ag,ah){$.extend(af,this.get_param_values_dict());var ae=function(){$.getJSON(rerun_tool_url,af,function(ai){if(ai==="no converter"){ag.container_div.addClass("error");ag.content_div.text(I)}else{if(ai.error){ag.container_div.addClass("error");ag.content_div.text(x+ai.message)}else{if(ai==="pending"){ag.container_div.addClass("pending");ag.content_div.text("Converting input data so that it can be used quickly with tool.");setTimeout(ae,2000)}else{ah(ai)}}}})};ae()}});var M=function(af,ae,ag,ah){this.name=af;this.label=ae;this.html=ag;this.value=ah};var g=function(ag,af,ai,aj,ah,ae){M.call(this,ag,af,ai,aj);this.min=ah;this.max=ae};var h=function(af,ae,ag,ah){this.name=af;this.index=ae;this.tool_id=ag;this.tool_exp_name=ah};var U=function(af,ae,ag,ah){h.call(this,af,ae,ag,ah);this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.min=Number.MAX_VALUE;this.max=-Number.MAX_VALUE;this.container=null;this.slider=null;this.slider_label=null};p(U.prototype,{applies_to:function(ae){if(ae.length>this.index){return true}return false},keep:function(ae){if(!this.applies_to(ae)){return true}var af=parseFloat(ae[this.index]);return(isNaN(af)||(af>=this.low&&af<=this.high))},update_attrs:function(af){var ae=false;if(!this.applies_to(af)){return ae}if(af[this.index]<this.min){this.min=Math.floor(af[this.index]);ae=true}if(af[this.index]>this.max){this.max=Math.ceil(af[this.index]);ae=true}return ae},update_ui_elt:function(){if(this.min!=this.max){this.container.show()}else{this.container.hide()}var ag=function(aj,ah){var ai=ah-aj;return(ai<=2?0.01:1)};var af=this.slider.slider("option","min"),ae=this.slider.slider("option","max");if(this.min<af||this.max>ae){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",ag(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var Z=function(ao,av){this.track=ao;this.filters=[];for(var ap=0;ap<av.length;ap++){var aq=av[ap],aw=aq.name,ae=aq.type,ah=aq.index,au=aq.tool_id,at=aq.tool_exp_name;if(ae==="int"||ae==="float"){this.filters[ap]=new U(aw,ah,au,at)}else{console.log("ERROR: unsupported filter: ",aw,ae)}}var ai=function(ax,ay,az){ax.click(function(){var aA=ay.text();max=parseFloat(az.slider("option","max")),input_size=(max<=1?4:max<=1000000?max.toString().length:6),multi_value=false;if(az.slider("option","values")){input_size=2*input_size+1;multi_value=true}ay.text("");$("<input type='text'/>").attr("size",input_size).attr("maxlength",input_size).attr("value",aA).appendTo(ay).focus().select().click(function(aB){aB.stopPropagation()}).blur(function(){$(this).remove();ay.text(aA)}).keyup(function(aF){if(aF.keyCode===27){$(this).trigger("blur")}else{if(aF.keyCode===13){var aD=az.slider("option","min"),aB=az.slider("option","max"),aE=function(aG){return(isNaN(aG)||aG>aB||aG<aD)},aC=$(this).val();if(!multi_value){aC=parseFloat(aC);if(aE(aC)){alert("Parameter value must be in the range ["+aD+"-"+aB+"]");return $(this)}}else{aC=aC.split("-");aC=[parseFloat(aC[0]),parseFloat(aC[1])];if(aE(aC[0])||aE(aC[1])){alert("Parameter value must be in the range ["+aD+"-"+aB+"]");return $(this)}}az.slider((multi_value?"values":"value"),aC)}}})})};this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(ax){ax.stopPropagation()}).click(function(ax){ax.stopPropagation()}).bind("dblclick",function(ax){ax.stopPropagation()}).bind("keydown",function(ax){ax.stopPropagation()});var ar=$("<div/>").addClass("sliders").appendTo(this.parent_div);var am=this;$.each(this.filters,function(aA,aC){aC.container=$("<div/>").addClass("slider-row").appendTo(ar);var aB=$("<div/>").addClass("elt-label").appendTo(aC.container);var az=$("<span/>").addClass("slider-name").text(aC.name+" ").appendTo(aB);var ay=$("<span/>");var aE=$("<span/>").addClass("slider-value").appendTo(aB).append("[").append(ay).append("]");var ax=$("<div/>").addClass("slider").appendTo(aC.container);aC.control_element=$("<div/>").attr("id",aC.name+"-filter-control").appendTo(ax);var aD=[0,0];aC.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(aG,aH){var aF=aH.values;ay.text(aF[0]+"-"+aF[1]);aC.low=aF[0];aC.high=aF[1];am.track.request_draw(true,true)},change:function(aF,aG){aC.control_element.slider("option","slide").call(aC.control_element,aF,aG)}});aC.slider=aC.control_element;aC.slider_label=ay;ai(aE,ay,aC.control_element);$("<div style='clear: both;'/>").appendTo(aC.container)});if(this.filters.length!==0){var aj=$("<div/>").addClass("param-row").appendTo(ar);var al=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(aj);var ag=this;al.click(function(){ag.run_on_dataset()})}var an=$("<div/>").addClass("display-controls").appendTo(this.parent_div),ak=$("<span/>").addClass("elt-label").text("Transparency:").appendTo(an),af=$("<select/>").attr("name","alpha_dropdown").appendTo(an);this.alpha_filter=null;$("<option/>").attr("value",-1).text("== None ==").appendTo(af);for(var ap=0;ap<this.filters.length;ap++){$("<option/>").attr("value",ap).text(this.filters[ap].name).appendTo(af)}af.change(function(){$(this).children("option:selected").each(function(){var ax=parseInt($(this).val());am.alpha_filter=(ax>=0?am.filters[ax]:null);am.track.request_draw(true,true)})});$("<div style='clear: both;'/>").appendTo(this.parent_div)};p(Z.prototype,{reset_filters:function(){for(var ae=0;ae<this.filters.length;ae++){filter=this.filters[ae];filter.slider.slider("option","values",[filter.min,filter.max])}this.alpha_filter=null},run_on_dataset:function(){var am=function(aq,ao,ap){if(!(ao in aq)){aq[ao]=ap}return aq[ao]};var ag={},ae,af,ah;for(var ai=0;ai<this.filters.length;ai++){ae=this.filters[ai];if(ae.tool_id){if(ae.min!=ae.low){af=am(ag,ae.tool_id,[]);af[af.length]=ae.tool_exp_name+" >= "+ae.low}if(ae.max!=ae.high){af=am(ag,ae.tool_id,[]);af[af.length]=ae.tool_exp_name+" <= "+ae.high}}}var ak=[];for(var an in ag){ak[ak.length]=[an,ag[an]]}var al=ak.length;(function aj(av,ar){var ap=ar[0],aq=ap[0],au=ap[1],at="("+au.join(") and (")+")",ao={cond:at,input:av,target_dataset_id:av,tool_id:aq},ar=ar.slice(1);$.getJSON(run_tool_url,ao,function(aw){if(aw.error){show_modal("Filter Dataset","Error running tool "+aq,{Close:hide_modal})}else{if(ar.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{aj(aw.dataset_id,ar)}}})})(this.track.dataset_id,ak)}});var N=function(af,ae){K.AlphaGenerator.call(this,ae);this.filter=af};N.prototype.gen_alpha=function(ae){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_alpha}return((parseFloat(ae[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var Y=function(ae){this.track=ae.track;this.params=ae.params;this.values={};if(ae.saved_values){this.restore_values(ae.saved_values)}this.onchange=ae.onchange};p(Y.prototype,{restore_values:function(ae){var af=this;$.each(this.params,function(ag,ah){if(ae[ah.key]!==undefined){af.values[ah.key]=ae[ah.key]}else{af.values[ah.key]=ah.default_value}})},build_form:function(){var af=this;var ae=$("<div />");$.each(this.params,function(aj,ah){if(!ah.hidden){var ag="param_"+aj;var al=af.values[ah.key];var ao=$("<div class='form-row' />").appendTo(ae);ao.append($("<label />").attr("for",ag).text(ah.label+":"));if(ah.type==="bool"){ao.append($('<input type="checkbox" />').attr("id",ag).attr("name",ag).attr("checked",al))}else{if(ah.type==="text"){ao.append($('<input type="text"/>').attr("id",ag).val(al).click(function(){$(this).select()}))}else{if(ah.type==="color"){var ak=$("<input />").attr("id",ag).attr("name",ag).val(al);var am=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var ai=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(am);var an=$("<div/>").appendTo(ai).farbtastic({width:100,height:100,callback:ak,color:al});$("<div />").append(ak).append(am).appendTo(ao).bind("click",function(ap){am.css({left:$(this).position().left+($(ak).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){am.hide();$(document).unbind("click.color-picker")});ap.stopPropagation()})}else{ao.append($("<input />").attr("id",ag).attr("name",ag).val(al))}}}}});return ae},update_from_form:function(ae){var ag=this;var af=false;$.each(this.params,function(ah,aj){if(!aj.hidden){var ak="param_"+ah;var ai=ae.find("#"+ak).val();if(aj.type==="float"){ai=parseFloat(ai)}else{if(aj.type==="int"){ai=parseInt(ai)}else{if(aj.type==="bool"){ai=ae.find("#"+ak).is(":checked")}}}if(ai!==ag.values[aj.key]){ag.values[aj.key]=ai;af=true}}});if(af){this.onchange()}}});var b=function(ag,af,ae,ah){this.index=ag;this.low=ag*P*af;this.high=(ag+1)*P*af;this.resolution=af;this.canvas=$("<div class='track-tile'/>").append(ae);this.data=ah;this.stale=false};var l=function(ag,af,ae,ah,ai){b.call(this,ag,af,ae,ah);this.max_val=ai};var O=function(ag,af,ae,ai,ah){b.call(this,ag,af,ae,ai);this.message=ah};var o=function(af,ae){this.name=af;this.view=ae;this.parent_element=ae.viewport_container};o.prototype.request_draw=function(){};o.prototype.draw=function(){};var y=function(af,ae){o.call(this,af,ae);this.members=[];this.drag_handle_class="group-handle";this.container_div=$("<div/>").addClass("group").appendTo(this.parent_element);this.container_div.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("group-name").text(this.name).appendTo(this.container_div);this.content_div=$("<div/>").addClass("content-div").appendTo(this.container_div)};p(y.prototype,o.prototype,{request_draw:function(af,ae){},draw:function(){}});var j=function(af,ae,ai,ag,ah){this.name=af;this.view=ae;this.parent_element=ai;this.data_url=(ag?ag:default_data_url);this.data_url_extra_params={};this.data_query_wait=(ah?ah:J);this.dataset_check_url=converted_datasets_state_url;this.drag_handle_class="draghandle";this.container_div=$("<div />").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)};p(j.prototype,{get_type:function(){if(this instanceof aa){return"LabelTrack"}else{if(this instanceof A){return"ReferenceTrack"}else{if(this instanceof k){return"LineTrack"}else{if(this instanceof V){return"ReadTrack"}else{if(this instanceof T){return"ToolDataFeatureTrack"}else{if(this instanceof S){return"VcfTrack"}else{if(this instanceof e){return"FeatureTrack"}}}}}}}return""},init:function(){var ae=this;ae.enabled=false;ae.tile_cache.clear();ae.data_manager.clear();ae.initial_canvas=undefined;ae.content_div.css("height","auto");ae.container_div.removeClass("nodata error pending");if(!ae.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:ae.hda_ldda,dataset_id:ae.dataset_id,chrom:ae.view.chrom},function(af){if(!af||af==="error"||af.kind==="error"){ae.container_div.addClass("error");ae.content_div.text(n);if(af.message){var ah=ae.view.tracks.indexOf(ae);var ag=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+af.message+"</pre>",{Close:hide_modal})});ae.content_div.append(ag)}}else{if(af==="no converter"){ae.container_div.addClass("error");ae.content_div.text(I)}else{if(af==="no data"||(af.data!==undefined&&(af.data===null||af.data.length===0))){ae.container_div.addClass("nodata");ae.content_div.text(E)}else{if(af==="pending"){ae.container_div.addClass("pending");ae.content_div.text(s);setTimeout(function(){ae.init()},ae.data_query_wait)}else{if(af.status==="data"){if(af.valid_chroms){ae.valid_chroms=af.valid_chroms;ae.make_name_popup_menu()}ae.content_div.text(X);if(ae.view.chrom){ae.content_div.text("");ae.content_div.css("height",ae.height_px+"px");ae.enabled=true;$.when(ae.predraw_init()).done(function(){ae.container_div.removeClass("nodata error pending");ae.request_draw()})}}}}}}})},predraw_init:function(){},set_name:function(ae){this.old_name=this.name;this.name=ae;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)}});var L=function(al,aj,am){var af=this,an=af.view;this.filters_manager=(al!==undefined?new Z(this,al):undefined);this.filters_available=false;this.filters_visible=false;this.tool=(aj!==undefined&&obj_length(aj)>0?new q(this,aj):undefined);this.is_overview=false;this.parent_track=am;this.child_tracks=[];if(af.hidden){return}if(this.parent_track){this.header_div.find(".draghandle").removeClass("draghandle").addClass("child-track-icon").addClass("icon-button");this.parent_element.addClass("child-track");this.tool=undefined}af.child_tracks_container=$("<div/>").addClass("child-tracks-container").hide();af.container_div.append(af.child_tracks_container);if(this.filters_manager){this.filters_div=this.filters_manager.parent_div;this.header_div.after(this.filters_div)}if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}if(af.display_modes!==undefined){if(af.mode_div===undefined){af.mode_div=$("<div class='right-float menubutton popup' />").appendTo(af.header_div);var ag=(af.track_config&&af.track_config.values.mode?af.track_config.values.mode:af.display_modes[0]);af.mode=ag;af.mode_div.text(ag);var ae={};for(var ah=0,ak=af.display_modes.length;ah<ak;ah++){var ai=af.display_modes[ah];ae[ai]=function(ao){return function(){af.change_mode(ao)}}(ai)}make_popupmenu(af.mode_div,ae)}else{af.mode_div.hide()}}this.make_name_popup_menu()};p(L.prototype,j.prototype,{change_mode:function(af){var ae=this;ae.mode_div.text(af);ae.mode=af;ae.track_config.values.mode=af;ae.tile_cache.clear();ae.request_draw()},make_name_popup_menu:function(){var af=this;var ae={};ae[(this.is_overview?"Hide overview":"Set as overview")]=function(){if(af.is_overview){af.view.reset_overview()}else{af.view.set_overview(af)}};ae["Edit configuration"]=function(){var al=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},aj=function(){af.track_config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ak=function(am){if((am.keyCode||am.which)===27){al()}else{if((am.keyCode||am.which)===13){aj()}}};$(window).bind("keypress.check_enter_esc",ak);show_modal("Configure Track",af.track_config.build_form(),{Cancel:al,OK:aj})};if(af.filters_available>0){var ai=(af.filters_div.is(":visible")?"Hide filters":"Show filters");ae[ai]=function(){af.filters_visible=(af.filters_div.is(":visible"));if(af.filters_visible){af.filters_manager.reset_filters()}af.filters_div.toggle();af.make_name_popup_menu()}}if(af.tool){var ai=(af.dynamic_tool_div.is(":visible")?"Hide tool":"Show tool");ae[ai]=function(){if(!af.dynamic_tool_div.is(":visible")){af.set_name(af.name+af.tool_region_and_parameters_str())}else{menu_option_text="Show dynamic tool";af.revert_name()}af.dynamic_tool_div.toggle();af.make_name_popup_menu()}}if(af.valid_chroms){ae["List chrom/contigs with data"]=function(){show_modal("Chrom/contigs with data","<p>"+af.valid_chroms.join("<br/>")+"</p>",{Close:function(){hide_modal()}})}}var ag=view;var ah=function(){$("#no-tracks").show()};if(this.parent_track){ag=this.parent_track;ah=function(){}}ae.Remove=function(){ag.remove_track(af);if(ag.num_tracks===0){ah()}};make_popupmenu(af.name_div,ae)},set_is_overview:function(ae){this.is_overview=ae;this.make_name_popup_menu()},get_overview_tile:function(){var ae=this;view=ae.view,resolution=Math.pow(C,Math.ceil(Math.log((view.max_high-view.max_low)/P)/Math.log(C))),view_width=view.container.width(),w_scale=view_width/(view.max_high-view.max_low),overview_tile=$.Deferred();$.when(ae.data_manager.get_data(view.max_low,view.max_high,"Auto",resolution,ae.data_url_extra_params)).then(function(af){var ah=ae._gen_tile_cache_key(view_width,w_scale,0),aj=ae.tile_cache.get(ah);if(!aj){aj=ae.draw_tile(af,"Auto",resolution,0,w_scale);ae.tile_cache.set(ah,aj)}var am=$(aj.canvas.find("canvas")),ai=am.clone(),al=am.get(0).getContext("2d"),ag=ai.get(0).getContext("2d"),ak=al.getImageData(0,0,al.canvas.width,al.canvas.height);ag.putImageData(ak,-ae.left_offset,(aj.data.dataset_type==="summary_tree"?R:0));new_tile=new b(-1,resolution,ai);overview_tile.resolve(new_tile)});return overview_tile},_gen_tile_cache_key:function(af,ag,ae){return af+"_"+ag+"_"+ae},request_draw:function(af,ae){this.view.request_redraw(false,af,ae,this)},_draw:function(ag,ap){if(!this.dataset_id){return}var ao=this.view.low,ak=this.view.high,am=ak-ao,ah=this.view.container.width(),at=ah/am,aj=this.view.resolution,ar=$("<div style='position: relative;'></div>");if(!ap){this.content_div.children().remove()}this.content_div.append(ar);this.max_height=0;var af=Math.floor(ao/aj/P);var an=true;var aq=[];var ae=0;while((af*P*aj)<ak){tile=this.draw_helper(ag,ah,af,aj,ar,at);if(tile){aq.push(tile)}else{an=false}af+=1;ae++}var ai=this;if(an){ai.postdraw_actions(aq,ah,at,ap)}for(var al=0;al<this.child_tracks.length;al++){this.child_tracks[al].request_draw(ag,ap)}},postdraw_actions:function(ai,aj,ak,ae){var ag=this;var ah=false;for(var af=0;af<ai.length;af++){if(ai[af].message){ah=true;break}}if(ah){for(var af=0;af<ai.length;af++){tile=ai[af];if(!tile.message){tile.canvas.css("padding-top",D)}}}},draw_helper:function(af,ag,ah,ak,aq,av,ar,al){var ai=this,ap=this._gen_tile_cache_key(ag,av,ah),am=ah*P*ak,au=am+P*ak;var an=(af?undefined:ai.tile_cache.get(ap));if(an){ai.show_tile(an,aq,av);return an}var ao=function(aw){return("isResolved" in aw)};var aj=true;var ae=ai.data_manager.get_data(am,au,ai.mode,ak,ai.data_url_extra_params);if(ao(ae)){aj=false}var at;if(view.reference_track&&av>view.canvas_manager.char_width_px){at=view.reference_track.data_manager.get_data(am,au,ai.mode,ak,view.reference_track.data_url_extra_params);if(ao(at)){aj=false}}if(aj){p(ae,al);var an=ai.draw_tile(ae,ai.mode,ak,ah,av,at);ai.tile_cache.set(ap,an);if(an!==undefined){ai.show_tile(an,aq,av)}return an}$.when(ae,at).then(function(){view.request_redraw()});return null},show_tile:function(al,an,ao){var ag=this,af=al.canvas,ak=af;if(al.message){var ap=$("<div/>"),am=$("<div/>").addClass("tile-message").text(al.message).css({height:D-1,width:al.canvas.width}).appendTo(ap),ai=$("<a href='javascript:void(0);'/>").addClass("icon more-down").appendTo(am),ae=$("<a href='javascript:void(0);'/>").addClass("icon more-across").appendTo(am);ap.append(af);ak=ap;ai.click(function(){al.stale=true;ag.data_manager.get_more_data(al.low,al.high,ag.mode,al.resolution,{},ag.data_manager.DEEP_DATA_REQ);ag.request_draw()}).dblclick(function(aq){aq.stopPropagation()});ae.click(function(){al.stale=true;ag.data_manager.get_more_data(al.low,al.high,ag.mode,al.resolution,{},ag.data_manager.BROAD_DATA_REQ);ag.request_draw()}).dblclick(function(aq){aq.stopPropagation()})}var aj=this.view.high-this.view.low,ah=(al.low-this.view.low)*ao;if(this.left_offset){ah-=this.left_offset}ak.css({position:"absolute",top:0,left:ah,height:""});an.append(ak);ag.max_height=Math.max(ag.max_height,ak.height());ag.content_div.css("height",ag.max_height+"px");an.children().css("height",ag.max_height+"px")},_get_tile_bounds:function(ae,af){var ah=ae*P*af,ai=P*af,ag=(ah+ai<=this.view.max_high?ah+ai:this.view.max_high);return[ah,ag]},tool_region_and_parameters_str:function(ag,ae,ah){var af=this,ai=(ag!==undefined&&ae!==undefined&&ah!==undefined?ag+":"+ae+"-"+ah:"all");return" - region=["+ai+"], parameters=["+af.tool.get_param_values().join(", ")+"]"},add_track:function(ae){ae.track_id=this.track_id+"_"+this.child_tracks.length;ae.container_div.attr("id","track_"+ae.track_id);this.child_tracks_container.append(ae.container_div);m(ae.container_div,".child-track-icon");if(!$(this.child_tracks_container).is(":visible")){this.child_tracks_container.show()}this.child_tracks.push(ae);this.view.has_changes=true},remove_track:function(ae){ae.container_div.fadeOut("slow",function(){$(this).remove()})}});var aa=function(ae,af){this.hidden=true;j.call(this,null,ae,af);this.container_div.addClass("label-track")};p(aa.prototype,j.prototype,{_draw:function(){var ag=this.view,ah=ag.high-ag.low,ak=Math.floor(Math.pow(10,Math.floor(Math.log(ah)/Math.log(10)))),ae=Math.floor(ag.low/ak)*ak,ai=this.view.container.width(),af=$("<div style='position: relative; height: 1.3em;'></div>");while(ae<ag.high){var aj=(ae-ag.low)/ah*ai;af.append($("<div class='label'>"+commatize(ae)+"</div>").css({position:"absolute",left:aj-1}));ae+=ak}this.content_div.children(":first").remove();this.content_div.append(af)}});var A=function(ae){this.hidden=true;j.call(this,null,ae,ae.top_labeltrack);L.call(this);ae.reference_track=this;this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url;this.data_url_extra_params={dbkey:ae.dbkey};this.data_manager=new G(B,this,false);this.tile_cache=new c(t)};p(A.prototype,L.prototype,{draw_tile:function(ao,ak,aj,af,ap){var ai=this,ag=P*aj;if(ap>this.view.canvas_manager.char_width_px){if(ao===null){ai.content_div.css("height","0px");return}var ah=this.view.canvas_manager.new_canvas();var an=ah.getContext("2d");ah.width=Math.ceil(ag*ap+ai.left_offset);ah.height=ai.height_px;an.font=an.canvas.manager.default_font;an.textAlign="center";for(var al=0,am=ao.length;al<am;al++){var ae=Math.round(al*ap);an.fillText(ao[al],ae+ai.left_offset,10)}return new b(af,aj,ah,ao)}this.content_div.css("height","0px")}});var k=function(ai,ag,aj,ae,ah){var af=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";j.call(this,ai,ag,ag.viewport_container);L.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=aj;this.dataset_id=ae;this.original_dataset_id=ae;this.data_manager=new Q(B,this);this.tile_cache=new c(t);this.left_offset=0;this.track_config=new Y({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ai},{key:"color",label:"Color",type:"color",default_value:"black"},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.height_px,hidden:true}],saved_values:ah,onchange:function(){af.set_name(af.prefs.name);af.vertical_range=af.prefs.max_value-af.prefs.min_value;$("#linetrack_"+af.track_id+"_minval").text(af.prefs.min_value);$("#linetrack_"+af.track_id+"_maxval").text(af.prefs.max_value);af.tile_cache.clear();af.request_draw()}});this.prefs=this.track_config.values;this.height_px=this.track_config.values.height;this.vertical_range=this.track_config.values.max_value-this.track_config.values.min_value;this.add_resize_handle()};p(k.prototype,L.prototype,{add_resize_handle:function(){var ae=this;var ah=false;var ag=false;var af=$("<div class='track-resize'>");$(ae.container_div).hover(function(){ah=true;af.show()},function(){ah=false;if(!ag){af.hide()}});af.hide().bind("dragstart",function(ai,aj){ag=true;aj.original_height=$(ae.content_div).height()}).bind("drag",function(aj,ak){var ai=Math.min(Math.max(ak.original_height+ak.deltaY,ae.min_height_px),ae.max_height_px);$(ae.content_div).css("height",ai);ae.height_px=ai;ae.request_draw(true)}).bind("dragend",function(ai,aj){ae.tile_cache.clear();ag=false;if(!ah){af.hide()}ae.track_config.values.height=ae.height_px}).appendTo(ae.container_div)},predraw_init:function(){var ae=this,af=ae.view.tracks.indexOf(ae);ae.vertical_range=undefined;return $.getJSON(ae.data_url,{stats:true,chrom:ae.view.chrom,low:null,high:null,hda_ldda:ae.hda_ldda,dataset_id:ae.dataset_id},function(ag){ae.container_div.addClass("line-track");var ai=ag.data;if(isNaN(parseFloat(ae.prefs.min_value))||isNaN(parseFloat(ae.prefs.max_value))){ae.prefs.min_value=ai.min;ae.prefs.max_value=ai.max;$("#track_"+af+"_minval").val(ae.prefs.min_value);$("#track_"+af+"_maxval").val(ae.prefs.max_value)}ae.vertical_range=ae.prefs.max_value-ae.prefs.min_value;ae.total_frequency=ai.total_frequency;ae.container_div.find(".yaxislabel").remove();var aj=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+af+"_minval").text(w(ae.prefs.min_value));var ah=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+af+"_maxval").text(w(ae.prefs.max_value));ah.css({position:"absolute",top:"24px",left:"10px"});ah.prependTo(ae.container_div);aj.css({position:"absolute",bottom:"2px",left:"10px"});aj.prependTo(ae.container_div)})},draw_tile:function(aq,aj,ai,ag,ap){if(this.vertical_range===undefined){return}var ae=this._get_tile_bounds(ag,ai),ak=ae[0],ao=ae[1],af=Math.ceil((ao-ak)*ap),am=this.height_px;var ah=this.view.canvas_manager.new_canvas();ah.width=af,ah.height=am;var an=ah.getContext("2d");var al=new K.LinePainter(aq.data,ak,ao,this.prefs,aj);al.draw(an,af,am);return new b(ag,ai,ah,aq.data)}});var e=function(ae,aj,ai,am,al,ag,ah,ak){var af=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];this.track_config=new Y({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ae},{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:al,onchange:function(){af.set_name(af.prefs.name);af.tile_cache.clear();af.request_draw()}});this.prefs=this.track_config.values;j.call(this,ae,aj,aj.viewport_container);L.call(this,ag,ah,ak);this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=ai;this.dataset_id=am;this.original_dataset_id=am;this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.inc_slots={};this.start_end_dct={};this.tile_cache=new c(d);this.data_manager=new Q(20,this);this.left_offset=200;this.painter=K.LinkedFeaturePainter};p(e.prototype,L.prototype,{postdraw_actions:function(au,ae,av,at){L.prototype.postdraw_actions.call(this,au,at);var ah=this;if(at){var aj=ah.content_div.children();var ak=false;for(var ai=aj.length-1,ao=0;ai>=ao;ai--){var ag=$(aj[ai]);if(ak){ag.remove()}else{if(ag.children().length!==0){ak=true}}}}if(ah.mode=="Histogram"){var an=-1;for(var ai=0;ai<au.length;ai++){var ar=au[ai].max_val;if(ar>an){an=ar}}for(var ai=0;ai<au.length;ai++){var aq=au[ai];if(aq.max_val!==an){aq.canvas.remove();ah.draw_helper(true,ae,aq.index,aq.resolution,aq.canvas.parent(),av,[],{max:an})}}}if(ah.filters_manager){var af=ah.filters_manager.filters;for(var am=0;am<af.length;am++){af[am].update_ui_elt()}var al=false,ap;for(var ai=0;ai<au.length;ai++){if(au[ai].data.length){ap=au[ai].data[0];for(var am=0;am<af.length;am++){if(af[am].applies_to(ap)){al=true;break}}}}if(ah.filters_available!==al){ah.filters_available=al;if(!ah.filters_available){ah.filters_div.hide()}ah.make_name_popup_menu()}}},update_auto_mode:function(ae){if(this.mode=="Auto"){if(ae=="no_detail"){ae="feature spans"}else{if(ae=="summary_tree"){ae="coverage histogram"}}this.mode_div.text("Auto ("+ae+")")}},incremental_slots:function(ai,af,ah){var ag=this.view.canvas_manager.dummy_context,ae=this.inc_slots[ai];if(!ae||(ae.mode!==ah)){ae=new (r.FeatureSlotter)(ai,ah==="Pack",z,function(aj){return ag.measureText(aj)});ae.mode=ah;this.inc_slots[ai]=ae}return ae.slot_features(af)},get_summary_tree_data:function(ai,al,ag,au){if(au>ag-al){au=ag-al}var ap=Math.floor((ag-al)/au),at=[],ah=0;var aj=0,ak=0,ao,ar=0,am=[],aq,an;var af=function(ax,aw,ay,av){ax[0]=aw+ay*av;ax[1]=aw+(ay+1)*av};while(ar<au&&aj!==ai.length){var ae=false;for(;ar<au&&!ae;ar++){af(am,al,ar,ap);for(ak=aj;ak<ai.length;ak++){ao=ai[ak].slice(1,3);if(is_overlap(ao,am)){ae=true;break}}if(ae){break}}data_start_index=ak;at[at.length]=aq=[am[0],0];for(;ak<ai.length;ak++){ao=ai[ak].slice(1,3);if(is_overlap(ao,am)){aq[1]++}else{break}}if(aq[1]>ah){ah=aq[1]}ar++}return{max:ah,delta:ap,data:at}},draw_tile:function(at,aw,aB,aF,ao,ah){var ay=this,aj=ay._get_tile_bounds(aF,aB),aH=aj[0],af=aj[1],av=af-aH,az=Math.ceil(av*ao),aL=25,ai=this.left_offset,au,ak;if(aw==="Auto"){if(at.dataset_type==="summary_tree"){aw=at.dataset_type}else{if(at.extra_info==="no_detail"){aw="no_detail"}else{var aK=at.data;if(this.view.high-this.view.low>H){aw="Squish"}else{aw="Pack"}}}this.update_auto_mode(aw)}if(aw==="summary_tree"||aw==="Histogram"){ak=this.summary_draw_height;this.container_div.find(".yaxislabel").remove();var ae=$("<div />").addClass("yaxislabel");ae.text(at.max);ae.css({position:"absolute",top:"24px",left:"10px",color:this.prefs.label_color});ae.prependTo(this.container_div);var ag=this.view.canvas_manager.new_canvas();ag.width=az+ai;ag.height=ak+R;if(at.dataset_type!="summary_tree"){var ap=this.get_summary_tree_data(at.data,aH,af,200);if(at.max){ap.max=at.max}at=ap}var aI=new K.SummaryTreePainter(at,aH,af,this.prefs);var aA=ag.getContext("2d");aA.translate(ai,R);aI.draw(aA,az,ak);return new l(aF,aB,ag,at.data,at.max)}var au,am=1;if(aw==="no_detail"||aw==="Squish"||aw==="Pack"){am=this.incremental_slots(ao,at.data,aw);au=this.inc_slots[ao].slots}var an=[];if(at.data){var aq=this.filters_manager.filters;for(var aC=0,aE=at.data.length;aC<aE;aC++){var al=at.data[aC];var aD=false;var ar;for(var aG=0,aJ=aq.length;aG<aJ;aG++){ar=aq[aG];ar.update_attrs(al);if(!ar.keep(al)){aD=true;break}}if(!aD){an.push(al)}}}var ax=(this.filters_manager.alpha_filter?new N(this.filters_manager.alpha_filter):null);var aI=new (this.painter)(an,aH,af,this.prefs,aw,ax,ah);var ak=Math.max(ac,aI.get_required_height(am));var ag=this.view.canvas_manager.new_canvas();ag.width=az+ai;ag.height=ak;var aA=ag.getContext("2d");aA.fillStyle=this.prefs.block_color;aA.font=aA.canvas.manager.default_font;aA.textAlign="right";this.container_div.find(".yaxislabel").remove();if(at.data){aA.translate(ai,0);aI.draw(aA,az,ak,au)}return new O(aF,aB,ag,at.data,at.message)}});var S=function(ah,af,aj,ae,ag,ai){e.call(this,ah,af,aj,ae,ag,ai);this.painter=K.VariantPainter};p(S.prototype,L.prototype,e.prototype);var V=function(ah,af,aj,ae,ag,ai){e.call(this,ah,af,aj,ae,ag,ai);this.track_config=new Y({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ah},{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ag,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.track_config.values;this.painter=K.ReadPainter;this.make_name_popup_menu()};p(V.prototype,L.prototype,e.prototype);var T=function(ai,ag,ak,ae,ah,aj,af){e.call(this,ai,ag,ak,ae,ah,aj,{},af);this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};p(T.prototype,L.prototype,e.prototype,{predraw_init:function(){var af=this;var ae=function(){if(af.data_manager.size()===0){setTimeout(ae,300)}else{af.data_url=default_data_url;af.data_query_wait=J;af.dataset_state_url=converted_datasets_state_url;$.getJSON(af.dataset_state_url,{dataset_id:af.dataset_id,hda_ldda:af.hda_ldda},function(ag){})}};ae()}});W.View=ab;W.DrawableCollection=y;W.LineTrack=k;W.FeatureTrack=e;W.ReadTrack=V};var slotting_module=function(c,b){var e=c("class").extend;var d=2,a=5;b.FeatureSlotter=function(j,h,f,g){this.slots={};this.start_end_dct={};this.w_scale=j;this.include_label=h;this.max_rows=f;this.measureText=g};e(b.FeatureSlotter.prototype,{slot_features:function(m){var p=this.w_scale,s=this.slots,h=this.start_end_dct,y=[],A=[],n=0,z=this.max_rows;for(var w=0,x=m.length;w<x;w++){var l=m[w],o=l[0];if(s[o]!==undefined){n=Math.max(n,s[o]);A.push(s[o])}else{y.push(w)}}var q=function(G,H){for(var F=0;F<=z;F++){var D=false,I=h[F];if(I!==undefined){for(var C=0,E=I.length;C<E;C++){var B=I[C];if(H>B[0]&&G<B[1]){D=true;break}}}if(!D){return F}}return -1};for(var w=0,x=y.length;w<x;w++){var l=m[y[w]],o=l[0],u=l[1],f=l[2],r=l[3],g=Math.floor(u*p),k=Math.ceil(f*p),v=this.measureText(r).width,j;if(r!==undefined&&this.include_label){v+=(d+a);if(g-v>=0){g-=v;j="left"}else{k+=v;j="right"}}var t=q(g,k);if(t>=0){if(h[t]===undefined){h[t]=[]}h[t].push([g,k]);s[o]=t;n=Math.max(n,t)}else{}}return n+1}})};var painters_module=function(k,x){var u=k("class").extend;var p=function(I,A,G,z,F,D){if(D===undefined){D=4}var C=z-A;var B=F-G;var E=Math.floor(Math.sqrt(C*C+B*B)/D);var J=C/E;var H=B/E;var y;for(y=0;y<E;y++,A+=J,G+=H){if(y%2!==0){continue}I.fillRect(A,G,D,1)}};var q=function(B,A,z,E){var D=A-E/2,C=A+E/2,F=z-Math.sqrt(E*3/2);B.beginPath();B.moveTo(D,F);B.lineTo(C,F);B.lineTo(A,z);B.lineTo(D,F);B.strokeStyle=this.fillStyle;B.fill();B.stroke();B.closePath()};var g=function(y){this.default_alpha=(y?y:1)};g.prototype.gen_alpha=function(y){return this.default_alpha};var n=function(A,C,y,z,B){this.data=A;this.view_start=C;this.view_end=y;this.prefs=u({},this.default_prefs,z);this.mode=B};n.prototype.default_prefs={};var v=function(A,C,y,z,B){n.call(this,A,C,y,z,B)};v.prototype.default_prefs={show_counts:false};v.prototype.draw=function(M,z,L){var E=this.view_start,O=this.view_end-this.view_start,N=z/O;var J=this.data.data,I=this.data.delta,G=this.data.max,B=L;delta_x_px=Math.ceil(I*N);M.save();for(var C=0,D=J.length;C<D;C++){var H=Math.floor((J[C][0]-E)*N);var F=J[C][1];if(!F){continue}var K=F/G*L;if(F!==0&&K<1){K=1}M.fillStyle=this.prefs.block_color;M.fillRect(H,B-K,delta_x_px,K);var A=4;if(this.prefs.show_counts&&(M.measureText(F).width+A)<delta_x_px){M.fillStyle=this.prefs.label_color;M.textAlign="center";M.fillText(F,H+(delta_x_px/2),10)}}M.restore()};var c=function(y,C,E,F,A){n.call(this,y,C,E,F,A);if(this.prefs.min_value===undefined){var G=Infinity;for(var z=0,B=this.data.length;z<B;z++){G=Math.min(G,this.data[z][1])}this.prefs.min_value=G}if(this.prefs.max_value===undefined){var D=-Infinity;for(var z=0,B=this.data.length;z<B;z++){D=Math.max(D,this.data[z][1])}this.prefs.max_value=D}};c.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};c.prototype.draw=function(N,M,K){var F=false,H=this.prefs.min_value,D=this.prefs.max_value,J=D-H,z=K,A=this.view_start,L=this.view_end-this.view_start,B=M/L,I=this.mode,T=this.data;N.save();var U=Math.round(K+H/J*K);if(I!=="Intensity"){N.fillStyle="#aaa";N.fillRect(0,U,M,1)}N.beginPath();var R,E,C;if(T.length>1){C=Math.ceil((T[1][0]-T[0][0])*B)}else{C=10}for(var O=0,P=T.length;O<P;O++){N.fillStyle=this.prefs.color;R=Math.round((T[O][0]-A)*B);E=T[O][1];var Q=false,G=false;if(E===null){if(F&&I==="Filled"){N.lineTo(R,z)}F=false;continue}if(E<H){G=true;E=H}else{if(E>D){Q=true;E=D}}if(I==="Histogram"){E=Math.round(E/J*z);N.fillRect(R,U,C,-E)}else{if(I==="Intensity"){E=255-Math.floor((E-H)/J*255);N.fillStyle="rgb("+E+","+E+","+E+")";N.fillRect(R,0,C,z)}else{E=Math.round(z-(E-H)/J*z);if(F){N.lineTo(R,E)}else{F=true;if(I==="Filled"){N.moveTo(R,z);N.lineTo(R,E)}else{N.moveTo(R,E)}}}}N.fillStyle=this.prefs.overflow_color;if(Q||G){var S;if(I==="Histogram"||I==="Intensity"){S=C}else{R-=2;S=4}if(Q){N.fillRect(R,0,S,3)}if(G){N.fillRect(R,z-3,S,3)}}N.fillStyle=this.prefs.color}if(I==="Filled"){if(F){N.lineTo(R,U);N.lineTo(0,U)}N.fill()}else{N.stroke()}N.restore()};var o=function(B,D,y,A,C,z){n.call(this,B,D,y,A,C);this.alpha_generator=(z?z:new g())};o.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};u(o.prototype,{get_required_height:function(z){var y=y_scale=this.get_row_height(),A=this.mode;if(A==="no_detail"||A==="Squish"||A==="Pack"){y=z*y_scale}return y+Math.max(Math.round(y_scale/2),5)},draw:function(K,B,J,G){var E=this.data,H=this.view_start,L=this.view_end;K.save();K.fillStyle=this.prefs.block_color;K.textAlign="right";var O=this.view_end-this.view_start,N=B/O,A=this.get_row_height();for(var D=0,F=E.length;D<F;D++){var M=E[D],C=M[0],y=M[1],z=M[2],I=(G&&G[C]!==undefined?G[C]:null);if((y<L&&z>H)&&(this.mode=="Dense"||I!==null)){this.draw_element(K,this.mode,M,I,H,L,N,A,B)}}K.restore()},draw_element:function(E,A,G,C,B,D,F,z,y){console.log("WARNING: Unimplemented function.")}});var d=10,j=3,m=5,w=10,f=1,s=3,e=3,a=9,l=2,h="#ccc";var r=function(B,D,y,A,C,z){o.call(this,B,D,y,A,C,z)};u(r.prototype,o.prototype,{get_row_height:function(){var z=this.mode,y;if(z==="Dense"){y=d}else{if(z==="no_detail"){y=j}else{if(z==="Squish"){y=m}else{y=w}}}return y},draw_element:function(K,D,S,F,M,ac,ag,ah,y){var P=S[0],ae=S[1],W=S[2],N=S[3],X=Math.floor(Math.max(0,(ae-M)*ag)),L=Math.ceil(Math.min(y,Math.max(0,(W-M)*ag))),V=(D==="Dense"?0:(0+F))*ah,J,aa,O=null,ai=null,B=this.prefs.block_color,Z=this.prefs.label_color;K.globalAlpha=this.alpha_generator.gen_alpha(S);if(D=="Dense"){F=1}if(D==="no_detail"){K.fillStyle=B;K.fillRect(X,V+5,L-X,f)}else{var I=S[4],U=S[5],Y=S[6],C=S[7];if(U&&Y){O=Math.floor(Math.max(0,(U-M)*ag));ai=Math.ceil(Math.min(y,Math.max(0,(Y-M)*ag)))}var af,Q;if(D==="Squish"||D==="Dense"){af=1;Q=e}else{af=5;Q=a}if(!C){if(S.strand){if(S.strand==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand_inv")}else{if(S.strand==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand_inv")}}}else{K.fillStyle=B}K.fillRect(X,V,L-X,Q)}else{var H,R;if(D==="Squish"||D==="Dense"){K.fillStyle=h;H=V+Math.floor(e/2)+1;R=1}else{if(I){var H=V;var R=Q;if(I==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand")}else{if(I==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand")}}}else{K.fillStyle=h;H+=(e/2)+1;R=1}}K.fillRect(X,H,L-X,R);for(var ad=0,A=C.length;ad<A;ad++){var E=C[ad],z=Math.floor(Math.max(0,(E[0]-M)*ag)),T=Math.ceil(Math.min(y,Math.max((E[1]-M)*ag)));if(z>T){continue}K.fillStyle=B;K.fillRect(z,V+(Q-af)/2+1,T-z,af);if(O!==undefined&&Y>U&&!(z>ai||T<O)){var ab=Math.max(z,O),G=Math.min(T,ai);K.fillRect(ab,V+1,G-ab,Q);if(C.length==1&&D=="Pack"){if(I==="+"){K.fillStyle=K.canvas.manager.get_pattern("right_strand_inv")}else{if(I==="-"){K.fillStyle=K.canvas.manager.get_pattern("left_strand_inv")}}if(ab+14<G){ab+=2;G-=2}K.fillRect(ab,V+1,G-ab,Q)}}}}if(D==="Pack"&&ae>M){K.fillStyle=Z;if(M===0&&X-K.measureText(N).width<0){K.textAlign="left";K.fillText(N,L+l,V+8)}else{K.textAlign="right";K.fillText(N,X-l,V+8)}}}K.globalAlpha=1}});var b=function(B,D,y,A,C,z){o.call(this,B,D,y,A,C,z)};u(b.prototype,o.prototype,{draw_element:function(R,M,G,C,U,A,J,S,P){var G=data[i],I=G[0],Q=G[1],B=G[2],L=G[3],E=Math.floor(Math.max(0,(Q-U)*J)),H=Math.ceil(Math.min(P,Math.max(0,(B-U)*J))),D=(M==="Dense"?0:(0+C))*S,y,V,z=null,K=null;if(no_label){R.fillStyle=block_color;R.fillRect(E+left_offset,D+5,H-E,1)}else{var T=G[4],O=G[5],F=G[6];y=9;V=1;R.fillRect(E+left_offset,D,H-E,y);if(M!=="Dense"&&L!==undefined&&Q>U){R.fillStyle=label_color;if(U===0&&E-R.measureText(L).width<0){R.textAlign="left";R.fillText(L,H+2+left_offset,D+8)}else{R.textAlign="right";R.fillText(L,E-2+left_offset,D+8)}R.fillStyle=block_color}var N=T+" / "+O;if(Q>U&&R.measureText(N).width<(H-E)){R.fillStyle="white";R.textAlign="center";R.fillText(N,left_offset+E+(H-E)/2,D+8);R.fillStyle=block_color}}}});var t=function(C,E,y,B,D,z,A){o.call(this,C,E,y,B,D,z);this.ref_seq=A};t.prototype.default_prefs=u({},o.prototype.default_prefs,{show_insertions:false});u(t.prototype,o.prototype,{get_row_height:function(){var y,z=this.mode;if(z==="Dense"){y=d}else{if(z==="Squish"){y=m}else{y=w;if(this.prefs.show_insertions){y*=2}}}return y},draw_read:function(U,P,L,Z,A,T,I,F,E){U.textAlign="center";var S=this,z=[Z,A],O=0,V=0,R=0;ref_seq=this.ref_seq,char_width_px=U.canvas.manager.char_width_px;var ae=[];if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){R=Math.round(L/2)}if(!I){I=[[0,F.length]]}for(var M=0,X=I.length;M<X;M++){var J=I[M],B="MIDNSHP=X"[J[0]],N=J[1];if(B==="H"||B==="S"){O-=N}var G=T+O,ad=Math.floor(Math.max(0,(G-Z)*L)),H=Math.floor(Math.max(0,(G+N-Z)*L));if(ad===H){H+=1}switch(B){case"H":break;case"S":case"M":case"=":if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(R>0){U.fillStyle=this.prefs.block_color;U.fillRect(ad-R,E+1,H-ad,9);U.fillStyle=h;for(var ab=0,y=Q.length;ab<y;ab++){if(this.prefs.show_differences&&ref_seq){var K=ref_seq[G-Z+ab];if(!K||K.toLowerCase()===Q[ab].toLowerCase()){continue}}if(G+ab>=Z&&G+ab<=A){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac,E+9)}}}else{U.fillStyle=this.prefs.block_color;U.fillRect(ad,E+4,H-ad,e)}}V+=N;O+=N;break;case"N":U.fillStyle=h;U.fillRect(ad-R,E+5,H-ad,1);O+=N;break;case"D":U.fillStyle="red";U.fillRect(ad-R,E+4,H-ad,3);O+=N;break;case"P":break;case"I":var Y=ad-R;if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(this.prefs.show_insertions){var D=ad-(H-ad)/2;if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){U.fillStyle="yellow";U.fillRect(D-R,E-9,H-ad,9);ae[ae.length]={type:"triangle",data:[Y,E+4,5]};U.fillStyle=h;switch(seq_tile_overlap){case (OVERLAP_START):Q=Q.slice(Z-G);break;case (OVERLAP_END):Q=Q.slice(0,G-A);break;case (CONTAINED_BY):break;case (CONTAINS):Q=Q.slice(Z-G,G-A);break}for(var ab=0,y=Q.length;ab<y;ab++){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac-(H-ad)/2,E)}}else{U.fillStyle="yellow";U.fillRect(D,E+(this.mode!=="Dense"?2:5),H-ad,(P!=="Dense"?e:s))}}else{if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>char_width_px){ae[ae.length]={type:"text",data:[Q.length,Y,E+9]}}else{}}}V+=N;break;case"X":V+=N;break}}U.fillStyle="yellow";var aa,C,af;for(var W=0;W<ae.length;W++){aa=ae[W];C=aa.type;af=aa.data;if(C==="text"){U.save();U.font="bold "+U.font;U.fillText(af[0],af[1],af[2]);U.restore()}else{if(C=="triangle"){q(U,af[0],af[1],af[2])}}}},draw_element:function(R,M,E,B,U,z,I,S,P){var H=E[0],Q=E[1],A=E[2],J=E[3],D=Math.floor(Math.max(0,(Q-U)*I)),F=Math.ceil(Math.min(P,Math.max(0,(A-U)*I))),C=(M==="Dense"?0:(0+B))*S,V=this.prefs.block_color,G=this.prefs.label_color,O=0;if((M==="Pack"||this.mode==="Auto")&&I>R.canvas.manager.char_width_px){var O=Math.round(I/2)}R.fillStyle=V;if(E[5] instanceof Array){var N=Math.floor(Math.max(0,(E[4][0]-U)*I)),L=Math.ceil(Math.min(P,Math.max(0,(E[4][1]-U)*I))),K=Math.floor(Math.max(0,(E[5][0]-U)*I)),y=Math.ceil(Math.min(P,Math.max(0,(E[5][1]-U)*I)));if(E[4][1]>=U&&E[4][0]<=z&&E[4][2]){this.draw_read(R,M,I,U,z,E[4][0],E[4][2],E[4][3],C)}if(E[5][1]>=U&&E[5][0]<=z&&E[5][2]){this.draw_read(R,M,I,U,z,E[5][0],E[5][2],E[5][3],C)}if(K>L){R.fillStyle=h;p(R,L-O,C+5,K-O,C+5)}}else{R.fillStyle=V;this.draw_read(R,M,I,U,z,Q,E[4],E[5],C)}if(M==="Pack"&&Q>U){R.fillStyle=this.prefs.label_color;var T=1;if(T===0&&D-R.measureText(J).width<0){R.textAlign="left";R.fillText(J,F+l-O,C+8)}else{R.textAlign="right";R.fillText(J,D-l-O,C+8)}R.fillStyle=V}}});x.AlphaGenerator=g;x.SummaryTreePainter=v;x.LinePainter=c;x.LinkedFeaturePainter=r;x.ReadPainter=t;x.VariantPainter=b};(function(d){var c={};var b=function(e){return c[e]};var a=function(f,g){var e={};g(b,e);c[f]=e};a("class",class_module);a("slotting",slotting_module);a("painters",painters_module);a("trackster",trackster_module);for(key in c.trackster){d[key]=c.trackster[key]}})(window);
\ No newline at end of file
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