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
This commit is contained in:
Stefano Mazzocchi 2010-04-13 00:25:43 +00:00
parent 7391f760db
commit ba85f50e39
3 changed files with 137 additions and 34 deletions

View File

@ -30,8 +30,20 @@ import com.metaweb.gridworks.model.Row;
public class ScatterplotCharter { 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() { public String getContentType() {
return "image/png"; return "image/png";
} }
@ -47,23 +59,30 @@ public class ScatterplotCharter {
class DrawingRowVisitor implements RowVisitor { class DrawingRowVisitor implements RowVisitor {
private static final double px = 0.5f;
boolean process = true; boolean process = true;
boolean smoothed = false;
int width = 50;
int height = 50;
int width;
int height;
int col_x; int col_x;
int col_y; int col_y;
int dim;
double w; double w;
double h; double h;
double min_x; double min_x;
double min_y; double min_y;
double max_x; double max_x;
double max_y; 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_x;
NumericBinIndex index_y; NumericBinIndex index_y;
@ -76,8 +95,8 @@ public class ScatterplotCharter {
if (column_x != null) { if (column_x != null) {
col_x = column_x.getCellIndex(); col_x = column_x.getCellIndex();
index_x = getBinIndex(project, column_x); index_x = getBinIndex(project, column_x);
min_x = index_x.getMin() * 1.1d; min_x = index_x.getMin();
max_x = index_x.getMax() * 1.1d; max_x = index_x.getMax();
} }
String col_y_name = o.getString("cy"); String col_y_name = o.getString("cy");
@ -85,12 +104,30 @@ public class ScatterplotCharter {
if (column_y != null) { if (column_y != null) {
col_y = column_y.getCellIndex(); col_y = column_y.getCellIndex();
index_y = getBinIndex(project, column_y); index_y = getBinIndex(project, column_y);
min_y = index_y.getMin() * 1.1d; min_y = index_y.getMin();
max_y = index_y.getMax() * 1.1d; max_y = index_y.getMax();
} }
width = o.getInt("w"); width = (o.has("w")) ? o.getInt("w") : 20;
height = o.getInt("h"); 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; w = (double) width;
h = (double) height; h = (double) height;
@ -103,8 +140,8 @@ public class ScatterplotCharter {
AffineTransform t = AffineTransform.getTranslateInstance(0,h); AffineTransform t = AffineTransform.getTranslateInstance(0,h);
t.concatenate(AffineTransform.getScaleInstance(1.0d, -1.0d)); t.concatenate(AffineTransform.getScaleInstance(1.0d, -1.0d));
g2.setTransform(t); g2.setTransform(t);
g2.setColor(COLOR); g2.setColor(color);
g2.setPaint(COLOR); g2.setPaint(color);
} else { } else {
image = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR); image = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR);
process = false; process = false;
@ -112,10 +149,11 @@ public class ScatterplotCharter {
} }
private NumericBinIndex getBinIndex(Project project, Column column) { private NumericBinIndex getBinIndex(Project project, Column column) {
String key = "numeric-bin:value"; String expression = "value";
String key = "numeric-bin:" + expression;
Evaluable eval = null; Evaluable eval = null;
try { try {
eval = MetaParser.parse("value"); eval = MetaParser.parse(expression);
} catch (ParsingException e) { } catch (ParsingException e) {
// this should never happen // this should never happen
} }
@ -137,9 +175,20 @@ public class ScatterplotCharter {
double xv = ((Number) cellx.value).doubleValue(); double xv = ((Number) cellx.value).doubleValue();
double yv = ((Number) celly.value).doubleValue(); double yv = ((Number) celly.value).doubleValue();
double x = (xv - min_x) * w / max_x; double x;
double y = (yv - min_y) * h / max_y; double y;
g2.fill(new Rectangle2D.Double(x, y, px, px));
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));
} }
} }

View File

@ -1,11 +1,14 @@
function ScatterplotDialog() { function ScatterplotDialog() {
this._createDialog(); this._createDialog();
this._plot_method = "lin";
this._plot_size = 20;
this._dot_size = 0.1;
} }
ScatterplotDialog.prototype._createDialog = function() { ScatterplotDialog.prototype._createDialog = function() {
var self = this; var self = this;
var frame = DialogSystem.createDialog(); var frame = DialogSystem.createDialog();
frame.width("900px"); frame.width("1100px");
var header = $('<div></div>').addClass("dialog-header").text('Scatterplot Matrix').appendTo(frame); var header = $('<div></div>').addClass("dialog-header").text('Scatterplot Matrix').appendTo(frame);
var body = $('<div></div>').addClass("dialog-body").appendTo(frame); var body = $('<div></div>').addClass("dialog-body").appendTo(frame);
@ -17,29 +20,75 @@ ScatterplotDialog.prototype._createDialog = function() {
'</tr></table>' + '</tr></table>' +
'</div>' '</div>'
).appendTo(frame); ).appendTo(frame);
var html = $( var html = $(
'<div class="grid-layout layout-normal">' + '<div class="grid-layout layout-normal"><table width="100%">' +
'<div bind="tableContainer" class="scatterplot-dialog-table-container"></div>' + '<tr>' +
'</div>' '<td>' +
'<span class="clustering-dialog-controls">Plot type: <select bind="plotSelector">' +
'<option selected="true">linear</option>' +
'<option>log-log</option>' +
'</select></span>' +
'<span class="clustering-dialog-controls">Plot Size: <input bind="plotSize" type="test" size="2" value="20"> px</span>' +
'<span class="clustering-dialog-controls">Dot Size: <input bind="dotSize" type="test" size="2" value="0.1"> px</span>' +
'</td>' +
'</tr>' +
'<tr>' +
'<td>' +
'<div bind="tableContainer" class="scatterplot-dialog-table-container"></div>' +
'</td>' +
'</tr>' +
'</table></div>'
).appendTo(body); ).appendTo(body);
this._elmts = DOM.bind(html); 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 left_footer = footer.find(".left");
var right_footer = footer.find(".right"); var right_footer = footer.find(".right");
$('<button></button>').text("Close").click(function() { self._dismiss(); }).appendTo(right_footer); $('<button></button>').text("Close").click(function() { self._dismiss(); }).appendTo(right_footer);
this._renderMatrix(theProject.columnModel.columns);
this._level = DialogSystem.showDialog(frame); this._level = DialogSystem.showDialog(frame);
this._renderMatrix();
}; };
ScatterplotDialog.prototype._renderMatrix = function(columns) { ScatterplotDialog.prototype._renderMatrix = function() {
var self = this; var self = this;
var columns = theProject.columnModel.columns;
var container = this._elmts.tableContainer; var container = this._elmts.tableContainer.html(
'<div style="margin: 1em; font-size: 130%; color: #888;">Processing... <img src="/images/small-spinner.gif"></div>'
);
if (columns.length > 0) { if (columns.length > 0) {
var table = $('<table></table>').addClass("scatterplot-matrix-table")[0]; var table = $('<table></table>').addClass("scatterplot-matrix-table")[0];
@ -51,8 +100,10 @@ ScatterplotDialog.prototype._renderMatrix = function(columns) {
var plotter_params = { var plotter_params = {
'cx' : cx.name, 'cx' : cx.name,
'cy' : cy.name, 'cy' : cy.name,
'w' : 20, 'w' : self._plot_size,
'h' : 20 'h' : self._plot_size,
'dot': self._dot_size,
'dim': self._plot_method
}; };
var params = { var params = {
project: theProject.id, project: theProject.id,

View File

@ -4,12 +4,15 @@
border: 1px solid #aaa; border: 1px solid #aaa;
} }
.clustering-dialog-controls {
margin-right: 2em;
}
table.scatterplot-matrix-table { table.scatterplot-matrix-table {
border-collapse: collapse; border-collapse: collapse;
} }
table.scatterplot-matrix-table > tbody > tr > td { table.scatterplot-matrix-table > tbody > tr > td {
padding: 2px;
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;
} }