diff --git a/lib/galaxy/visualization/tracks/data/interval_index.py b/lib/galaxy/visualization/tracks/data/interval_index.py index a974c6ff382..3bca5ca1019 100644 --- a/lib/galaxy/visualization/tracks/data/interval_index.py +++ b/lib/galaxy/visualization/tracks/data/interval_index.py @@ -9,6 +9,8 @@ import pkg_resources; pkg_resources.require( "bx-python" ) from bx.interval_index_file import Indexes from galaxy.datatypes.interval import Bed, Gff +MAX_VALS = 500 # only display first MAX_VALS features + class IntervalIndexDataProvider( object ): def __init__( self, converted_dataset, original_dataset ): self.original_dataset = original_dataset @@ -20,8 +22,14 @@ class IntervalIndexDataProvider( object ): source = open( self.original_dataset.file_name ) index = Indexes( self.converted_dataset.file_name ) results = [] + count = 0 + message = None for start, end, offset in index.find(chrom, start, end): + if count >= MAX_VALS: + message = "Only the first %s features are being displayed." % MAX_VALS + break + count += 1 source.seek(offset) feature = source.readline().split() payload = [ offset, start, end ] @@ -53,4 +61,4 @@ class IntervalIndexDataProvider( object ): results.append(payload) - return results + return { 'data': results, 'message': message } diff --git a/lib/galaxy/web/controllers/tracks.py b/lib/galaxy/web/controllers/tracks.py index 770acb02e45..95d2b926539 100644 --- a/lib/galaxy/web/controllers/tracks.py +++ b/lib/galaxy/web/controllers/tracks.py @@ -291,7 +291,8 @@ class TracksController( BaseController, UsesVisualization ): # Have to choose between indexer and data provider indexer = dataset_type_to_data_provider[data_sources['index']]( dataset.get_converted_dataset(trans, data_sources['index']), dataset ) summary = indexer.get_summary( chrom, low, high, **kwargs ) - if summary is not None: + if summary is not None and kwargs.get("mode", "Auto") == "Auto": + # Only check for summary if it's Auto mode (which is the default) if summary == "no_detail": kwargs["no_detail"] = True # meh extra_info = "no_detail" diff --git a/lib/galaxy/web/controllers/visualization.py b/lib/galaxy/web/controllers/visualization.py index 0f589309ce9..e5f75b485a6 100644 --- a/lib/galaxy/web/controllers/visualization.py +++ b/lib/galaxy/web/controllers/visualization.py @@ -228,7 +228,7 @@ class VisualizationController( BaseController, Sharable, UsesAnnotations, UsesVi # Get session and visualization. session = trans.sa_session - visualization = trans.sa_session.query( model.Visualization ).get( trans.security.decode_id( id ) ) + visualization = self.get_visualization( trans, id, check_ownership=True ) # Do operation on visualization. if 'make_accessible_via_link' in kwargs: @@ -261,7 +261,7 @@ class VisualizationController( BaseController, Sharable, UsesAnnotations, UsesVi def share( self, trans, id=None, email="", use_panels=False ): """ Handle sharing a visualization with a particular user. """ msg = mtype = None - visualization = trans.sa_session.query( model.Visualization ).get( trans.security.decode_id( id ) ) + visualization = self.get_visualization( trans, id, check_ownership=True ) if email: other = trans.sa_session.query( model.User ) \ .filter( and_( model.User.table.c.email==email, @@ -330,7 +330,7 @@ class VisualizationController( BaseController, Sharable, UsesAnnotations, UsesVi @web.require_login( "get item name and link" ) def get_name_and_link_async( self, trans, id=None ): """ Returns visualization's name and link. """ - visualization = self.get_visualization( trans, id ) + visualization = self.get_visualization( trans, id, check_ownership=False, check_accessible=True ) if self.create_item_slug( trans.sa_session, visualization ): trans.sa_session.flush() @@ -342,7 +342,7 @@ class VisualizationController( BaseController, Sharable, UsesAnnotations, UsesVi """ Returns item content in HTML format. """ # Get visualization, making sure it's accessible. - visualization = self.get_visualization( trans, id, False, True ) + visualization = self.get_visualization( trans, id, check_ownership=False, check_accessible=True ) if visualization is None: raise web.httpexceptions.HTTPNotFound() @@ -373,25 +373,26 @@ class VisualizationController( BaseController, Sharable, UsesAnnotations, UsesVi visualization = model.Visualization() visualization.title = visualization_title visualization.slug = visualization_slug + visualization.dbkey = visualization_dbkey + visualization.type = 'trackster' # HACK: set visualization type to trackster since it's the only viz visualization_annotation = sanitize_html( visualization_annotation, 'utf-8', 'text/html' ) self.add_item_annotation( trans, visualization, visualization_annotation ) visualization.user = user + # And the first (empty) visualization revision visualization_revision = model.VisualizationRevision() visualization_revision.title = visualization_title + visualization_revision.config = {} + visualization_revision.dbkey = visualization_dbkey visualization_revision.visualization = visualization - # HACK: set visualization type to trackster; when we have multiple visualization types, we'll need to get type from the user. - visualization.type = 'trackster' visualization.latest_revision = visualization_revision - # Visualization config is dbkey for now. - visualization.latest_revision.config = { 'dbkey' : visualization_dbkey } - visualization_revision.content = "" + # Persist session = trans.sa_session - session.add( visualization ) + session.add(visualization) + session.add(visualization_revision) session.flush() - # Display the management visualization - ## trans.set_message( "Visualization '%s' created" % visualization.title ) + return trans.response.send_redirect( web.url_for( action='list' ) ) return trans.show_form( @@ -414,12 +415,9 @@ class VisualizationController( BaseController, Sharable, UsesAnnotations, UsesVi """ Edit a visualization's attributes. """ - encoded_id = id - id = trans.security.decode_id( id ) + visualization = self.get_visualization( trans, id, check_ownership=True ) session = trans.sa_session - visualization = session.query( model.Visualization ).get( id ) - user = trans.user - assert visualization.user == user + visualization_title_err = visualization_slug_err = visualization_annotation_err = "" if trans.request.method == "POST": if not visualization_title: @@ -428,7 +426,7 @@ class VisualizationController( BaseController, Sharable, UsesAnnotations, UsesVi visualization_slug_err = "Visualization id is required" elif not VALID_SLUG_RE.match( visualization_slug ): visualization_slug_err = "Visualization identifier must consist of only lowercase letters, numbers, and the '-' character" - elif visualization_slug != visualization.slug and trans.sa_session.query( model.Visualization ).filter_by( user=user, slug=visualization_slug, deleted=False ).first(): + elif visualization_slug != visualization.slug and trans.sa_session.query( model.Visualization ).filter_by( user=visualization.user, slug=visualization_slug, deleted=False ).first(): visualization_slug_err = "Visualization id must be unique" else: visualization.title = visualization_title @@ -449,7 +447,7 @@ class VisualizationController( BaseController, Sharable, UsesAnnotations, UsesVi if not visualization_annotation: visualization_annotation = "" return trans.show_form( - web.FormBuilder( web.url_for( id=encoded_id ), "Edit visualization attributes", submit_text="Submit" ) + web.FormBuilder( web.url_for( id=id ), "Edit visualization attributes", submit_text="Submit" ) .add_text( "visualization_title", "Visualization title", value=visualization_title, error=visualization_title_err ) .add_text( "visualization_slug", "Visualization identifier", value=visualization_slug, error=visualization_slug_err, help="""A unique identifier that will be used for @@ -460,18 +458,5 @@ class VisualizationController( BaseController, Sharable, UsesAnnotations, UsesVi .add_text( "visualization_annotation", "Visualization annotation", value=visualization_annotation, error=visualization_annotation_err, help="A description of the visualization; annotation is shown alongside published visualizations."), template="visualization/create.mako" ) - - # @web.expose - # @web.require_login() - # def list( self, trans, *args, **kwargs ): - # return self.list_grid( trans, *args, **kwargs ) - - #@web.expose - #@web.require_admin - #def index( self, trans, *args, **kwargs ): - # # Build grid - # grid = self.list( trans, *args, **kwargs ) - # # Render grid wrapped in panels - # return trans.fill_template( "visualization/index.mako", grid=grid ) - + \ No newline at end of file diff --git a/static/scripts/packed/trackster.js b/static/scripts/packed/trackster.js index ccb0759f993..92ee7e0ad19 100644 --- a/static/scripts/packed/trackster.js +++ b/static/scripts/packed/trackster.js @@ -1 +1 @@ -var DENSITY=200,FEATURE_LEVELS=10,DATA_ERROR="There was an error in indexing this dataset. ",DATA_NOCONVERTER="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",DATA_NONE="No data for this chrom/contig.",DATA_PENDING="Currently indexing... please wait",DATA_LOADING="Loading data...",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=30,CACHED_DATA=5,CONTEXT=$("").get(0).getContext("2d"),PX_PER_CHAR=CONTEXT.measureText("A").width,RIGHT_STRAND,LEFT_STRAND;var right_img=new Image();right_img.src=image_path+"/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src=image_path+"/visualization/strand_left.png";left_img.onload=function(){LEFT_STRAND=CONTEXT.createPattern(left_img,"repeat")};var right_img_inv=new Image();right_img_inv.src=image_path+"/visualization/strand_right_inv.png";right_img_inv.onload=function(){RIGHT_STRAND_INV=CONTEXT.createPattern(right_img_inv,"repeat")};var left_img_inv=new Image();left_img_inv.src=image_path+"/visualization/strand_left_inv.png";left_img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function round_1000(a){return Math.round(a*1000)/1000}var Cache=function(a){this.num_elements=a;this.clear()};$.extend(Cache.prototype,{get:function(b){var a=this.key_ary.indexOf(b);if(a!=-1){this.key_ary.splice(a,1);this.key_ary.push(b)}return this.obj_cache[b]},set:function(b,c){if(!this.obj_cache[b]){if(this.key_ary.length>=this.num_elements){var a=this.key_ary.shift();delete this.obj_cache[a]}this.key_ary.push(b)}this.obj_cache[b]=c;return c},clear:function(){this.obj_cache={};this.key_ary=[]}});var View=function(a,c,e,d,b){this.container=a;this.vis_id=d;this.dbkey=b;this.title=e;this.chrom=c;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init();this.reset()};$.extend(View.prototype,{init:function(){var c=this.container,a=this;this.top_labeltrack=$("
").addClass("top-labeltrack").appendTo(c);this.content_div=$("").addClass("content").css("position","relative").appendTo(c);this.intro_div=$("").addClass("intro").text("Select a chrom from the dropdown below").hide().appendTo(c);this.viewport_container=$("").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.nav_container=$("").addClass("nav-container").appendTo(c);this.nav_labeltrack=$("").addClass("nav-labeltrack").appendTo(this.nav_container);this.nav=$("").addClass("nav").appendTo(this.nav_container);this.overview=$("").addClass("overview").appendTo(this.nav);this.overview_viewport=$("").addClass("overview-viewport").appendTo(this.overview);this.overview_box=$("").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("").addClass("nav-controls").appendTo(this.nav);this.chrom_form=$("").attr("action",function(){void (0)}).appendTo(this.nav_controls);this.chrom_select=$("").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("").appendTo(this.chrom_form);var b=function(d){if(d.type==="focusout"||(d.keyCode||d.which)===13||(d.keyCode||d.which)===27){if((d.keyCode||d.which)!==27){a.go_to($(this).val())}$(this).hide();a.location_span.show();a.chrom_select.show();return false}};this.nav_input=$("").addClass("nav-input").hide().bind("keypress focusout",b).appendTo(this.chrom_form);this.location_span=$("").addClass("location").appendTo(this.chrom_form);this.location_span.bind("click",function(){a.location_span.hide();a.chrom_select.hide();a.nav_input.css("display","inline-block");a.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("").attr("type","hidden").val(this.vis_id).appendTo(this.chrom_form)}this.zo_link=$("").click(function(){a.zoom_out();a.redraw()}).html('
').appendTo(this.chrom_form);this.zi_link=$("").click(function(){a.zoom_in();a.redraw()}).html('
').appendTo(this.chrom_form);$.ajax({url:chrom_url,data:(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}),dataType:"json",success:function(d){if(d.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=d.chrom_info;var f='';for(i in a.chrom_data){var e=a.chrom_data[i]["chrom"];f+='"}a.chrom_select.html(f);a.intro_div.show();a.content_div.hide();a.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())})},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}});this.content_div.bind("dblclick",function(d){a.zoom_in(d.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(d){this.current_x=d.offsetX}).bind("drag",function(d){var g=d.offsetX-this.current_x;this.current_x=d.offsetX;var f=Math.round(g/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-f)});this.viewport_container.bind("dragstart",function(d){this.original_low=a.low;this.current_height=d.clientY;this.current_x=d.offsetX;this.active=(d.clientX"+d.message+"",{Close:hide_modal})});a.content_div.append(e)}}else{if(d==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(d.data!==undefined&&(d.data===null||d.data.length===0)){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(d==="pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;b(d);a.draw()}}}}})}else{a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}}});var TiledTrack=function(){var c=this,b=c.view;if(c.display_modes!==undefined){if(c.mode_div===undefined){c.mode_div=$("").appendTo(c.header_div);var g=c.display_modes[0];c.mode=g;c.mode_div.text(g);var a=function(h){c.mode_div.text(h);c.mode=h;c.tile_cache.clear();c.draw()};var e={};for(var d in c.display_modes){var f=c.display_modes[d];e[f]=function(h){return function(){a(h)}}(f)}make_popupmenu(c.mode_div,e)}else{c.mode_div.hide()}}if(c.overview_check_div===undefined){c.overview_check_div=$("").css("margin-top","-3px").appendTo(c.header_div);c.overview_check=$("").appendTo(c.overview_check_div);c.overview_check.bind("click",function(){var h=this;b.overview_viewport.find("canvas").remove();c.set_overview();$(".overview_check").each(function(){if(this!==h){$(this).attr("checked",false)}})});c.overview_check_div.append($("").text("Overview"))}};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(){var j=this.view.low,e=this.view.high,f=e-j,d=this.view.resolution;var l=$(""),m=this.content_div.width()/f,h;this.content_div.children(":first").remove();this.content_div.append(l),this.max_height=0;var a=Math.floor(j/d/DENSITY);while((a*DENSITY*d)
').appendTo(this.chrom_form);this.zi_link=$("").click(function(){a.zoom_in();a.redraw()}).html('
').appendTo(this.chrom_form);$.ajax({url:chrom_url,data:(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}),dataType:"json",success:function(d){if(d.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=d.chrom_info;var f='';for(i in a.chrom_data){var e=a.chrom_data[i]["chrom"];f+='"}a.chrom_select.html(f);a.intro_div.show();a.content_div.hide();a.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())})},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}});this.content_div.bind("dblclick",function(d){a.zoom_in(d.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(d){this.current_x=d.offsetX}).bind("drag",function(d){var g=d.offsetX-this.current_x;this.current_x=d.offsetX;var f=Math.round(g/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-f)});this.viewport_container.bind("dragstart",function(d){this.original_low=a.low;this.current_height=d.clientY;this.current_x=d.offsetX;this.active=(d.clientX"+d.message+"",{Close:hide_modal})});a.content_div.append(e)}}else{if(d==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(d.data!==undefined&&(d.data===null||d.data.length===0)){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(d==="pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;b(d);a.draw()}}}}})}else{a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}}});var TiledTrack=function(){var c=this,b=c.view;if(c.display_modes!==undefined){if(c.mode_div===undefined){c.mode_div=$("").appendTo(c.header_div);var g=c.display_modes[0];c.mode=g;c.mode_div.text(g);var a=function(h){c.mode_div.text(h);c.mode=h;c.tile_cache.clear();c.draw()};var e={};for(var d in c.display_modes){var f=c.display_modes[d];e[f]=function(h){return function(){a(h)}}(f)}make_popupmenu(c.mode_div,e)}else{c.mode_div.hide()}}if(c.overview_check_div===undefined){c.overview_check_div=$("").css("margin-top","-3px").appendTo(c.header_div);c.overview_check=$("").appendTo(c.overview_check_div);c.overview_check.bind("click",function(){var h=this;b.overview_viewport.find("canvas").remove();c.set_overview();$(".overview_check").each(function(){if(this!==h){$(this).attr("checked",false)}})});c.overview_check_div.append($("").text("Overview"))}};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(){var j=this.view.low,e=this.view.high,f=e-j,d=this.view.resolution;var l=$(""),m=this.content_div.width()/f,h;this.content_div.children(":first").remove();this.content_div.append(l),this.max_height=0;var a=Math.floor(j/d/DENSITY);while((a*DENSITY*d)