commit/galaxy-central: 3 new changesets
3 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/changeset/0941c74d1d05/ changeset: 0941c74d1d05 user: carlfeberhard date: 2012-11-20 21:30:22 summary: scatterplot: add ability to auto-render based on query string affected #: 4 files diff -r 67b9614dcab440027292c5dc387ef2eb1a763c19 -r 0941c74d1d058ad6183347417e45fd5fd1528501 lib/galaxy/webapps/galaxy/controllers/visualization.py --- a/lib/galaxy/webapps/galaxy/controllers/visualization.py +++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py @@ -786,6 +786,9 @@ @web.expose def scatterplot( self, trans, dataset_id, **kwargs ): + """ + Returns a page that controls and renders a scatteplot graph. + """ # Get HDA. hda = self.get_dataset( trans, dataset_id, check_ownership=False, check_accessible=True ) hda_dict = hda.get_api_value() @@ -793,6 +796,7 @@ if( hda_dict[ 'metadata_column_names' ] == None and hasattr( hda.datatype, 'column_names' ) ): hda_dict[ 'metadata_column_names' ] = hda.datatype.column_names + history_id = trans.security.encode_id( hda.history.id ) #TODO: add column data @@ -845,4 +849,3 @@ name = fields[4] rows.append( [location, name] ) return { 'data': rows } - diff -r 67b9614dcab440027292c5dc387ef2eb1a763c19 -r 0941c74d1d058ad6183347417e45fd5fd1528501 static/scripts/templates/visualization-templates.html --- a/static/scripts/templates/visualization-templates.html +++ b/static/scripts/templates/visualization-templates.html @@ -2,11 +2,10 @@ {{! main controls }} <ul class="nav nav-tabs"> - <li class="active"> - <a data-toggle="tab" href="#data-settings">Data Controls</a> - </li> + <li class="active"><a data-toggle="tab" href="#data-settings">Data Controls</a></li><li><a data-toggle="tab" href="#chart-settings">Plot Controls</a></li><li><a data-toggle="tab" href="#chart-stats">Statistics</a></li> + <li><a data-toggle="tab" href="#chart">Chart</a></li></ul> {{! data settings }} diff -r 67b9614dcab440027292c5dc387ef2eb1a763c19 -r 0941c74d1d058ad6183347417e45fd5fd1528501 static/scripts/viz/scatterplot.js --- a/static/scripts/viz/scatterplot.js +++ b/static/scripts/viz/scatterplot.js @@ -412,14 +412,14 @@ } // titles - newDatapoints.attr( 'title', function( d, i ){ - return (( ids )?( ids[ i ] + ': ' ):( '' )) + newXCol[ i ] + ', ' + newYCol[ i ]; - }); + //newDatapoints.attr( 'title', function( d, i ){ + // return (( ids )?( ids[ i ] + ': ' ):( '' )) + newXCol[ i ] + ', ' + newYCol[ i ]; + //}); // events newDatapoints //TODO: remove magic numbers - .on( 'mouseover', function(){ + .on( 'mouseover', function( d, i ){ var datapoint = d3.select( this ); datapoint .style( 'fill', 'red' ) @@ -438,12 +438,24 @@ .attr( 'x1', datapoint.attr( 'cx' ) ).attr( 'y1', datapoint.attr( 'cy' ) ) .attr( 'x2', datapoint.attr( 'cx' ) ).attr( 'y2', plot.config.height ) .classed( 'hoverline', true ); + + //var datapointWindowPos = $( this ).position(); + var datapointWindowPos = $( this ).offset(); + window.dot = this; + console.debug( 'datapointWindowPos:', datapointWindowPos ); + console.debug( 'datapoint r:', datapoint.attr( 'r' ) ); + //this.popup = make_abs_box( datapointWindowPos.top, datapointWindowPos.left + datapoint.attr( 'r' ), + this.popup = make_abs_box( datapointWindowPos.top, datapointWindowPos.left, + newXCol[ i ], newYCol[ i ], ( ids )?( ids[ i ] ):( undefined ) ); + $( 'body' ).append( this.popup ); }) .on( 'mouseout', function(){ d3.select( this ) .style( 'fill', 'black' ) .style( 'fill-opacity', 0.2 ); - + if( this.popup ){ + this.popup.remove(); + } d3.selectAll( '.hoverline' ).remove(); }); @@ -499,7 +511,7 @@ loadingIndicatorImage : 'loading_large_white_bg.gif', initialize : function( attributes ){ - if( this.logger ){ window.form = this; } + console.debug( this + '.initialize, attributes:', attributes ); this.dataset = null; this.chartConfig = null; @@ -517,7 +529,7 @@ }, initializeFromAttributes : function( attributes ){ - // ensure certain vars we need are passed in attributes + // required settings: ensure certain vars we need are passed in attributes if( !attributes || !attributes.dataset ){ throw( "ScatterplotView requires a dataset" ); } else { @@ -586,9 +598,9 @@ loadingIndicatorImagePath : galaxy_paths.get( 'image_path' ) + '/' + this.loadingIndicatorImage }; + //TODO: isNumericColumn // gather column indeces (from metadata_column_types) and names (from metadata_columnnames) _.each( this.dataset.metadata_column_types, function( type, index ){ - //TODO: using 0-based indeces // label with the name if available (fall back on 'column <index>') var name = 'column ' + ( index + 1 ); if( view.dataset.metadata_column_names ){ @@ -597,23 +609,46 @@ // filter numeric columns to their own list if( type === 'int' || type === 'float' ){ - formData.numericColumns.push({ index: index, name: name }); + formData.numericColumns.push({ index: ( index + 1 ), name: name }); } - formData.allColumns.push({ index: index, name: name }); + formData.allColumns.push({ index: ( index + 1 ), name: name }); }); - //TODO: other vals: max_vals, start_val, pagination (plot-settings) // render template and set up panels, store refs this.$el.append( ScatterplotControlForm.templates.form( formData ) ); + this.$dataSettingsPanel = this.$el.find( '.tab-pane#data-settings' ); this.$chartSettingsPanel = this._render_chartSettings(); this.$statsPanel = this.$el.find( '.tab-pane#chart-stats' ); - + + // preset to column selectors if they were passed in the config + this.$dataSettingsPanel.find( '#X-select' ).val( this.chartConfig.xColumn ); + this.$dataSettingsPanel.find( '#Y-select' ).val( this.chartConfig.yColumn ); + if( this.chartConfig.idColumn !== undefined ){ + this.$dataSettingsPanel.find( '#include-id-checkbox' ) + .attr( 'checked', true ).trigger( 'change' ); + this.$dataSettingsPanel.find( '#ID-select' ).val( this.chartConfig.idColumn ); + } + //this.$el.find( 'ul.nav' ).find( 'a[href="#chart-settings"]' ).tab( 'show' ); + + //TODO:?? add autoRender=1 to query maybe? + if( this.chartConfig.xColumn && this.chartConfig.yColumn ){ + this.renderPlot(); + } return this; }, - + + //TODO: seems like a function of dataset or metadata + isColumnNumeric : function( index ){ + if( ( index >= 0 ) && ( index < this.dataset.metadata_column_types.length ) ){ + var columnType = this.dataset.metadata_column_types[ index ]; + return ( columnType === 'int' || columnType === 'float' ); + } + return false; + }, + _render_chartSettings : function(){ // chart settings panel var chartControl = this, @@ -658,7 +693,7 @@ // ------------------------------------------------------------------------- EVENTS events : { - 'click #include-id-checkbox' : 'toggleThirdColumnSelector', + 'change #include-id-checkbox' : 'toggleThirdColumnSelector', 'click #data-settings #render-button' : 'renderPlot', 'click #chart-settings #render-button' : 'changeChartSettings' }, @@ -948,7 +983,7 @@ }, toString : function(){ - return 'ScatterplotControlForm(' + this.dataset.id + ')'; + return 'ScatterplotControlForm(' + (( this.dataset )?( this.dataset.id ):( '' )) + ')'; } }); diff -r 67b9614dcab440027292c5dc387ef2eb1a763c19 -r 0941c74d1d058ad6183347417e45fd5fd1528501 templates/visualization/scatterplot.mako --- a/templates/visualization/scatterplot.mako +++ b/templates/visualization/scatterplot.mako @@ -193,6 +193,15 @@ fill-opacity: 0.2; } +/* -------------------------------------------- info box */ +.zero-dimensions { + width: 0; + height: 0; + border-top: 8px solid transparent; + border-bottom: 8px solid transparent; + border-right: 8px solid grey; +} + </style></%def> @@ -207,21 +216,88 @@ require([ "viz/scatterplot" ], function( scatterplot ){ var hda = ${h.to_json_string( hda )}, - historyID = '${historyID}'; - - settingsForm = new scatterplot.ScatterplotControlForm({ - dataset : hda, - el : $( '#chart-settings-form' ), - apiDatasetsURL : "${h.url_for( controller='/api/datasets' )}", + historyID = '${historyID}', + querySettings = ${h.to_json_string( kwargs )}, + chartConfig = _.extend( querySettings, { + containerSelector : '#chart-holder', + //TODO: move to ScatterplotControlForm.initialize + marginTop : ( querySettings.marginTop > 20 )?( querySettings.marginTop ):( 20 ), - chartConfig : { - containerSelector : '#chart-holder', - marginTop : 20, - } + xColumn : querySettings.xColumn, + yColumn : querySettings.yColumn, + idColumn : querySettings.idColumn + }); + console.debug( querySettings ); + + var settingsForm = new scatterplot.ScatterplotControlForm({ + dataset : hda, + apiDatasetsURL : "${h.url_for( controller='/api/datasets' )}", + el : $( '#chart-settings-form' ), + chartConfig : chartConfig }).render(); }); + +function make_abs_box( top, left, x, y, id ){ + console.debug( top, left, x, y, id ); + var ARROW_SIZE = 8, + ARROW_COLOR = 'grey', + DIST_TO_POINT = 4, + halfArrowSize = ARROW_SIZE / 2; + + var boxContainer = $( '<div />' ) + .attr( 'id', 'abs-box-container' ) + // top left arrow + .css({ + 'position' : 'absolute', + 'top' : top - halfArrowSize, + 'left' : left + ARROW_SIZE + DIST_TO_POINT, + 'background-color': 'transparent', + }); + window.boxContainer = boxContainer; + + var arrowLeft = $( '<div />' ) + .attr( 'id', 'abs-box-arrow' ) + .addClass( 'zero-dimensions' ) + .css({ + 'border-top' : ARROW_SIZE + 'px solid transparent', + 'border-bottom' : ARROW_SIZE + 'px solid transparent', + 'border-right' : ARROW_SIZE + 'px solid ' + ARROW_COLOR, + }); + boxContainer.append( arrowLeft ); + window.arrow = arrowLeft; + + console.debug( 'arrow height:', arrowLeft.height() ); + var boxInfo = $( '<div />' ) + .attr( 'id', 'abs-box' ) + .css({ + 'position' : 'relative', + //TODO: 4 here is the border-radius + 'top' : -( 2 * ARROW_SIZE + 6 ), + 'left' : ARROW_SIZE, + 'border' : '2px solid grey', + 'border-radius' : '4px', + 'padding' : '4px', + 'background-color': 'white', + 'box-shadow' : '4px 4px 4px black' + }); + + // remove + if( id ){ + $( '<div />' ).addClass( 'abs-box-id' ).css( 'font-weight', 'bold' ).text( id ).appendTo( boxInfo ); + } + $( '<div />' ).addClass( 'abs-box-x' ).text( x ).appendTo( boxInfo ); + $( '<div />' ).addClass( 'abs-box-y' ).text( y ).appendTo( boxInfo ); + boxContainer.append( boxInfo ); + boxContainer.append( '<div style="clear:both"></div>' ); + window.boxInfo = boxContainer; + + //console.debug( boxContainer ); + return boxContainer; +} + + </script></%def> https://bitbucket.org/galaxy/galaxy-central/changeset/f25f13784d20/ changeset: f25f13784d20 user: carlfeberhard date: 2012-11-20 21:32:14 summary: scatterplot: clean up affected #: 2 files diff -r 0941c74d1d058ad6183347417e45fd5fd1528501 -r f25f13784d20b7f8697ff499b73339ac7d2b4acc static/scripts/viz/scatterplot.js --- a/static/scripts/viz/scatterplot.js +++ b/static/scripts/viz/scatterplot.js @@ -412,9 +412,9 @@ } // titles - //newDatapoints.attr( 'title', function( d, i ){ - // return (( ids )?( ids[ i ] + ': ' ):( '' )) + newXCol[ i ] + ', ' + newYCol[ i ]; - //}); + newDatapoints.attr( 'title', function( d, i ){ + return (( ids )?( ids[ i ] + ': ' ):( '' )) + newXCol[ i ] + ', ' + newYCol[ i ]; + }); // events newDatapoints @@ -440,23 +440,21 @@ .classed( 'hoverline', true ); //var datapointWindowPos = $( this ).position(); - var datapointWindowPos = $( this ).offset(); - window.dot = this; - console.debug( 'datapointWindowPos:', datapointWindowPos ); - console.debug( 'datapoint r:', datapoint.attr( 'r' ) ); - //this.popup = make_abs_box( datapointWindowPos.top, datapointWindowPos.left + datapoint.attr( 'r' ), - this.popup = make_abs_box( datapointWindowPos.top, datapointWindowPos.left, - newXCol[ i ], newYCol[ i ], ( ids )?( ids[ i ] ):( undefined ) ); - $( 'body' ).append( this.popup ); + //var datapointWindowPos = $( this ).offset(); + //window.dot = this; + ////this.popup = make_abs_box( datapointWindowPos.top, datapointWindowPos.left + datapoint.attr( 'r' ), + //this.popup = make_abs_box( datapointWindowPos.top, datapointWindowPos.left, + // newXCol[ i ], newYCol[ i ], ( ids )?( ids[ i ] ):( undefined ) ); + //$( 'body' ).append( this.popup ); }) .on( 'mouseout', function(){ d3.select( this ) .style( 'fill', 'black' ) .style( 'fill-opacity', 0.2 ); - if( this.popup ){ - this.popup.remove(); - } d3.selectAll( '.hoverline' ).remove(); + //if( this.popup ){ + // this.popup.remove(); + //} }); return newDatapoints; @@ -511,7 +509,7 @@ loadingIndicatorImage : 'loading_large_white_bg.gif', initialize : function( attributes ){ - console.debug( this + '.initialize, attributes:', attributes ); + this.log( this + '.initialize, attributes:', attributes ); this.dataset = null; this.chartConfig = null; diff -r 0941c74d1d058ad6183347417e45fd5fd1528501 -r f25f13784d20b7f8697ff499b73339ac7d2b4acc templates/visualization/scatterplot.mako --- a/templates/visualization/scatterplot.mako +++ b/templates/visualization/scatterplot.mako @@ -227,7 +227,7 @@ yColumn : querySettings.yColumn, idColumn : querySettings.idColumn }); - console.debug( querySettings ); + //console.debug( querySettings ); var settingsForm = new scatterplot.ScatterplotControlForm({ dataset : hda, https://bitbucket.org/galaxy/galaxy-central/changeset/7002f41bcaa3/ changeset: 7002f41bcaa3 user: carlfeberhard date: 2012-11-20 21:32:40 summary: pack scripts affected #: 1 file diff -r f25f13784d20b7f8697ff499b73339ac7d2b4acc -r 7002f41bcaa3b1a5f5023e3c2d523488812873df static/scripts/packed/viz/scatterplot.js --- a/static/scripts/packed/viz/scatterplot.js +++ b/static/scripts/packed/viz/scatterplot.js @@ -1,1 +1,1 @@ -define(["../libs/underscore","../mvc/base-mvc","../utils/LazyDataLoader","../templates/compiled/template-visualization-scatterplotControlForm","../templates/compiled/template-visualization-statsTable","../templates/compiled/template-visualization-chartSettings","../libs/d3","../libs/bootstrap","../libs/jquery/jquery-ui"],function(){function a(f){var d=10,h=7,g=10,e=8,c=5;this.log=function(){if(this.debugging&&console&&console.debug){var i=Array.prototype.slice.call(arguments);i.unshift(this.toString());console.debug.apply(console,i)}};this.log("new TwoVarScatterplot:",f);this.defaults={id:"TwoVarScatterplot",containerSelector:"body",maxDataPoints:30000,datapointSize:4,animDuration:500,xNumTicks:10,yNumTicks:10,xAxisLabelBumpY:40,yAxisLabelBumpX:-35,width:500,height:500,marginTop:50,marginRight:50,marginBottom:50,marginLeft:50,xMin:null,xMax:null,yMin:null,yMax:null,xLabel:"X",yLabel:"Y"};this.config=_.extend({},this.defaults,f);this.updateConfig=function(i,j){_.extend(this.config,i)};this.toString=function(){return this.config.id};this.translateStr=function(i,j){return"translate("+i+","+j+")"};this.rotateStr=function(j,i,k){return"rotate("+j+","+i+","+k+")"};this.svg=d3.select(this.config.containerSelector).append("svg:svg").attr("class","chart");this.content=this.svg.append("svg:g").attr("class","content").attr("id",this.config.id);this.xAxis=this.content.append("g").attr("class","axis").attr("id","x-axis");this.xAxisLabel=this.xAxis.append("text").attr("class","axis-label").attr("id","x-axis-label");this.yAxis=this.content.append("g").attr("class","axis").attr("id","y-axis");this.yAxisLabel=this.yAxis.append("text").attr("class","axis-label").attr("id","y-axis-label");this.adjustChartDimensions=function(l,j,i,k){l=l||0;j=j||0;i=i||0;k=k||0;this.svg.attr("width",this.config.width+(this.config.marginRight+j)+(this.config.marginLeft+k)).attr("height",this.config.height+(this.config.marginTop+l)+(this.config.marginBottom+i)).style("display","block");this.content=this.svg.select("g.content").attr("transform",this.translateStr(this.config.marginLeft+k,this.config.marginTop+l))};this.preprocessData=function(k,j,i){return(k.length>this.config.maxDataPoints)?(k.slice(0,this.config.maxDataPoints)):(k)};this.setUpDomains=function(i,k,j){this.xMin=this.config.xMin||(j)?(j[0].min):(d3.min(i));this.xMax=this.config.xMax||(j)?(j[0].max):(d3.max(i));this.yMin=this.config.yMin||(j)?(j[1].min):(d3.min(k));this.yMax=this.config.yMax||(j)?(j[1].max):(d3.max(k))};this.setUpScales=function(){this.xScale=d3.scale.linear().domain([this.xMin,this.xMax]).range([0,this.config.width]),this.yScale=d3.scale.linear().domain([this.yMin,this.yMax]).range([this.config.height,0])};this.setUpXAxis=function(){this.xAxisFn=d3.svg.axis().scale(this.xScale).ticks(this.config.xNumTicks).orient("bottom");this.xAxis.attr("transform",this.translateStr(0,this.config.height)).call(this.xAxisFn);this.xLongestLabel=d3.max(_.map([this.xMin,this.xMax],function(i){return(String(i)).length}));if(this.xLongestLabel>=c){this.xAxis.selectAll("g").filter(":nth-child(odd)").style("display","none")}this.xAxisLabel.attr("x",this.config.width/2).attr("y",this.config.xAxisLabelBumpY).attr("text-anchor","middle").text(this.config.xLabel)};this.setUpYAxis=function(){this.yAxisFn=d3.svg.axis().scale(this.yScale).ticks(this.config.yNumTicks).orient("left");this.yAxis.call(this.yAxisFn);var i=this.yAxis.selectAll("text").filter(function(m,l){return l!==0});this.yLongestLabel=d3.max(i[0].map(function(m,l){return(d3.select(m).text()).length}))||0;var j=d+(this.yLongestLabel*h)+e+g;this.config.yAxisLabelBumpX=-(j-g);if(this.config.marginLeft<j){var k=(j)-this.config.marginLeft;k=(k<0)?(0):(k);this.adjustChartDimensions(0,0,0,k)}this.yAxisLabel.attr("x",this.config.yAxisLabelBumpX).attr("y",this.config.height/2).attr("text-anchor","middle").attr("transform",this.rotateStr(-90,this.config.yAxisLabelBumpX,this.config.height/2)).text(this.config.yLabel)};this.renderGrid=function(){this.vGridLines=this.content.selectAll("line.v-grid-line").data(this.xScale.ticks(this.xAxisFn.ticks()[0]));this.vGridLines.enter().append("svg:line").classed("grid-line v-grid-line",true);this.vGridLines.attr("x1",this.xScale).attr("y1",0).attr("x2",this.xScale).attr("y2",this.config.height);this.vGridLines.exit().remove();this.hGridLines=this.content.selectAll("line.h-grid-line").data(this.yScale.ticks(this.yAxisFn.ticks()[0]));this.hGridLines.enter().append("svg:line").classed("grid-line h-grid-line",true);this.hGridLines.attr("x1",0).attr("y1",this.yScale).attr("x2",this.config.width).attr("y2",this.yScale);this.hGridLines.exit().remove()};this.glyphEnterState=function(i){};this.glyphFinalState=function(i){};this.glyphExitState=function(i){};this.renderDatapoints=function(i,l,j){this.log(this+".renderDatapoints",arguments);var k=0;this.datapoints=this.addDatapoints(i,l,j,".glyph");this.datapoints.exit().each(function(){k+=1}).transition().duration(this.config.animDuration).attr("cy",this.config.height).attr("r",0).remove();this.log(k," glyphs removed")};this.addDatapoints=function(m,k,i,l){this.log(this+".addDatapoints",arguments);var p=this,o=0,q=function(s,r){return p.xScale(m[r])},j=function(s,r){return p.yScale(k[r])};var n=this.content.selectAll(l);this.log("existing datapoints:",n);n=n.data(m);o=0;n.enter().append("svg:circle").each(function(){o+=1}).classed("glyph",true).attr("cx",q).attr("cy",j).attr("r",0);this.log(o," new glyphs created");o=0;n.transition().duration(this.config.animDuration).each(function(){o+=1}).attr("cx",q).attr("cy",j).attr("r",p.config.datapointSize);this.log(o," existing glyphs transitioned");if(i){n.attr("data",function(s,r){return(i[r])})}n.attr("title",function(s,r){return((i)?(i[r]+": "):(""))+m[r]+", "+k[r]});n.on("mouseover",function(){var r=d3.select(this);r.style("fill","red").style("fill-opacity",1);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",r.attr("cx")).attr("y1",r.attr("cy")).attr("x2",0).attr("y2",r.attr("cy")).classed("hoverline",true);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",r.attr("cx")).attr("y1",r.attr("cy")).attr("x2",r.attr("cx")).attr("y2",p.config.height).classed("hoverline",true)}).on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",0.2);d3.selectAll(".hoverline").remove()});return n};this.render=function(k,l){this.log(this+".render",arguments);var i=k[0],m=k[1],j=(k.length>2)?(k[2]):(undefined);i=this.preprocessData(i);m=this.preprocessData(m);this.log("xCol len",i.length,"yCol len",m.length);this.setUpDomains(i,m,l);this.setUpScales();this.adjustChartDimensions();this.setUpXAxis();this.setUpYAxis();this.renderGrid();this.renderDatapoints(i,m,j)}}var b=BaseView.extend(LoggableMixin).extend({className:"scatterplot-settings-form",dataLoadDelay:500,dataLoadSize:3001,loadingIndicatorImage:"loading_large_white_bg.gif",initialize:function(c){if(this.logger){window.form=this}this.dataset=null;this.chartConfig=null;this.plot=null;this.loader=null;this.$statsPanel=null;this.$chartSettingsPanel=null;this.$dataSettingsPanel=null;this.dataFetch=null;this.initializeFromAttributes(c);this.initializeChart(c);this.initializeDataLoader(c)},initializeFromAttributes:function(c){if(!c||!c.dataset){throw ("ScatterplotView requires a dataset")}else{this.dataset=c.dataset}if(jQuery.type(this.dataset.metadata_column_types)==="string"){this.dataset.metadata_column_types=this.dataset.metadata_column_types.split(", ")}this.log("dataset:",this.dataset);if(!c.apiDatasetsURL){throw ("ScatterplotView requires a apiDatasetsURL")}else{this.dataURL=c.apiDatasetsURL+"/"+this.dataset.id+"?"}this.log("this.dataURL:",this.dataURL)},initializeChart:function(c){this.chartConfig=c.chartConfig||{};if(this.logger){this.chartConfig.debugging=true}this.log("initial chartConfig:",this.chartConfig);this.plot=new a(this.chartConfig);this.chartConfig=this.plot.config},initializeDataLoader:function(d){var c=this;this.loader=new LazyDataLoader({logger:(this.logger)?(this.logger):(null),url:null,start:d.start||0,total:d.total||this.dataset.metadata_data_lines,delay:this.dataLoadDelay,size:this.dataLoadSize,buildUrl:function(f,e){return this.url+"&"+jQuery.param({start_val:f,max_vals:e})}});$(this.loader).bind("error",function(g,e,f){c.log("ERROR:",e,f);alert("ERROR fetching data:\n"+e+"\n"+f);c.hideLoadingIndicator()})},render:function(){var c=this,d={config:this.chartConfig,allColumns:[],numericColumns:[],loadingIndicatorImagePath:galaxy_paths.get("image_path")+"/"+this.loadingIndicatorImage};_.each(this.dataset.metadata_column_types,function(g,f){var e="column "+(f+1);if(c.dataset.metadata_column_names){e=c.dataset.metadata_column_names[f]}if(g==="int"||g==="float"){d.numericColumns.push({index:f,name:e})}d.allColumns.push({index:f,name:e})});this.$el.append(b.templates.form(d));this.$dataSettingsPanel=this.$el.find(".tab-pane#data-settings");this.$chartSettingsPanel=this._render_chartSettings();this.$statsPanel=this.$el.find(".tab-pane#chart-stats");return this},_render_chartSettings:function(){var c=this,d=this.$el.find(".tab-pane#chart-settings"),e={datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};d.append(b.templates.chartSettings(this.chartConfig));d.find(".numeric-slider-input").each(function(){var h=$(this),g=h.find(".slider-output"),i=h.find(".slider"),j=h.attr("id");function f(){var l=$(this),k=l.slider("value");g.text(k)}i.slider(_.extend(e[j],{value:c.chartConfig[j],change:f,slide:f}))});return d},events:{"click #include-id-checkbox":"toggleThirdColumnSelector","click #data-settings #render-button":"renderPlot","click #chart-settings #render-button":"changeChartSettings"},toggleThirdColumnSelector:function(){this.$el.find('select[name="ID"]').parent().toggle()},showLoadingIndicator:function(d,e){d=d||"";var c=this.$el.find("div#loading-indicator");messageBox=c.find(".loading-message");if(c.is(":visible")){if(d){messageBox.fadeOut("fast",function(){messageBox.text(d);messageBox.fadeIn("fast",e)})}else{e()}}else{if(d){messageBox.text(d)}c.fadeIn("fast",e)}},hideLoadingIndicator:function(c){this.$el.find("div#loading-indicator").fadeOut("fast",c)},renderPlot:function(){var c=this;c.data=null;c.meta=null;_.extend(this.chartConfig,this.getGraphSettings());this.log("this.chartConfig:",this.chartConfig);this.plot.updateConfig(this.chartConfig,false);this.loader.url=this.dataURL+"&"+jQuery.param(this.getDataSettings());this.log("this.loader, url:",this.loader.url,"total:",this.loader.total);$(this.loader).bind("loaded.new",function(e,d){c.log(c+" loaded.new",d);c.postProcessDataFetchResponse(d);c.log("postprocessed data:",c.data,"meta:",c.meta);c.showLoadingIndicator("Rendering...",function(){c.$el.find("ul.nav").find('a[href="#chart-stats"]').tab("show");c.plot.render(c.data,c.meta);c.renderStats(c.data,c.meta);c.hideLoadingIndicator()})});$(this.loader).bind("complete",function(d,e){c.log("complete",e);$(c.loader).unbind()});c.showLoadingIndicator("Fetching data...",function(){c.loader.load()})},renderStats:function(){this.$statsPanel.html(b.templates.statsTable({stats:[{name:"Count",xval:this.meta[0].count,yval:this.meta[1].count},{name:"Min",xval:this.meta[0].min,yval:this.meta[1].min},{name:"Max",xval:this.meta[0].max,yval:this.meta[1].max},{name:"Sum",xval:this.meta[0].sum,yval:this.meta[1].sum},{name:"Mean",xval:this.meta[0].mean,yval:this.meta[1].mean},{name:"Median",xval:this.meta[0].median,yval:this.meta[1].median}]}))},changeChartSettings:function(){var c=this;newGraphSettings=this.getGraphSettings();this.log("newGraphSettings:",newGraphSettings);_.extend(this.chartConfig,newGraphSettings);this.log("this.chartConfig:",this.chartConfig);this.plot.updateConfig(this.chartConfig,false);if(c.data&&c.meta){c.showLoadingIndicator("Rendering...",function(){c.plot.render(c.data,c.meta);c.hideLoadingIndicator()})}else{this.renderPlot()}},postProcessDataFetchResponse:function(c){this.postProcessData(c.data);this.postProcessMeta(c.meta)},postProcessData:function(d){var c=this;if(c.data){_.each(d,function(f,e){c.data[e]=c.data[e].concat(f)})}else{c.data=d}},postProcessMeta:function(e){var c=this,d=this.dataset.metadata_column_types;if(c.meta){_.each(e,function(g,f){var k=c.meta[f],i=d[f];c.log(f+" postprocessing meta:",g);k.count+=(g.count)?(g.count):(0);c.log(f,"count:",k.count);if((i==="int")||(i==="float")){k.min=Math.min(g.min,k.min);k.max=Math.max(g.max,k.max);k.sum=g.sum+k.sum;k.mean=(k.count)?(k.sum/k.count):(null);var h=c.data[f].slice().sort(),j=Math.floor(h.length/2);if(h.length%2===0){k.median=((h[j]+h[(j+1)])/2)}else{k.median=h[j]}}})}else{c.meta=e;c.log("initial meta:",c.meta)}},getDataSettings:function(){var d=this.getColumnSelections(),c=[];this.log("columnSelections:",d);c=[d.X.colIndex,d.Y.colIndex];if(this.$dataSettingsPanel.find("#include-id-checkbox").attr("checked")){c.push(d.ID.colIndex)}var e={data_type:"raw_data",columns:"["+c+"]"};this.log("params:",e);return e},getColumnSelections:function(){var c={};this.$dataSettingsPanel.find("div.column-select select").each(function(){var d=$(this),e=d.val();c[d.attr("name")]={colIndex:e,colName:d.children('[value="'+e+'"]').text()}});return c},getGraphSettings:function(){var e={},f=this.getColumnSelections();e.datapointSize=this.$chartSettingsPanel.find("#datapointSize.numeric-slider-input").find(".slider").slider("value");e.width=this.$chartSettingsPanel.find("#width.numeric-slider-input").find(".slider").slider("value");e.height=this.$chartSettingsPanel.find("#height.numeric-slider-input").find(".slider").slider("value");var d=this.$chartSettingsPanel.find("input#X-axis-label").val(),c=this.$chartSettingsPanel.find("input#Y-axis-label").val();e.xLabel=(d==="X")?(f.X.colName):(d);e.yLabel=(c==="Y")?(f.Y.colName):(c);e.animDuration=10;if(this.$chartSettingsPanel.find("#animDuration.checkbox-input").is(":checked")){e.animDuration=500}this.log("graphSettings:",e);return e},toString:function(){return"ScatterplotControlForm("+this.dataset.id+")"}});b.templates={form:Handlebars.templates["template-visualization-scatterplotControlForm"],statsTable:Handlebars.templates["template-visualization-statsTable"],chartSettings:Handlebars.templates["template-visualization-chartSettings"]};return{LazyDataLoader:LazyDataLoader,TwoVarScatterplot:a,ScatterplotControlForm:b}}); \ No newline at end of file +define(["../libs/underscore","../mvc/base-mvc","../utils/LazyDataLoader","../templates/compiled/template-visualization-scatterplotControlForm","../templates/compiled/template-visualization-statsTable","../templates/compiled/template-visualization-chartSettings","../libs/d3","../libs/bootstrap","../libs/jquery/jquery-ui"],function(){function a(f){var d=10,h=7,g=10,e=8,c=5;this.log=function(){if(this.debugging&&console&&console.debug){var i=Array.prototype.slice.call(arguments);i.unshift(this.toString());console.debug.apply(console,i)}};this.log("new TwoVarScatterplot:",f);this.defaults={id:"TwoVarScatterplot",containerSelector:"body",maxDataPoints:30000,datapointSize:4,animDuration:500,xNumTicks:10,yNumTicks:10,xAxisLabelBumpY:40,yAxisLabelBumpX:-35,width:500,height:500,marginTop:50,marginRight:50,marginBottom:50,marginLeft:50,xMin:null,xMax:null,yMin:null,yMax:null,xLabel:"X",yLabel:"Y"};this.config=_.extend({},this.defaults,f);this.updateConfig=function(i,j){_.extend(this.config,i)};this.toString=function(){return this.config.id};this.translateStr=function(i,j){return"translate("+i+","+j+")"};this.rotateStr=function(j,i,k){return"rotate("+j+","+i+","+k+")"};this.svg=d3.select(this.config.containerSelector).append("svg:svg").attr("class","chart");this.content=this.svg.append("svg:g").attr("class","content").attr("id",this.config.id);this.xAxis=this.content.append("g").attr("class","axis").attr("id","x-axis");this.xAxisLabel=this.xAxis.append("text").attr("class","axis-label").attr("id","x-axis-label");this.yAxis=this.content.append("g").attr("class","axis").attr("id","y-axis");this.yAxisLabel=this.yAxis.append("text").attr("class","axis-label").attr("id","y-axis-label");this.adjustChartDimensions=function(l,j,i,k){l=l||0;j=j||0;i=i||0;k=k||0;this.svg.attr("width",this.config.width+(this.config.marginRight+j)+(this.config.marginLeft+k)).attr("height",this.config.height+(this.config.marginTop+l)+(this.config.marginBottom+i)).style("display","block");this.content=this.svg.select("g.content").attr("transform",this.translateStr(this.config.marginLeft+k,this.config.marginTop+l))};this.preprocessData=function(k,j,i){return(k.length>this.config.maxDataPoints)?(k.slice(0,this.config.maxDataPoints)):(k)};this.setUpDomains=function(i,k,j){this.xMin=this.config.xMin||(j)?(j[0].min):(d3.min(i));this.xMax=this.config.xMax||(j)?(j[0].max):(d3.max(i));this.yMin=this.config.yMin||(j)?(j[1].min):(d3.min(k));this.yMax=this.config.yMax||(j)?(j[1].max):(d3.max(k))};this.setUpScales=function(){this.xScale=d3.scale.linear().domain([this.xMin,this.xMax]).range([0,this.config.width]),this.yScale=d3.scale.linear().domain([this.yMin,this.yMax]).range([this.config.height,0])};this.setUpXAxis=function(){this.xAxisFn=d3.svg.axis().scale(this.xScale).ticks(this.config.xNumTicks).orient("bottom");this.xAxis.attr("transform",this.translateStr(0,this.config.height)).call(this.xAxisFn);this.xLongestLabel=d3.max(_.map([this.xMin,this.xMax],function(i){return(String(i)).length}));if(this.xLongestLabel>=c){this.xAxis.selectAll("g").filter(":nth-child(odd)").style("display","none")}this.xAxisLabel.attr("x",this.config.width/2).attr("y",this.config.xAxisLabelBumpY).attr("text-anchor","middle").text(this.config.xLabel)};this.setUpYAxis=function(){this.yAxisFn=d3.svg.axis().scale(this.yScale).ticks(this.config.yNumTicks).orient("left");this.yAxis.call(this.yAxisFn);var i=this.yAxis.selectAll("text").filter(function(m,l){return l!==0});this.yLongestLabel=d3.max(i[0].map(function(m,l){return(d3.select(m).text()).length}))||0;var j=d+(this.yLongestLabel*h)+e+g;this.config.yAxisLabelBumpX=-(j-g);if(this.config.marginLeft<j){var k=(j)-this.config.marginLeft;k=(k<0)?(0):(k);this.adjustChartDimensions(0,0,0,k)}this.yAxisLabel.attr("x",this.config.yAxisLabelBumpX).attr("y",this.config.height/2).attr("text-anchor","middle").attr("transform",this.rotateStr(-90,this.config.yAxisLabelBumpX,this.config.height/2)).text(this.config.yLabel)};this.renderGrid=function(){this.vGridLines=this.content.selectAll("line.v-grid-line").data(this.xScale.ticks(this.xAxisFn.ticks()[0]));this.vGridLines.enter().append("svg:line").classed("grid-line v-grid-line",true);this.vGridLines.attr("x1",this.xScale).attr("y1",0).attr("x2",this.xScale).attr("y2",this.config.height);this.vGridLines.exit().remove();this.hGridLines=this.content.selectAll("line.h-grid-line").data(this.yScale.ticks(this.yAxisFn.ticks()[0]));this.hGridLines.enter().append("svg:line").classed("grid-line h-grid-line",true);this.hGridLines.attr("x1",0).attr("y1",this.yScale).attr("x2",this.config.width).attr("y2",this.yScale);this.hGridLines.exit().remove()};this.glyphEnterState=function(i){};this.glyphFinalState=function(i){};this.glyphExitState=function(i){};this.renderDatapoints=function(i,l,j){this.log(this+".renderDatapoints",arguments);var k=0;this.datapoints=this.addDatapoints(i,l,j,".glyph");this.datapoints.exit().each(function(){k+=1}).transition().duration(this.config.animDuration).attr("cy",this.config.height).attr("r",0).remove();this.log(k," glyphs removed")};this.addDatapoints=function(m,k,i,l){this.log(this+".addDatapoints",arguments);var p=this,o=0,q=function(s,r){return p.xScale(m[r])},j=function(s,r){return p.yScale(k[r])};var n=this.content.selectAll(l);this.log("existing datapoints:",n);n=n.data(m);o=0;n.enter().append("svg:circle").each(function(){o+=1}).classed("glyph",true).attr("cx",q).attr("cy",j).attr("r",0);this.log(o," new glyphs created");o=0;n.transition().duration(this.config.animDuration).each(function(){o+=1}).attr("cx",q).attr("cy",j).attr("r",p.config.datapointSize);this.log(o," existing glyphs transitioned");if(i){n.attr("data",function(s,r){return(i[r])})}n.attr("title",function(s,r){return((i)?(i[r]+": "):(""))+m[r]+", "+k[r]});n.on("mouseover",function(t,r){var s=d3.select(this);s.style("fill","red").style("fill-opacity",1);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",s.attr("cx")).attr("y1",s.attr("cy")).attr("x2",0).attr("y2",s.attr("cy")).classed("hoverline",true);p.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",s.attr("cx")).attr("y1",s.attr("cy")).attr("x2",s.attr("cx")).attr("y2",p.config.height).classed("hoverline",true)}).on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",0.2);d3.selectAll(".hoverline").remove()});return n};this.render=function(k,l){this.log(this+".render",arguments);var i=k[0],m=k[1],j=(k.length>2)?(k[2]):(undefined);i=this.preprocessData(i);m=this.preprocessData(m);this.log("xCol len",i.length,"yCol len",m.length);this.setUpDomains(i,m,l);this.setUpScales();this.adjustChartDimensions();this.setUpXAxis();this.setUpYAxis();this.renderGrid();this.renderDatapoints(i,m,j)}}var b=BaseView.extend(LoggableMixin).extend({className:"scatterplot-settings-form",dataLoadDelay:500,dataLoadSize:3001,loadingIndicatorImage:"loading_large_white_bg.gif",initialize:function(c){this.log(this+".initialize, attributes:",c);this.dataset=null;this.chartConfig=null;this.plot=null;this.loader=null;this.$statsPanel=null;this.$chartSettingsPanel=null;this.$dataSettingsPanel=null;this.dataFetch=null;this.initializeFromAttributes(c);this.initializeChart(c);this.initializeDataLoader(c)},initializeFromAttributes:function(c){if(!c||!c.dataset){throw ("ScatterplotView requires a dataset")}else{this.dataset=c.dataset}if(jQuery.type(this.dataset.metadata_column_types)==="string"){this.dataset.metadata_column_types=this.dataset.metadata_column_types.split(", ")}this.log("dataset:",this.dataset);if(!c.apiDatasetsURL){throw ("ScatterplotView requires a apiDatasetsURL")}else{this.dataURL=c.apiDatasetsURL+"/"+this.dataset.id+"?"}this.log("this.dataURL:",this.dataURL)},initializeChart:function(c){this.chartConfig=c.chartConfig||{};if(this.logger){this.chartConfig.debugging=true}this.log("initial chartConfig:",this.chartConfig);this.plot=new a(this.chartConfig);this.chartConfig=this.plot.config},initializeDataLoader:function(d){var c=this;this.loader=new LazyDataLoader({logger:(this.logger)?(this.logger):(null),url:null,start:d.start||0,total:d.total||this.dataset.metadata_data_lines,delay:this.dataLoadDelay,size:this.dataLoadSize,buildUrl:function(f,e){return this.url+"&"+jQuery.param({start_val:f,max_vals:e})}});$(this.loader).bind("error",function(g,e,f){c.log("ERROR:",e,f);alert("ERROR fetching data:\n"+e+"\n"+f);c.hideLoadingIndicator()})},render:function(){var c=this,d={config:this.chartConfig,allColumns:[],numericColumns:[],loadingIndicatorImagePath:galaxy_paths.get("image_path")+"/"+this.loadingIndicatorImage};_.each(this.dataset.metadata_column_types,function(g,f){var e="column "+(f+1);if(c.dataset.metadata_column_names){e=c.dataset.metadata_column_names[f]}if(g==="int"||g==="float"){d.numericColumns.push({index:(f+1),name:e})}d.allColumns.push({index:(f+1),name:e})});this.$el.append(b.templates.form(d));this.$dataSettingsPanel=this.$el.find(".tab-pane#data-settings");this.$chartSettingsPanel=this._render_chartSettings();this.$statsPanel=this.$el.find(".tab-pane#chart-stats");this.$dataSettingsPanel.find("#X-select").val(this.chartConfig.xColumn);this.$dataSettingsPanel.find("#Y-select").val(this.chartConfig.yColumn);if(this.chartConfig.idColumn!==undefined){this.$dataSettingsPanel.find("#include-id-checkbox").attr("checked",true).trigger("change");this.$dataSettingsPanel.find("#ID-select").val(this.chartConfig.idColumn)}if(this.chartConfig.xColumn&&this.chartConfig.yColumn){this.renderPlot()}return this},isColumnNumeric:function(c){if((c>=0)&&(c<this.dataset.metadata_column_types.length)){var d=this.dataset.metadata_column_types[c];return(d==="int"||d==="float")}return false},_render_chartSettings:function(){var c=this,d=this.$el.find(".tab-pane#chart-settings"),e={datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};d.append(b.templates.chartSettings(this.chartConfig));d.find(".numeric-slider-input").each(function(){var h=$(this),g=h.find(".slider-output"),i=h.find(".slider"),j=h.attr("id");function f(){var l=$(this),k=l.slider("value");g.text(k)}i.slider(_.extend(e[j],{value:c.chartConfig[j],change:f,slide:f}))});return d},events:{"change #include-id-checkbox":"toggleThirdColumnSelector","click #data-settings #render-button":"renderPlot","click #chart-settings #render-button":"changeChartSettings"},toggleThirdColumnSelector:function(){this.$el.find('select[name="ID"]').parent().toggle()},showLoadingIndicator:function(d,e){d=d||"";var c=this.$el.find("div#loading-indicator");messageBox=c.find(".loading-message");if(c.is(":visible")){if(d){messageBox.fadeOut("fast",function(){messageBox.text(d);messageBox.fadeIn("fast",e)})}else{e()}}else{if(d){messageBox.text(d)}c.fadeIn("fast",e)}},hideLoadingIndicator:function(c){this.$el.find("div#loading-indicator").fadeOut("fast",c)},renderPlot:function(){var c=this;c.data=null;c.meta=null;_.extend(this.chartConfig,this.getGraphSettings());this.log("this.chartConfig:",this.chartConfig);this.plot.updateConfig(this.chartConfig,false);this.loader.url=this.dataURL+"&"+jQuery.param(this.getDataSettings());this.log("this.loader, url:",this.loader.url,"total:",this.loader.total);$(this.loader).bind("loaded.new",function(e,d){c.log(c+" loaded.new",d);c.postProcessDataFetchResponse(d);c.log("postprocessed data:",c.data,"meta:",c.meta);c.showLoadingIndicator("Rendering...",function(){c.$el.find("ul.nav").find('a[href="#chart-stats"]').tab("show");c.plot.render(c.data,c.meta);c.renderStats(c.data,c.meta);c.hideLoadingIndicator()})});$(this.loader).bind("complete",function(d,e){c.log("complete",e);$(c.loader).unbind()});c.showLoadingIndicator("Fetching data...",function(){c.loader.load()})},renderStats:function(){this.$statsPanel.html(b.templates.statsTable({stats:[{name:"Count",xval:this.meta[0].count,yval:this.meta[1].count},{name:"Min",xval:this.meta[0].min,yval:this.meta[1].min},{name:"Max",xval:this.meta[0].max,yval:this.meta[1].max},{name:"Sum",xval:this.meta[0].sum,yval:this.meta[1].sum},{name:"Mean",xval:this.meta[0].mean,yval:this.meta[1].mean},{name:"Median",xval:this.meta[0].median,yval:this.meta[1].median}]}))},changeChartSettings:function(){var c=this;newGraphSettings=this.getGraphSettings();this.log("newGraphSettings:",newGraphSettings);_.extend(this.chartConfig,newGraphSettings);this.log("this.chartConfig:",this.chartConfig);this.plot.updateConfig(this.chartConfig,false);if(c.data&&c.meta){c.showLoadingIndicator("Rendering...",function(){c.plot.render(c.data,c.meta);c.hideLoadingIndicator()})}else{this.renderPlot()}},postProcessDataFetchResponse:function(c){this.postProcessData(c.data);this.postProcessMeta(c.meta)},postProcessData:function(d){var c=this;if(c.data){_.each(d,function(f,e){c.data[e]=c.data[e].concat(f)})}else{c.data=d}},postProcessMeta:function(e){var c=this,d=this.dataset.metadata_column_types;if(c.meta){_.each(e,function(g,f){var k=c.meta[f],i=d[f];c.log(f+" postprocessing meta:",g);k.count+=(g.count)?(g.count):(0);c.log(f,"count:",k.count);if((i==="int")||(i==="float")){k.min=Math.min(g.min,k.min);k.max=Math.max(g.max,k.max);k.sum=g.sum+k.sum;k.mean=(k.count)?(k.sum/k.count):(null);var h=c.data[f].slice().sort(),j=Math.floor(h.length/2);if(h.length%2===0){k.median=((h[j]+h[(j+1)])/2)}else{k.median=h[j]}}})}else{c.meta=e;c.log("initial meta:",c.meta)}},getDataSettings:function(){var d=this.getColumnSelections(),c=[];this.log("columnSelections:",d);c=[d.X.colIndex,d.Y.colIndex];if(this.$dataSettingsPanel.find("#include-id-checkbox").attr("checked")){c.push(d.ID.colIndex)}var e={data_type:"raw_data",columns:"["+c+"]"};this.log("params:",e);return e},getColumnSelections:function(){var c={};this.$dataSettingsPanel.find("div.column-select select").each(function(){var d=$(this),e=d.val();c[d.attr("name")]={colIndex:e,colName:d.children('[value="'+e+'"]').text()}});return c},getGraphSettings:function(){var e={},f=this.getColumnSelections();e.datapointSize=this.$chartSettingsPanel.find("#datapointSize.numeric-slider-input").find(".slider").slider("value");e.width=this.$chartSettingsPanel.find("#width.numeric-slider-input").find(".slider").slider("value");e.height=this.$chartSettingsPanel.find("#height.numeric-slider-input").find(".slider").slider("value");var d=this.$chartSettingsPanel.find("input#X-axis-label").val(),c=this.$chartSettingsPanel.find("input#Y-axis-label").val();e.xLabel=(d==="X")?(f.X.colName):(d);e.yLabel=(c==="Y")?(f.Y.colName):(c);e.animDuration=10;if(this.$chartSettingsPanel.find("#animDuration.checkbox-input").is(":checked")){e.animDuration=500}this.log("graphSettings:",e);return e},toString:function(){return"ScatterplotControlForm("+((this.dataset)?(this.dataset.id):(""))+")"}});b.templates={form:Handlebars.templates["template-visualization-scatterplotControlForm"],statsTable:Handlebars.templates["template-visualization-statsTable"],chartSettings:Handlebars.templates["template-visualization-chartSettings"]};return{LazyDataLoader:LazyDataLoader,TwoVarScatterplot:a,ScatterplotControlForm:b}}); \ 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.
participants (1)
-
Bitbucket