diff --git a/src/main/java/com/metaweb/gridworks/browsing/facets/ExpressionNumericRowBinner.java b/src/main/java/com/metaweb/gridworks/browsing/facets/ExpressionNumericRowBinner.java new file mode 100644 index 000000000..c95e2cf8a --- /dev/null +++ b/src/main/java/com/metaweb/gridworks/browsing/facets/ExpressionNumericRowBinner.java @@ -0,0 +1,61 @@ +package com.metaweb.gridworks.browsing.facets; + +import java.util.Properties; + +import com.metaweb.gridworks.browsing.RowVisitor; +import com.metaweb.gridworks.expr.Evaluable; +import com.metaweb.gridworks.model.Cell; +import com.metaweb.gridworks.model.Project; +import com.metaweb.gridworks.model.Row; + +public class ExpressionNumericRowBinner implements RowVisitor { + final protected Evaluable _evaluable; + final protected int _cellIndex; + final protected NumericBinIndex _index; + + final public int[] bins; + + public ExpressionNumericRowBinner(Evaluable evaluable, int cellIndex, NumericBinIndex index) { + _evaluable = evaluable; + _cellIndex = cellIndex; + _index = index; + bins = new int[_index.getBins().length]; + } + + @Override + public boolean visit(Project project, int rowIndex, Row row) { + if (_cellIndex < row.cells.size()) { + Cell cell = row.cells.get(_cellIndex); + if (cell != null) { + Properties bindings = new Properties(); + + bindings.put("project", project); + bindings.put("cell", cell); + bindings.put("value", cell.value); + + Object value = _evaluable.evaluate(bindings); + if (value != null) { + if (value.getClass().isArray()) { + Object[] a = (Object[]) value; + for (Object v : a) { + processValue(v); + } + } else { + processValue(value); + } + } + } + } + return false; + } + + protected void processValue(Object value) { + if (value instanceof Number) { + double d = ((Number) value).doubleValue(); + + int bin = (int) Math.round((d - _index.getMin()) / _index.getStep()); + + bins[bin]++; + } + } +} diff --git a/src/main/java/com/metaweb/gridworks/browsing/facets/RangeFacet.java b/src/main/java/com/metaweb/gridworks/browsing/facets/RangeFacet.java index d7c0c168c..5d36cd941 100644 --- a/src/main/java/com/metaweb/gridworks/browsing/facets/RangeFacet.java +++ b/src/main/java/com/metaweb/gridworks/browsing/facets/RangeFacet.java @@ -24,6 +24,7 @@ public class RangeFacet implements Facet { protected double _min; protected double _max; protected double _step; + protected int[] _baseBins; protected int[] _bins; protected double _from; @@ -50,6 +51,12 @@ public class RangeFacet implements Facet { } writer.endArray(); + writer.key("baseBins"); writer.array(); + for (int b : _baseBins) { + writer.value(b); + } + writer.endArray(); + writer.key("mode"); writer.value(_mode); if ("min".equals(_mode)) { writer.key("from"); writer.value(_from); @@ -118,6 +125,13 @@ public class RangeFacet implements Facet { _min = index.getMin(); _max = index.getMax(); _step = index.getStep(); - _bins = index.getBins(); + _baseBins = index.getBins(); + + ExpressionNumericRowBinner binner = + new ExpressionNumericRowBinner(_eval, _cellIndex, index); + + filteredRows.accept(project, binner); + + _bins = binner.bins; } } diff --git a/src/main/webapp/scripts/project/range-facet.js b/src/main/webapp/scripts/project/range-facet.js index 12e7cf6f9..c9ddecf29 100644 --- a/src/main/webapp/scripts/project/range-facet.js +++ b/src/main/webapp/scripts/project/range-facet.js @@ -138,6 +138,7 @@ RangeFacet.prototype.updateState = function(data) { this._config.min = data.min; this._config.max = data.max; this._config.step = data.step; + this._baseBins = data.baseBins; this._bins = data.bins; switch (this._config.mode) { @@ -165,16 +166,22 @@ RangeFacet.prototype.render = function() { this._sliderDiv.slider("option", "step", this._config.step); var max = 0; - for (var i = 0; i < this._bins.length; i++) { - max = Math.max(max, this._bins[i]); + for (var i = 0; i < this._baseBins.length; i++) { + max = Math.max(max, this._baseBins[i]); } + if (max == 0) { this._histogramDiv.hide(); } else { - var a = []; - for (var i = 0; i < this._bins.length; i++) { + var values = []; + var diffs = []; + + for (var i = 0; i < this._baseBins.length; i++) { var v = Math.ceil(100 * this._bins[i] / max); - a.push(v == 0 ? 0 : Math.max(2, v)); // use min 2 to make sure something shows up + var diff = Math.ceil(100 * this._baseBins[i] / max) - v; + + values.push(v == 0 ? 0 : Math.max(2, v)); // use min 2 to make sure something shows up + diffs.push(diff == 0 ? 0 : Math.max(2, diff)); } this._histogramDiv.empty().show(); @@ -182,8 +189,8 @@ RangeFacet.prototype.render = function() { "http://chart.apis.google.com/chart?" + [ "chs=" + this._histogramDiv[0].offsetWidth + "x50", //"cht=ls&chm=o,ff6600,0,-1,3&chls=0", // use for line plot - "cht=bvs&chbh=r,0&chco=000088", // use for histogram - "chd=t:" + a.join(",") + "cht=bvs&chbh=r,0&chco=000088,aaaaff", // use for histogram + "chd=t:" + values.join(",") + "|" + diffs.join(",") ].join("&") ).appendTo(this._histogramDiv); }