2 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/changeset/5027e0458ef0/ changeset: 5027e0458ef0 user: carlfeberhard date: 2012-09-17 23:12:42 summary: initial, un-wired prototype for scatterplot visualization affected #: 6 files diff -r 65ecf4e0ed28eaa2f3e64495ab800aa7c9779a54 -r 5027e0458ef06686cbf56770c5e02e9d5d1673c1 lib/galaxy/visualization/data_providers/basic.py --- a/lib/galaxy/visualization/data_providers/basic.py +++ b/lib/galaxy/visualization/data_providers/basic.py @@ -90,6 +90,11 @@ break fields = line.split() + #pre: column indeces should be avail in fields + for col_index in cols: + assert col_index < len( fields ), ( + "column index (%d) must be less than fields length: %d" % ( col_index, len( fields ) ) ) + data.append( [ cast_val( fields[c], self.original_dataset.metadata.column_types[c] ) for c in cols ] ) f.close() diff -r 65ecf4e0ed28eaa2f3e64495ab800aa7c9779a54 -r 5027e0458ef06686cbf56770c5e02e9d5d1673c1 lib/galaxy/web/api/datasets.py --- a/lib/galaxy/web/api/datasets.py +++ b/lib/galaxy/web/api/datasets.py @@ -215,8 +215,14 @@ # Return data. data = None data_provider = trans.app.data_provider_registry.get_data_provider( raw=True, original_dataset=dataset ) + if data_provider == ColumnDataProvider: + #pre: should have column kwargs + #print 'kwargs:', kwargs + assert 'cols' in kwargs, ( + "ColumnDataProvider needs a 'cols' parameter in the query string" ) data = data_provider( original_dataset=dataset ).get_data( **kwargs ) + else: # Default to genomic data. # FIXME: need better way to set dataset_type. diff -r 65ecf4e0ed28eaa2f3e64495ab800aa7c9779a54 -r 5027e0458ef06686cbf56770c5e02e9d5d1673c1 lib/galaxy/web/controllers/visualization.py --- a/lib/galaxy/web/controllers/visualization.py +++ b/lib/galaxy/web/controllers/visualization.py @@ -6,6 +6,7 @@ from galaxy.web.controllers.library import LibraryListGrid from galaxy.visualization.genomes import decode_dbkey from galaxy.visualization.genome.visual_analytics import get_dataset_job +from galaxy.visualization.data_providers.basic import ColumnDataProvider # # -- Grids -- @@ -801,6 +802,28 @@ def get_item( self, trans, id ): return self.get_visualization( trans, id ) + @web.expose + def scatterplot( self, trans, dataset_id, cols ): + # Get HDA. + hda = self.get_dataset( trans, dataset_id, check_ownership=False, check_accessible=True ) + + # get some metadata for the page + hda_dict = hda.get_api_value() + #title = "Scatter plot of {name}:".format( **hda_dict ) + #subtitle = "{misc_info}".format( **hda_dict ) + + #TODO: add column data + # Read data. + data_provider = ColumnDataProvider( original_dataset=hda ) + data = data_provider.get_data( cols ) + + # Return plot. + return trans.fill_template_mako( "visualization/scatterplot.mako", + title=hda.name, subtitle=hda.info, + hda=hda, + data=data ) + + @web.json def bookmarks_from_dataset( self, trans, hda_id=None, ldda_id=None ): if hda_id: diff -r 65ecf4e0ed28eaa2f3e64495ab800aa7c9779a54 -r 5027e0458ef06686cbf56770c5e02e9d5d1673c1 templates/root/history.mako --- a/templates/root/history.mako +++ b/templates/root/history.mako @@ -17,7 +17,16 @@ <meta http-equiv="Pragma" content="no-cache"> ${h.css( "base", "history", "autocomplete_tagging" )} -${h.js( "libs/jquery/jquery", "libs/bootstrap", "galaxy.base", "libs/json2", "libs/jquery/jstorage", "libs/jquery/jquery.autocomplete", "galaxy.autocom_tagging" )} +${h.js( + "libs/jquery/jquery", + "libs/bootstrap", + "galaxy.base", + "libs/json2", + "libs/jquery/jstorage", + "libs/jquery/jquery.autocomplete", + "galaxy.autocom_tagging", + "libs/underscore" +)} <script type="text/javascript"> @@ -289,8 +298,61 @@ }); } - init_trackster_links(); + /** + * Create popup menu for visualization icon. + */ + function init_viz_icon(icon) { + var icon_link = $(icon); + make_popupmenu( icon_link , { + "${_("Trackster")}": function() { + $.ajax({ + url: icon_link.attr("data-url"), + dataType: "html", + error: function() { alert( "Could not add this dataset to browser." ); }, + success: function(table_html) { + var parent = window.parent; + parent.show_modal("View Data in a New or Saved Visualization", "", { + "Cancel": function() { + parent.hide_modal(); + }, + "View in saved visualization": function() { + // Show new modal with saved visualizations. + parent.hide_modal(); + parent.show_modal("Add Data to Saved Visualization", table_html, { + "Cancel": function() { + parent.hide_modal(); + }, + "Add to visualization": function() { + $(parent.document).find('input[name=id]:checked').each(function() { + var vis_id = $(this).val(); + parent.location = icon_link.attr("action-url") + "&id=" + vis_id; + }); + }, + }); + }, + "View in new visualization": function() { + parent.location = icon_link.attr("new-url"); + } + }); + } + }); + }, + //"${_("Scatterplot")}": function() { + // var data_id = icon_link.parents(".historyItemContainer").attr("id").split("-")[1]; + // parent.galaxy_main.location = + // "${h.url_for( controller='visualization', action='scatterplot', col1=9, col2=13 )}" + // + "&dataset_id=" + data_id; + //} + } ); + return icon; + }; + + _.each( $(".visualize-icon"), function(icon) { + console.debug( 'Init visualization icons, icon:', icon ); + init_viz_icon(icon); + }); + function init_phyloviz_links() { // PhyloViz links // Add to trackster browser functionality diff -r 65ecf4e0ed28eaa2f3e64495ab800aa7c9779a54 -r 5027e0458ef06686cbf56770c5e02e9d5d1673c1 templates/root/history_common.mako --- a/templates/root/history_common.mako +++ b/templates/root/history_common.mako @@ -234,9 +234,12 @@ else: data_url = h.url_for( controller='visualization', action='list_tracks' ) %> - <a href="javascript:void(0)" data-url="${data_url}" class="icon-button chart_curve tooltip trackster-add" - action-url="${h.url_for( controller='visualization', action='trackster', dataset_id=dataset_id)}" - new-url="${h.url_for( controller='visualization', action='trackster', dataset_id=dataset_id, default_dbkey=data.dbkey)}" title="View in Trackster"></a> + <!--<a href="javascript:void(0)" data-url="${data_url}" class="icon-button chart_curve tooltip trackster-add"--> + <!-- action-url="${h.url_for( controller='visualization', action='trackster', dataset_id=dataset_id)}"--> + <!-- new-url="${h.url_for( controller='visualization', action='trackster', dataset_id=dataset_id, default_dbkey=data.dbkey)}" title="View in Trackster"></a>--> + <a href="javascript:void(0)" data-url="${data_url}" class="icon-button chart_curve tooltip visualize-icon" + action-url="${h.url_for( controller='tracks', action='browser', dataset_id=dataset_id)}" + new-url="${h.url_for( controller='tracks', action='index', dataset_id=dataset_id, default_dbkey=data.dbkey)}" title="Visualize"></a> %endif <% isPhylogenyData = isinstance(data.datatype, (Phyloxml, Nexus, Newick)) diff -r 65ecf4e0ed28eaa2f3e64495ab800aa7c9779a54 -r 5027e0458ef06686cbf56770c5e02e9d5d1673c1 templates/visualization/scatterplot.mako --- /dev/null +++ b/templates/visualization/scatterplot.mako @@ -0,0 +1,205 @@ +<%inherit file="/base.mako"/> + +<%def name="stylesheets()"> +${parent.stylesheets()} +${h.css( "history", "autocomplete_tagging", "trackster", "overcast/jquery-ui-1.8.5.custom", "library" )} + +<style type="text/css"> +* { margin: 0px, padding: 0px; } + +.subtitle { + margin-left: 1em; + margin-top: -1em; + color: grey; + font-size: small; +} + +.chart { + /*shape-rendering: crispEdges;*/ +} + +.grid-line { + fill: none; + stroke: lightgrey; + stroke-opacity: 0.5; + shape-rendering: crispEdges; + stroke-dasharray: 3, 3; +} + +.axis path, .axis line { + fill: none; + stroke: black; + shape-rendering: crispEdges; +} +.axis text { + font-family: sans-serif; + font-size: 12px; +} + + +circle.bubble { + stroke: none; + fill: black; + fill-opacity: 0.2; +} + +</style> + +</%def> + +<%def name="javascripts()"> +${parent.javascripts()} +${h.js( "libs/d3" )} + +<script type="text/javascript"> +/* ============================================================================= +todo: + validate columns (here or server) + send: type, column title/name in JSON + + + move to obj, possibly view? + fetch (new?) data + config changes to the graph + download svg (png?) + +============================================================================= */ +function translateStr( x, y ){ + return 'translate(' + x + ',' + y + ')'; +} +function rotateStr( d, x, y ){ + return 'rotate(' + d + ',' + x + ',' + y + ')'; +} + +$(function() { + // Constants + var data = ${data}, + MAX_DATA_POINTS = 30000, + BUBBLE_RADIUS = 5, + ENTRY_ANIM_DURATION = 500, + X_TICKS = 10, Y_TICKS = 10, + X_AXIS_LABEL_BUMP_Y = 40, + Y_AXIS_LABEL_BUMP_X = -35, + WIDTH = 300, + HEIGHT = 300, + MARGIN= 50, + xLabel = "Magnitude", + yLabel = "Depth"; + + // set a cap on the data, limit to first n points + data = data.slice( 0, MAX_DATA_POINTS ); + + // split the data into columns + //TODO: compute min, max on server. + var col1_data = data.map( function(e) { return e[0] }), + col2_data = data.map( function(e) { return e[1] }), + xMin = d3.min( col1_data ), + xMax = d3.max( col1_data ), + yMin = d3.min( col2_data ), + yMax = d3.max( col2_data ); + console.log( 'col1_data:', col1_data ); + console.log( 'col2_data:', col2_data ); + console.log( 'xMin, xMax, yMin, yMax:', xMin, xMax, yMin, yMax ); + + // Set up. + d3.select( "body" ).append( "svg:svg" ) + .attr( "width", WIDTH + ( MARGIN * 2 ) ) + .attr( "height", HEIGHT + ( MARGIN * 2 ) ) + .attr( "class", "chart" ); + + // Scale for x, y based on data domains + // origin: bottom, left + var x_scale = d3.scale.linear() + .domain([ xMin, xMax ]) + .range([ 0, WIDTH ]), + y_scale = d3.scale.linear() + .domain([ yMin, yMax ]) + .range([ HEIGHT, 0 ]); + + // Selection of SVG, append group (will group our entire chart), give attributes + // apply a group and transform all coords away from margins + var chart = d3.select( ".chart" ).append( "svg:g" ) + .attr( "class", "content" ) + .attr( "transform", translateStr( MARGIN, MARGIN ) ); + + // axes + var xAxisFn = d3.svg.axis() + .scale( x_scale ) + .ticks( X_TICKS ) + .orient( 'bottom' ); + var xAxis = chart.append( 'g' ).attr( 'class', 'axis' ).attr( 'id', 'x-axis' ) + .attr( 'transform', translateStr( 0, HEIGHT ) ) + .call( xAxisFn ) + console.debug( 'xAxis:', xAxis ); window.xAxis = xAxis, window.xAxisFn = xAxisFn; + + var xAxisLabel = xAxis.append( 'text' ).attr( 'class', 'axis-label' ).attr( 'id', 'x-axis-label' ) + .attr( 'x', WIDTH / 2 ) + .attr( 'y', X_AXIS_LABEL_BUMP_Y ) + .attr( 'text-anchor', 'middle' ) + .text( xLabel ); + console.debug( 'xAxisLabel:', xAxisLabel ); window.xAxisLabel = xAxisLabel; + + var yAxisFn = d3.svg.axis() + .scale( y_scale ) + .ticks( Y_TICKS ) + .orient( 'left' ); + var yAxis = chart.append( 'g' ).attr( 'class', 'axis' ).attr( 'id', 'y-axis' ) + .call( yAxisFn ); + console.debug( 'yAxis:', yAxis ); window.yAxis = yAxis, window.yAxisFn = yAxisFn; + + var yAxisLabel = yAxis.append( 'text' ).attr( 'class', 'axis-label' ).attr( 'id', 'y-axis-label' ) + .attr( 'x', Y_AXIS_LABEL_BUMP_X ) + .attr( 'y', HEIGHT / 2 ) + .attr( 'text-anchor', 'middle' ) + .attr( 'transform', rotateStr( -90, Y_AXIS_LABEL_BUMP_X, HEIGHT / 2 ) ) + .text( yLabel ); + console.debug( 'yAxisLabel:', yAxisLabel ); window.yAxisLabel = yAxisLabel; + + // grid lines + var hGridLines = chart.selectAll( '.h-grid-line' ) + .data( x_scale.ticks( xAxisFn.ticks()[0] ) ) + .enter().append( 'svg:line' ) + .classed( 'grid-line h-grid-line', true ) + .attr( 'x1', x_scale ).attr( 'y1', 0 ) + .attr( 'x2', x_scale ).attr( 'y2', HEIGHT ) + console.debug( 'hGridLines:', hGridLines ); window.hGridLines = hGridLines; + + var vGridLines = chart.selectAll( '.v-grid-line' ) + .data( y_scale.ticks( yAxisFn.ticks()[0] ) ) + .enter().append( 'svg:line' ) + .classed( 'grid-line v-grid-line', true ) + .attr( 'x1', 0 ) .attr( 'y1', y_scale ) + .attr( 'x2', WIDTH ).attr( 'y2', y_scale ) + console.debug( 'vGridLines:', vGridLines ); window.vGridLines = vGridLines; + + // Functions used to render plot. + var xPosFn = function( d, i ){ + return x_scale( col1_data[ i ] ); + }; + var yPosFn = function( d, i ){ + return y_scale( col2_data[ i ] ); + }; + + // Create bubbles for each data point. + chart.selectAll( "circle.bubble" ) + .data(data).enter() + .append( "svg:circle" ).attr( "class", "bubble" ) + // start all bubbles at corner... + .attr( "r", 0 ) + .attr( "fill", "white" ) + // ...animate to final position + .transition().duration( ENTRY_ANIM_DURATION ) + .attr("cx", xPosFn ) + .attr("cy", yPosFn ) + .attr("r", BUBBLE_RADIUS); + + //TODO: on hover red line to axes, display values +}); +</script> +</%def> + +<%def name="body()"> + <h1 class="title">Scatterplot of '${title}':</h1> + <h2 class="subtitle">${subtitle}</h2> + +</%def> https://bitbucket.org/galaxy/galaxy-central/changeset/833f02590bbd/ changeset: 833f02590bbd user: carlfeberhard date: 2012-09-17 23:19:53 summary: scatterplot.mako: some cleanup affected #: 4 files diff -r 5027e0458ef06686cbf56770c5e02e9d5d1673c1 -r 833f02590bbd11f8ed1bdc024b380c1bb185bfae lib/galaxy/web/api/datasets.py --- a/lib/galaxy/web/api/datasets.py +++ b/lib/galaxy/web/api/datasets.py @@ -219,6 +219,7 @@ if data_provider == ColumnDataProvider: #pre: should have column kwargs #print 'kwargs:', kwargs + #TODO??: could default to first two here assert 'cols' in kwargs, ( "ColumnDataProvider needs a 'cols' parameter in the query string" ) data = data_provider( original_dataset=dataset ).get_data( **kwargs ) diff -r 5027e0458ef06686cbf56770c5e02e9d5d1673c1 -r 833f02590bbd11f8ed1bdc024b380c1bb185bfae templates/root/history.mako --- a/templates/root/history.mako +++ b/templates/root/history.mako @@ -349,7 +349,6 @@ }; _.each( $(".visualize-icon"), function(icon) { - console.debug( 'Init visualization icons, icon:', icon ); init_viz_icon(icon); }); diff -r 5027e0458ef06686cbf56770c5e02e9d5d1673c1 -r 833f02590bbd11f8ed1bdc024b380c1bb185bfae templates/root/history_common.mako --- a/templates/root/history_common.mako +++ b/templates/root/history_common.mako @@ -234,9 +234,6 @@ else: data_url = h.url_for( controller='visualization', action='list_tracks' ) %> - <!--<a href="javascript:void(0)" data-url="${data_url}" class="icon-button chart_curve tooltip trackster-add"--> - <!-- action-url="${h.url_for( controller='visualization', action='trackster', dataset_id=dataset_id)}"--> - <!-- new-url="${h.url_for( controller='visualization', action='trackster', dataset_id=dataset_id, default_dbkey=data.dbkey)}" title="View in Trackster"></a>--><a href="javascript:void(0)" data-url="${data_url}" class="icon-button chart_curve tooltip visualize-icon" action-url="${h.url_for( controller='tracks', action='browser', dataset_id=dataset_id)}" new-url="${h.url_for( controller='tracks', action='index', dataset_id=dataset_id, default_dbkey=data.dbkey)}" title="Visualize"></a> diff -r 5027e0458ef06686cbf56770c5e02e9d5d1673c1 -r 833f02590bbd11f8ed1bdc024b380c1bb185bfae templates/visualization/scatterplot.mako --- a/templates/visualization/scatterplot.mako +++ b/templates/visualization/scatterplot.mako @@ -56,7 +56,6 @@ todo: validate columns (here or server) send: type, column title/name in JSON - move to obj, possibly view? fetch (new?) data @@ -97,9 +96,9 @@ xMax = d3.max( col1_data ), yMin = d3.min( col2_data ), yMax = d3.max( col2_data ); - console.log( 'col1_data:', col1_data ); - console.log( 'col2_data:', col2_data ); - console.log( 'xMin, xMax, yMin, yMax:', xMin, xMax, yMin, yMax ); + //console.log( 'col1_data:', col1_data ); + //console.log( 'col2_data:', col2_data ); + //console.log( 'xMin, xMax, yMin, yMax:', xMin, xMax, yMin, yMax ); // Set up. d3.select( "body" ).append( "svg:svg" ) @@ -130,14 +129,14 @@ var xAxis = chart.append( 'g' ).attr( 'class', 'axis' ).attr( 'id', 'x-axis' ) .attr( 'transform', translateStr( 0, HEIGHT ) ) .call( xAxisFn ) - console.debug( 'xAxis:', xAxis ); window.xAxis = xAxis, window.xAxisFn = xAxisFn; + //console.debug( 'xAxis:', xAxis ); window.xAxis = xAxis, window.xAxisFn = xAxisFn; var xAxisLabel = xAxis.append( 'text' ).attr( 'class', 'axis-label' ).attr( 'id', 'x-axis-label' ) .attr( 'x', WIDTH / 2 ) .attr( 'y', X_AXIS_LABEL_BUMP_Y ) .attr( 'text-anchor', 'middle' ) .text( xLabel ); - console.debug( 'xAxisLabel:', xAxisLabel ); window.xAxisLabel = xAxisLabel; + //console.debug( 'xAxisLabel:', xAxisLabel ); window.xAxisLabel = xAxisLabel; var yAxisFn = d3.svg.axis() .scale( y_scale ) @@ -145,7 +144,7 @@ .orient( 'left' ); var yAxis = chart.append( 'g' ).attr( 'class', 'axis' ).attr( 'id', 'y-axis' ) .call( yAxisFn ); - console.debug( 'yAxis:', yAxis ); window.yAxis = yAxis, window.yAxisFn = yAxisFn; + //console.debug( 'yAxis:', yAxis ); window.yAxis = yAxis, window.yAxisFn = yAxisFn; var yAxisLabel = yAxis.append( 'text' ).attr( 'class', 'axis-label' ).attr( 'id', 'y-axis-label' ) .attr( 'x', Y_AXIS_LABEL_BUMP_X ) @@ -153,7 +152,7 @@ .attr( 'text-anchor', 'middle' ) .attr( 'transform', rotateStr( -90, Y_AXIS_LABEL_BUMP_X, HEIGHT / 2 ) ) .text( yLabel ); - console.debug( 'yAxisLabel:', yAxisLabel ); window.yAxisLabel = yAxisLabel; + //console.debug( 'yAxisLabel:', yAxisLabel ); window.yAxisLabel = yAxisLabel; // grid lines var hGridLines = chart.selectAll( '.h-grid-line' ) @@ -162,7 +161,7 @@ .classed( 'grid-line h-grid-line', true ) .attr( 'x1', x_scale ).attr( 'y1', 0 ) .attr( 'x2', x_scale ).attr( 'y2', HEIGHT ) - console.debug( 'hGridLines:', hGridLines ); window.hGridLines = hGridLines; + //console.debug( 'hGridLines:', hGridLines ); window.hGridLines = hGridLines; var vGridLines = chart.selectAll( '.v-grid-line' ) .data( y_scale.ticks( yAxisFn.ticks()[0] ) ) @@ -170,7 +169,7 @@ .classed( 'grid-line v-grid-line', true ) .attr( 'x1', 0 ) .attr( 'y1', y_scale ) .attr( 'x2', WIDTH ).attr( 'y2', y_scale ) - console.debug( 'vGridLines:', vGridLines ); window.vGridLines = vGridLines; + //console.debug( 'vGridLines:', vGridLines ); window.vGridLines = vGridLines; // Functions used to render plot. var xPosFn = function( d, i ){ 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.