diff --git a/eggs.ini b/eggs.ini index 7bec53d8b6f..06dca8b1bac 100644 --- a/eggs.ini +++ b/eggs.ini @@ -12,7 +12,7 @@ repository = http://eggs.g2.bx.psu.edu no_auto = pbs_python DRMAA_python [eggs:platform] -bx_python = 0.7.0 +bx_python = 0.7.1 Cheetah = 2.2.2 ctypes = 1.0.2 DRMAA_python = 0.2 @@ -67,7 +67,7 @@ Whoosh = 0.3.18 psycopg2 = _8.4.2_static pysqlite = _3.6.17_static MySQL_python = _5.1.41_static -bx_python = _494c2d1d68b3_rebuild1 +bx_python = _7b95ff194725 GeneTrack = _dev_48da9e998f0caf01c5be731e926f4b0481f658f0 SQLAlchemy = _dev_r6498 pysam = _kanwei_b10f6e722e9a diff --git a/lib/galaxy/datatypes/converters/interval_to_summary_tree_converter.py b/lib/galaxy/datatypes/converters/interval_to_summary_tree_converter.py index 2fb73a6e18d..f7f89dbf407 100644 --- a/lib/galaxy/datatypes/converters/interval_to_summary_tree_converter.py +++ b/lib/galaxy/datatypes/converters/interval_to_summary_tree_converter.py @@ -50,4 +50,4 @@ def main(): st.write(out_fname) if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/lib/galaxy/visualization/tracks/data_providers.py b/lib/galaxy/visualization/tracks/data_providers.py index 29cb08dece9..30792835d2d 100644 --- a/lib/galaxy/visualization/tracks/data_providers.py +++ b/lib/galaxy/visualization/tracks/data_providers.py @@ -2,14 +2,15 @@ Data providers for tracks visualizations. """ -import sys -from math import ceil, log +import sys, time +from math import ceil, log, sqrt import pkg_resources pkg_resources.require( "bx-python" ) if sys.version_info[:2] == (2, 4): pkg_resources.require( "ctypes" ) pkg_resources.require( "pysam" ) pkg_resources.require( "numpy" ) +import numpy from galaxy.datatypes.util.gff_util import * from galaxy.util.json import from_json_string from bx.interval_index_file import Indexes @@ -740,40 +741,73 @@ class BBIDataProvider( TracksDataProvider ): # Bigwig has the possibility of it being a standalone bigwig file, in which case we use # original_dataset, or coming from wig->bigwig conversion in which we use converted_dataset f, bbi = self._get_dataset() - + + # If the stats kwarg was provide, we compute overall summary data for + # the entire chromosome, but no reduced data -- currently only + # providing values used by trackster to determine the default range if 'stats' in kwargs: - all_dat = bbi.query(chrom, 0, 2147483647, 1) + # FIXME: use actual chromosome size + summary = bbi.summarize( chrom, 0, 214783647, 1 ) f.close() - if all_dat is None: + if summary is None: return None - - all_dat = all_dat[0] # only 1 summary - return { 'data' : { 'max': float( all_dat['max'] ), \ - 'min': float( all_dat['min'] ), \ - 'total_frequency': float( all_dat['coverage'] ) } \ - } - + else: + # Does the summary contain any defined values? + valid_count = summary.valid_count[0] + if summary.valid_count < 1: + return None + + # Compute $\mu \pm 2\sigma$ to provide an estimate for upper and lower + # bounds that contain ~95% of the data. + mean = summary.sum_data[0] / valid_count + var = summary.sum_squares[0] - mean + if valid_count > 1: + var /= valid_count - 1 + sd = numpy.sqrt( var ) + + return dict( data=dict( min=summary.min_val[0], max=summary.max_val[0], mean=mean, sd=sd ) ) + start = int(start) end = int(end) + + # The following seems not to work very well, for example it will only return one + # data point if the tile is 1280px wide. Not sure what the intent is. + # The first zoom level for BBI files is 640. If too much is requested, it will look at each block instead # of summaries. The calculation done is: zoom <> (end-start)/num_points/2. # Thus, the optimal number of points is (end-start)/num_points/2 = 640 # num_points = (end-start) / 1280 - num_points = (end-start) / 1280 - if num_points < 1: - num_points = end - start - else: - num_points = min(num_points, 500) + #num_points = (end-start) / 1280 + #if num_points < 1: + # num_points = end - start + #else: + # num_points = min(num_points, 500) - data = bbi.query(chrom, start, end, num_points) + # For now, we'll do 1000 data points by default However, the summaries + # don't seem to work when a summary pixel corresponds to less than one + # datapoint, so we prevent that. + # FIXME: need to switch over to using the full data at high levels of + # detail. + num_points = min( 1000, end - start ) + + summary = bbi.summarize( chrom, start, end, num_points ) f.close() - - pos = start - step_size = (end - start) / num_points + result = [] - if data: - for dat_dict in data: - result.append( (pos, float_nan(dat_dict['mean']) ) ) + + if summary: + mean = summary.sum_data / summary.valid_count + + ## Standard deviation by bin, not yet used + ## var = summary.sum_squares - mean + ## var /= minimum( valid_count - 1, 1 ) + ## sd = sqrt( var ) + + pos = start + step_size = (end - start) / num_points + + for i in range( num_points ): + result.append( (pos, float_nan( mean[i] ) ) ) pos += step_size return { 'data': result } diff --git a/lib/galaxy/web/controllers/tracks.py b/lib/galaxy/web/controllers/tracks.py index 68397d6a3be..3ae6cea5063 100644 --- a/lib/galaxy/web/controllers/tracks.py +++ b/lib/galaxy/web/controllers/tracks.py @@ -528,6 +528,7 @@ class TracksController( BaseUIController, UsesVisualization, UsesHistoryDatasetA if not standalone_provider.has_data( chrom ): return messages.NO_DATA valid_chroms = standalone_provider.valid_chroms() + # Have data if we get here return { "status": messages.DATA, "valid_chroms": valid_chroms } @@ -1041,4 +1042,4 @@ def _get_highest_priority_msg( message_list ): return_message = message elif return_message == None and message == messages.PENDING: return_message = message - return return_message \ No newline at end of file + return return_message diff --git a/static/june_2007_style/base.css.tmpl b/static/june_2007_style/base.css.tmpl index 998165bb0d7..d53be3086af 100644 --- a/static/june_2007_style/base.css.tmpl +++ b/static/june_2007_style/base.css.tmpl @@ -231,6 +231,10 @@ div.form-row-error-message { padding: 3px 0 0 1em; } +.form-row .help { + color: #666; +} + select, input, textarea { font: inherit; } diff --git a/static/june_2007_style/blue/base.css b/static/june_2007_style/blue/base.css index a6caed06955..70bc7fede74 100644 --- a/static/june_2007_style/blue/base.css +++ b/static/june_2007_style/blue/base.css @@ -43,6 +43,7 @@ div.form-row label.inline{display:inline;} div.form-row-input{float:left;} div.form-row-input label{font-weight:normal;display:inline;} div.form-row-error-message{width:300px;float:left;color:red;font-weight:bold;padding:3px 0 0 1em;} +.form-row .help{color:#666;} select,input,textarea{font:inherit;} select,textarea,input[type="text"],input[type="file"],input[type="password"]{-webkit-box-sizing:border-box;max-width:300px;} .errormessagelarge,.warningmessagelarge,.donemessagelarge,.infomessagelarge{padding:10px;padding-left:52px;min-height:32px;border:1px solid #AA6666;background-color:#FFCCCC;background-image:url(error_message_icon.png);background-repeat:no-repeat;background-position:10px 10px;} diff --git a/static/june_2007_style/blue/panel_layout.css b/static/june_2007_style/blue/panel_layout.css index 298ee40af41..5a3e2cf51d7 100644 --- a/static/june_2007_style/blue/panel_layout.css +++ b/static/june_2007_style/blue/panel_layout.css @@ -23,9 +23,11 @@ div.unified-panel-body{position:absolute;top:2em;bottom:0;width:100%;margin-top: .panel-header-button:hover{color:black;background-color:#ccc;} .panel-header-button:active{color:white;background-color:#aaaaaa;} #overlay{position:fixed;top:0;left:0;width:100%;height:100%;z-index:20000;} +#overlay.modal #overlay-background{background:rgba(0,0,0,0.5);} .dialog-box-container{position:relative;margin-top:80px;margin-right:auto;margin-left:auto;} .dialog-box-wrapper{position:relative;padding:1em;background-color:rgba(0,0,0,0.5);-moz-border-radius:1em;-webkit-border-radius:1em;} .dialog-box{border:solid #999 1px;background:white;z-index:80000;} +#overlay.modal .dialog-box .body{min-width:600px;} .dialog-box .body{padding:5px;overflow:auto;max-height:500px;min-width:300px;} .dialog-box .buttons{padding:5px;} .panel-error-message,.panel-warning-message,.panel-done-message,.panel-info-message{height:24px;line-height:24px;color:#303030;padding:0px;padding-left:26px;background-color:#FFCCCC;background-image:url(error_small.png);background-repeat:no-repeat;background-position:6px 50%;} diff --git a/static/june_2007_style/blue/trackster.css b/static/june_2007_style/blue/trackster.css index e59b26677a9..a9ba82ae395 100644 --- a/static/june_2007_style/blue/trackster.css +++ b/static/june_2007_style/blue/trackster.css @@ -3,30 +3,9 @@ .content{font:10px verdana;} .nav-controls{text-align:center;padding:1px 0;} .nav-controls input{margin:0 5px;} -.menu-button{padding: 0px 4px 0px 4px;} #zoom-in,#zoom-out{display:inline-block;height:16px;width:16px;margin-bottom:-3px;cursor:pointer;} #zoom-out{background:transparent url(../images/fugue/magnifier-zoom-out.png) center center no-repeat;} #zoom-in{margin-left:10px;background:transparent url(../images/fugue/magnifier-zoom.png) center center no-repeat;} -.overview-icon{background:transparent url(../images/fugue/application-dock-270-bw.png) no-repeat;} -.overview-icon:hover{background:transparent url(../images/fugue/application-dock-270.png) no-repeat;} -.settings-icon{background:transparent url(../images/fugue/gear-bw.png) no-repeat;} -.settings-icon:hover{background:transparent url(../images/fugue/gear.png) no-repeat;} -.tools-icon{background:transparent url(../images/fugue/toolbox-bw.png) no-repeat;} -.tools-icon:hover{background:transparent url(../images/fugue/toolbox.png) no-repeat;} -.filters-icon{background:transparent url(../images/fugue/ui-slider-050-bw.png) no-repeat;} -.filters-icon:hover{background:transparent url(../images/fugue/ui-slider-050.png) no-repeat;} -.remove-icon,.overview-close{background:transparent url(../images/fugue/cross-small-bw.png) no-repeat;} -.remove-icon:hover,.overview-close:hover{background:transparent url(../images/fugue/cross-circle.png) no-repeat;} -#close-icon{background:transparent url(../images/fugue/cross-circle-bw.png) no-repeat;margin-right:0px;} -#close-icon:hover{background:transparent url(../images/fugue/cross-circle.png) no-repeat;} -#add-tracks-icon{background:transparent url(../images/fugue/plus-button-bw.png) no-repeat;} -#add-tracks-icon:hover{background:transparent url(../images/fugue/plus-button.png) no-repeat;} -#add-group-icon{background:transparent url(../images/fugue/block--plus-bw.png) no-repeat;} -#add-group-icon:hover{background:transparent url(../images/fugue/block--plus.png) no-repeat;} -#bookmarks-icon{background:transparent url(../images/fugue/bookmarks-bw.png) no-repeat;} -#bookmarks-icon:hover{background:transparent url(../images/fugue/bookmarks.png) no-repeat;} -#save-icon{background:transparent url(../images/fugue/disk--arrow-bw.png) no-repeat;} -#save-icon:hover{background:transparent url(../images/fugue/disk--arrow.png) no-repeat;} .nav-input{font-size:12px;width:30em;z-index:1000;} .location{display:inline-block;width:15em;margin:0 10px;} .draghandle{margin-top:2px;cursor:move;float:left;background:transparent url(../images/visualization/draggable_horizontal.png) center center no-repeat;width:10px;height:12px;} @@ -65,16 +44,39 @@ 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;} +.filters > .sliders,.display-controls{float:left;margin:1em;} .sliders{width:410px;} -.display-controls{border-left:solid 2px #DDDDDD;padding-left:1em} -.filter-row{margin-top:0.4em;} +.display-controls{border-left:solid 2px #DDDDDD;padding-left:1em +} +.filter-row { + margin-top:0.4em;} .slider-row{margin-left:1em;} .elt-label{float:left;font-weight:bold;margin-right:1em;} .slider{float:right;width:200px;position:relative;} .tool-name{font-size:110%;font-weight:bold;} .param-row{margin-top:0.2em;margin-left:1em;} .param-label{float:left;font-weight:bold;padding-top:0.2em;} +.menu-button{padding:0px 4px 0px 4px;} +.settings-icon{background:transparent url(../images/fugue/gear-bw.png) no-repeat;} +.settings-icon:hover{background:transparent url(../images/fugue/gear.png) no-repeat;} +.overview-icon{background:transparent url(../images/fugue/application-dock-270-bw.png) no-repeat;} +.overview-icon:hover{background:transparent url(../images/fugue/application-dock-270.png) no-repeat;} +.tools-icon{background:transparent url(../images/fugue/toolbox-bw.png) no-repeat;} +.tools-icon:hover{background:transparent url(../images/fugue/toolbox.png) no-repeat;} +.filters-icon{background:transparent url(../images/fugue/ui-slider-050-bw.png) no-repeat;} +.filters-icon:hover{background:transparent url(../images/fugue/ui-slider-050.png) no-repeat;} +.remove-icon,.overview-close{background:transparent url(../images/fugue/cross-small-bw.png) no-repeat;} +.remove-icon:hover,.overview-close:hover{background:transparent url(../images/fugue/cross-circle.png) no-repeat;} +#close-icon{background:transparent url(../images/fugue/cross-circle-bw.png) no-repeat;margin-right:0px;} +#close-icon:hover{background:transparent url(../images/fugue/cross-circle.png) no-repeat;} +#add-tracks-icon{background:transparent url(../images/fugue/plus-button-bw.png) no-repeat;} +#add-tracks-icon:hover{background:transparent url(../images/fugue/plus-button.png) no-repeat;} +#add-group-icon{background:transparent url(../images/fugue/block--plus-bw.png) no-repeat;} +#add-group-icon:hover{background:transparent url(../images/fugue/block--plus.png) no-repeat;} +#bookmarks-icon{background:transparent url(../images/fugue/bookmarks-bw.png) no-repeat;} +#bookmarks-icon:hover{background:transparent url(../images/fugue/bookmarks.png) no-repeat;} +#save-icon{background:transparent url(../images/fugue/disk--arrow-bw.png) no-repeat;} +#save-icon:hover{background:transparent url(../images/fugue/disk--arrow.png) no-repeat;} .child-track-icon{background:url('../images/fugue/arrow-000-small-bw.png') no-repeat;width:30px;cursor:move;} .track-resize{background:white url('../images/visualization/draggable_vertical.png') no-repeat top center;position:absolute;right:3px;bottom:-4px;width:14px;height:7px;border:solid #999 1px;z-index:100;} .bookmark{background:white;border:solid #999 1px;border-right:none;margin:0.5em;margin-right:0;padding:0.5em;} @@ -85,4 +87,5 @@ input{font:10px verdana;} .icon.more-across{background:url('../images/fugue/arrow-transition-bw.png') no-repeat 0px 0px;} .intro{padding:1em;} .intro > .action-button{background-color:#CCC;padding:1em;} -.feature-popup{background-color:#DDD;position:absolute;z-index:1000} +.feature-popup{position:absolute;z-index:1000;padding:5px;font-size:10px;filter:alpha(opacity=80);background-repeat:no-repeat;background-image:url(../images/tipsy.gif);background-position:top center;} +.feature-popup-inner{padding:5px 8px 4px 8px;background-color:black;color:white;} diff --git a/static/june_2007_style/panel_layout.css.tmpl b/static/june_2007_style/panel_layout.css.tmpl index 614079a91a4..292501dda9c 100644 --- a/static/june_2007_style/panel_layout.css.tmpl +++ b/static/june_2007_style/panel_layout.css.tmpl @@ -161,6 +161,10 @@ div.unified-panel-body { z-index: 20000; } +#overlay.modal #overlay-background { + background: rgba(0,0,0,0.5); +} + .dialog-box-container { position: relative; margin-top: 80px; @@ -182,6 +186,10 @@ div.unified-panel-body { z-index: 80000; } +#overlay.modal .dialog-box .body { + min-width: 600px; +} + .dialog-box .body { padding: 5px; overflow: auto; diff --git a/static/june_2007_style/trackster.css.tmpl b/static/june_2007_style/trackster.css.tmpl index 16e92729a7c..a902ec965d0 100644 --- a/static/june_2007_style/trackster.css.tmpl +++ b/static/june_2007_style/trackster.css.tmpl @@ -405,8 +405,19 @@ input { background-color: #CCC; padding: 1em; } -.feature-popup{ - background-color: #DDD; + +.feature-popup { position: absolute; - z-index: 1000 + z-index: 1000; + padding: 5px; + font-size: 10px; + filter: alpha(opacity=80); + background-repeat: no-repeat; + background-image: url(../images/tipsy.gif); + background-position: top center; +} +.feature-popup-inner { + padding: 5px 8px 4px 8px; + background-color: black; + color: white; } diff --git a/static/scripts/galaxy.panels.js b/static/scripts/galaxy.panels.js index be187d8fb57..37adce6b7e2 100644 --- a/static/scripts/galaxy.panels.js +++ b/static/scripts/galaxy.panels.js @@ -163,13 +163,23 @@ function make_right_panel( panel_el, center_el, border_el ) { // Modal dialog boxes function hide_modal() { - $(".dialog-box-container" ).fadeOut( function() { + $(".dialog-box-container" ).hide( 0, function() { $("#overlay").hide(); + $("#overlay").removeClass( "modal" ); $( ".dialog-box" ).find( ".body" ).children().remove(); } ); }; -function show_modal( title, body, buttons, extra_buttons, init_fn ) { +function show_modal() { + $("#overlay").addClass( "modal" ); + _show_modal.apply( this, arguments ); +} + +function show_message() { + _show_modal.apply( this, arguments ); +} + +function _show_modal( title, body, buttons, extra_buttons, init_fn ) { if ( title ) { $( ".dialog-box" ).find( ".title" ).html( title ); $( ".dialog-box" ).find( ".unified-panel-header" ).show(); @@ -205,7 +215,7 @@ function show_modal( title, body, buttons, extra_buttons, init_fn ) { $( ".dialog-box" ).find( ".body" ).html( body ); if ( ! $(".dialog-box-container").is( ":visible" ) ) { $("#overlay").show(); - $(".dialog-box-container").fadeIn(); + $(".dialog-box-container").show(); } // Fix min-width so that modal cannot shrink considerably if // new content is loaded. diff --git a/static/scripts/trackster.js b/static/scripts/trackster.js index bf57da53f95..5875baee4e9 100644 --- a/static/scripts/trackster.js +++ b/static/scripts/trackster.js @@ -701,7 +701,7 @@ extend(Drawable.prototype, { remove: function() { this.container.remove_drawable(this); - this.container_div.fadeOut('slow', function() { + this.container_div.hide(0, function() { $(this).remove(); // HACK: is there a better way to update the view? view.update_intro_div(); @@ -1027,6 +1027,7 @@ extend( View.prototype, DrawableCollection.prototype, { // Only act on x axis scrolling if we see if, y will be i // handled by the browser when the event bubbles up if ( dx ) { + dx *= 50; var delta_chrom = Math.round( - dx / view.viewport_container.width() * (view.high - view.low) ); view.move_delta( delta_chrom ); } @@ -1255,7 +1256,7 @@ extend( View.prototype, DrawableCollection.prototype, { DrawableCollection.prototype.remove_drawable.call(this, drawable); if (hide) { var view = this; - drawable.container_div.fadeOut('slow', function() { + drawable.container_div.hide(0, function() { $(this).remove(); view.update_intro_div(); }); @@ -2114,8 +2115,14 @@ extend(DrawableConfig.prototype, { build_form: function() { var track_config = this; var container = $("
"); - $.each( this.params, function( index, param ) { - if ( ! param.hidden ) { + var param; + // Function to process parameters recursively + function handle_params( params, container ) { + for ( var index = 0; index < params.length; index++ ) { + param = params[index]; + // Hidden params have no representation in the form + if ( param.hidden ) { continue; } + // Build row for param var id = 'param_' + index; var value = track_config.values[ param.key ]; var row = $("").appendTo( container ); @@ -2127,18 +2134,19 @@ extend(DrawableConfig.prototype, { } else if ( param.type === 'color' ) { var input = $('').attr("id", id ).attr("name", id ).val( value ); // Color picker in tool tip style float - var tip = $( "" ).hide(); + var tip = $( "" ).hide(); // Inner div for padding purposes var tip_inner = $("").appendTo(tip); var farb_container = $("") .appendTo(tip_inner) .farbtastic( { width: 100, height: 100, callback: input, color: value }); - // Outer div container input and tip for hover to work $("").append( input ).append( tip ).appendTo( row ).bind( "click", function ( e ) { tip.css( { - left: $(this).position().left + ( $(input).width() / 2 ) - 60, - top: $(this).position().top + $(this.height) + // left: $(this).position().left + ( $(input).width() / 2 ) - 60, + // top: $(this).position().top + $(this.height) + left: $(this).position().left + $(input).width() + 5, + top: $(this).position().top - ( $(tip).height() / 2 ) + ( $(input).height() / 2 ) } ).show(); $(document).bind( "click.color-picker", function() { tip.hide(); @@ -2150,8 +2158,15 @@ extend(DrawableConfig.prototype, { else { row.append( $('').attr("id", id ).attr("name", id ).val( value ) ); } + // Help text + if ( param.help ) { + row.append( $("").text( param.help ) ); + } } - }); + } + // Handle top level parameters in order + handle_params( this.params, container ); + // Return element containing constructed form return container; }, update_from_form: function( container ) { @@ -2229,7 +2244,16 @@ FeatureTrackTile.prototype.predisplay_actions = function() { // Only show popups in Pack mode. if (tile.mode !== "Pack") { return; } - $(this.canvas).mousemove(function (e) { + $(this.canvas).hover( function() { + this.hovered = true; + $(this).mousemove(); + }, function() { + this.hovered = false; + // Clear popup if it is still hanging around (this is probably not needed) + $(this).siblings(".feature-popup").remove(); + } ).mousemove(function (e) { + // Use the hover plugin to get a delay before showing popup + if ( !this.hovered ) { return; } // Get feature data for position. var this_offset = $(this).offset(), @@ -2270,8 +2294,8 @@ FeatureTrackTile.prototype.predisplay_actions = function() { // Build popup. var popup = $("").attr("id", feature_uid).addClass("feature-popup"), - key, value, - table = $("