From ba85f50e39a0b69200b6162ab40047df1fe6b4ae Mon Sep 17 00:00:00 2001 From: Stefano Mazzocchi Date: Tue, 13 Apr 2010 00:25:43 +0000 Subject: [PATCH] adding log-log support to the scatterplot matrix and more controls (the scatterfacet still doesn't work but this is already more useful) git-svn-id: http://google-refine.googlecode.com/svn/trunk@456 7d457c2a-affb-35e4-300a-418c747d4874 --- .../browsing/charting/ScatterplotCharter.java | 93 ++++++++++++++----- .../scripts/dialogs/scatterplot-dialog.js | 73 ++++++++++++--- .../styles/dialogs/scatterplot-dialog.css | 5 +- 3 files changed, 137 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/metaweb/gridworks/browsing/charting/ScatterplotCharter.java b/src/main/java/com/metaweb/gridworks/browsing/charting/ScatterplotCharter.java index 3bcabb204..884c60e12 100644 --- a/src/main/java/com/metaweb/gridworks/browsing/charting/ScatterplotCharter.java +++ b/src/main/java/com/metaweb/gridworks/browsing/charting/ScatterplotCharter.java @@ -30,8 +30,20 @@ import com.metaweb.gridworks.model.Row; public class ScatterplotCharter { - private static final Color COLOR = Color.black; - + private static final int LIN = 0; + private static final int LOG = 1; + private static final int RADIAL = 2; + + private static int getAxisDim(String type) { + if ("log".equals(type)) { + return LOG; + } else if ("rad".equals(type) || "radial".equals(type)) { + return RADIAL; + } else { + return LIN; + } + } + public String getContentType() { return "image/png"; } @@ -47,23 +59,30 @@ public class ScatterplotCharter { class DrawingRowVisitor implements RowVisitor { - private static final double px = 0.5f; - boolean process = true; - boolean smoothed = false; - - int width = 50; - int height = 50; + int width; + int height; int col_x; int col_y; + int dim; + double w; double h; double min_x; double min_y; double max_x; double max_y; - + double delta_x; + double delta_y; + double log_delta_x; + double log_delta_y; + double rx; + double ry; + double dot; + + Color color; + NumericBinIndex index_x; NumericBinIndex index_y; @@ -76,8 +95,8 @@ public class ScatterplotCharter { if (column_x != null) { col_x = column_x.getCellIndex(); index_x = getBinIndex(project, column_x); - min_x = index_x.getMin() * 1.1d; - max_x = index_x.getMax() * 1.1d; + min_x = index_x.getMin(); + max_x = index_x.getMax(); } String col_y_name = o.getString("cy"); @@ -85,12 +104,30 @@ public class ScatterplotCharter { if (column_y != null) { col_y = column_y.getCellIndex(); index_y = getBinIndex(project, column_y); - min_y = index_y.getMin() * 1.1d; - max_y = index_y.getMax() * 1.1d; + min_y = index_y.getMin(); + max_y = index_y.getMax(); } - width = o.getInt("w"); - height = o.getInt("h"); + width = (o.has("w")) ? o.getInt("w") : 20; + height = (o.has("h")) ? o.getInt("h") : 20; + + dot = (o.has("dot")) ? o.getDouble("dot") : 0.1d; + + dim = (o.has("dim")) ? getAxisDim(o.getString("dim")) : LIN; + + delta_x = max_x - min_x; + delta_y = max_y - min_y; + + if (dim == RADIAL) { + rx = (o.has("rx")) ? o.getDouble("rx") : 0.0d; + ry = (o.has("ry")) ? o.getDouble("ry") : 0.0d; + } else if (dim == LOG) { + log_delta_x = Math.log10(delta_x); + log_delta_y = Math.log10(delta_y); + } + + String color_str = (o.has("color")) ? o.getString("color") : "000000"; + color = new Color(Integer.parseInt(color_str,16)); w = (double) width; h = (double) height; @@ -103,8 +140,8 @@ public class ScatterplotCharter { AffineTransform t = AffineTransform.getTranslateInstance(0,h); t.concatenate(AffineTransform.getScaleInstance(1.0d, -1.0d)); g2.setTransform(t); - g2.setColor(COLOR); - g2.setPaint(COLOR); + g2.setColor(color); + g2.setPaint(color); } else { image = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR); process = false; @@ -112,10 +149,11 @@ public class ScatterplotCharter { } private NumericBinIndex getBinIndex(Project project, Column column) { - String key = "numeric-bin:value"; + String expression = "value"; + String key = "numeric-bin:" + expression; Evaluable eval = null; try { - eval = MetaParser.parse("value"); + eval = MetaParser.parse(expression); } catch (ParsingException e) { // this should never happen } @@ -137,9 +175,20 @@ public class ScatterplotCharter { double xv = ((Number) cellx.value).doubleValue(); double yv = ((Number) celly.value).doubleValue(); - double x = (xv - min_x) * w / max_x; - double y = (yv - min_y) * h / max_y; - g2.fill(new Rectangle2D.Double(x, y, px, px)); + double x; + double y; + + if (dim == LOG) { + x = Math.log10(xv - min_x) * w / log_delta_x - dot / 2; + y = Math.log10(yv - min_y) * h / log_delta_y - dot / 2; + } else if (dim == RADIAL) { + x = (xv - min_x) * w / delta_x - dot / 2; + y = (yv - min_y) * h / delta_y - dot / 2; + } else { + x = (xv - min_x) * w / delta_x - dot / 2; + y = (yv - min_y) * h / delta_y - dot / 2; + } + g2.fill(new Rectangle2D.Double(x, y, dot, dot)); } } diff --git a/src/main/webapp/scripts/dialogs/scatterplot-dialog.js b/src/main/webapp/scripts/dialogs/scatterplot-dialog.js index ebebb4135..445cc28a4 100644 --- a/src/main/webapp/scripts/dialogs/scatterplot-dialog.js +++ b/src/main/webapp/scripts/dialogs/scatterplot-dialog.js @@ -1,11 +1,14 @@ function ScatterplotDialog() { this._createDialog(); + this._plot_method = "lin"; + this._plot_size = 20; + this._dot_size = 0.1; } ScatterplotDialog.prototype._createDialog = function() { var self = this; var frame = DialogSystem.createDialog(); - frame.width("900px"); + frame.width("1100px"); var header = $('
').addClass("dialog-header").text('Scatterplot Matrix').appendTo(frame); var body = $('
').addClass("dialog-body").appendTo(frame); @@ -17,29 +20,75 @@ ScatterplotDialog.prototype._createDialog = function() { '' + '' ).appendTo(frame); - + var html = $( - '
' + - '
' + - '
' + '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '
' + + 'Plot type: ' + + 'Plot Size: px' + + 'Dot Size: px' + + '
' + + '
' + + '
' ).appendTo(body); + this._elmts = DOM.bind(html); + this._elmts.plotSelector.change(function() { + var selection = $(this).find("option:selected").text(); + if (selection == 'linear') { + self._plot_method = "lin"; + } else if (selection === 'log-log') { + self._plot_method = "log"; + } + self._renderMatrix(); + }); + + this._elmts.plotSize.change(function() { + try { + self._plot_size = parseInt($(this).val()) + self._renderMatrix(); + } catch (e) { + alert("Must be a number"); + } + }); + + this._elmts.dotSize.change(function() { + try { + self._dot_size = parseFloat($(this).val()) + self._renderMatrix(); + } catch (e) { + alert("Must be a number"); + } + }); + var left_footer = footer.find(".left"); var right_footer = footer.find(".right"); $('').text("Close").click(function() { self._dismiss(); }).appendTo(right_footer); - this._renderMatrix(theProject.columnModel.columns); this._level = DialogSystem.showDialog(frame); + this._renderMatrix(); }; -ScatterplotDialog.prototype._renderMatrix = function(columns) { +ScatterplotDialog.prototype._renderMatrix = function() { var self = this; + var columns = theProject.columnModel.columns; - var container = this._elmts.tableContainer; - + var container = this._elmts.tableContainer.html( + '
Processing...
' + ); + if (columns.length > 0) { var table = $('
').addClass("scatterplot-matrix-table")[0]; @@ -51,8 +100,10 @@ ScatterplotDialog.prototype._renderMatrix = function(columns) { var plotter_params = { 'cx' : cx.name, 'cy' : cy.name, - 'w' : 20, - 'h' : 20 + 'w' : self._plot_size, + 'h' : self._plot_size, + 'dot': self._dot_size, + 'dim': self._plot_method }; var params = { project: theProject.id, diff --git a/src/main/webapp/styles/dialogs/scatterplot-dialog.css b/src/main/webapp/styles/dialogs/scatterplot-dialog.css index 6732d819c..dd86562a9 100644 --- a/src/main/webapp/styles/dialogs/scatterplot-dialog.css +++ b/src/main/webapp/styles/dialogs/scatterplot-dialog.css @@ -4,12 +4,15 @@ border: 1px solid #aaa; } +.clustering-dialog-controls { + margin-right: 2em; +} + table.scatterplot-matrix-table { border-collapse: collapse; } table.scatterplot-matrix-table > tbody > tr > td { - padding: 2px; text-align: center; vertical-align: middle; }