+
);
diff --git a/src/firefly/js/visualize/XYPlotCntlr.js b/src/firefly/js/visualize/XYPlotCntlr.js
index e28cdbcfb4..4d9cad546e 100644
--- a/src/firefly/js/visualize/XYPlotCntlr.js
+++ b/src/firefly/js/visualize/XYPlotCntlr.js
@@ -41,6 +41,8 @@ const RESET_ZOOM = `${XYPLOT_DATA_KEY}/RESET_ZOOM`;
xyPlotParams: {
title: string
xyRatio: number
+ nbins {x,y}
+ shading: string (lin|log)
selection: {xMin, xMax, yMin, yMax} // currently selected rectangle
zoom: {xMin, xMax, yMin, yMax} // currently zoomed rectangle
stretch: string (fit|fill)
@@ -49,18 +51,12 @@ const RESET_ZOOM = `${XYPLOT_DATA_KEY}/RESET_ZOOM`;
label
unit
options: [grid,log,flip]
- nbins
- min
- max
}
y: {
columnOrExpr
label
unit
options: [grid,log,flip]
- nbins
- min
- max
}
}
*/
@@ -244,11 +240,19 @@ function fetchPlotData(dispatch, activeTableServerRequest, xyPlotParams, chartId
limits = [xMin, xMax, yMin, yMax];
}
+ let maxBins = 10000;
+ let xyRatio = xyPlotParams.xyRatio || 1.0;
+ if (xyPlotParams.nbins) {
+ const {x, y} = xyPlotParams.nbins;
+ maxBins = x*y;
+ xyRatio = x/y;
+ }
+
const req = Object.assign({}, omit(activeTableServerRequest, ['tbl_id', 'META_INFO']), {
'startIdx' : 0,
'pageSize' : 1000000,
//'inclCols' : `${xyPlotParams.x.columnOrExpr},${xyPlotParams.y.columnOrExpr}`, // ignored if 'decimate' is present
- 'decimate' : serializeDecimateInfo(xyPlotParams.x.columnOrExpr, xyPlotParams.y.columnOrExpr, 10000, 1.0, ...limits)
+ 'decimate' : serializeDecimateInfo(xyPlotParams.x.columnOrExpr, xyPlotParams.y.columnOrExpr, maxBins, xyRatio, ...limits)
});
req.tbl_id = `xy-${chartId}`;
diff --git a/src/firefly/js/visualize/XYPlotOptions.jsx b/src/firefly/js/visualize/XYPlotOptions.jsx
index dc16aaad26..bac4588c63 100644
--- a/src/firefly/js/visualize/XYPlotOptions.jsx
+++ b/src/firefly/js/visualize/XYPlotOptions.jsx
@@ -3,7 +3,7 @@
*/
import React, {PropTypes} from 'react';
-import {get} from 'lodash';
+import {get, isUndefined, omitBy} from 'lodash';
import ColValuesStatistics from './ColValuesStatistics.js';
import CompleteButton from '../ui/CompleteButton.jsx';
@@ -17,7 +17,9 @@ import {SuggestBoxInputField} from '../ui/SuggestBoxInputField.jsx';
import {FieldGroupCollapsible} from '../ui/panel/CollapsiblePanel.jsx';
import {plotParamsShape} from './XYPlot.jsx';
-import {showInfoPopup} from '../ui/PopupUtil.jsx';
+const DECI_ENABLE_SIZE = 5000;
+
+const helpStyle = {fontStyle: 'italic', color: '#808080', paddingBottom: 10};
/*
* Split content into prior content and the last alphanumeric token in the text
@@ -65,12 +67,6 @@ var XYPlotOptions = React.createClass({
const xName = get(flds, ['x.columnOrExpr']);
const yName = get(flds, ['y.columnOrExpr']);
- // workaround for validator not being called for unchanged fields
- if (!xName || !yName) {
- showInfoPopup('X and Y must not be empty.', 'Action required.');
- return;
- }
-
const xOptions = get(flds, ['x.options']);
let xLabel = get(flds, ['x.label']), xUnit = get(flds, ['x.unit']);
if (!xLabel) { xLabel = xName; }
@@ -82,7 +78,8 @@ var XYPlotOptions = React.createClass({
if (!yLabel) { yLabel = yName; }
if (!yUnit) {yUnit = this.getUnit(yName); }
-
+ const nbinsX = get(flds, ['nbins.x']);
+ const nbinsY = get(flds, ['nbins.y']);
/*
const axisParamsShape = PropTypes.shape({
@@ -90,24 +87,25 @@ var XYPlotOptions = React.createClass({
label : PropTypes.string,
unit : PropTypes.string,
options : PropTypes.string, // ex. 'grid,log,flip'
- nbins : PropTypes.number,
- min : PropTypes.number,
- max : PropTypes.number
});
const xyPlotParamsShape = PropTypes.shape({
- xyRatio : PropTypes.number,
+ xyRatio : PropTypes.string,
stretch : PropTypes.oneOf(['fit','fill']),
+ nbins : PropTypes.shape({x : PropTypes.number, y : PropTypes.number}),
+ shading : PropTypes.oneOf(['lin', 'log']),
x : axisParamsShape,
y : axisParamsShape
});
*/
- const xyPlotParams = {
- xyRatio : flds.xyRatio ? flds.xyRatio : undefined,
+ const xyPlotParams = omitBy({
+ xyRatio : flds.xyRatio || undefined,
stretch : flds.stretch,
+ nbins : (nbinsX && nbinsY) ? {x: Number(nbinsX), y: Number(nbinsY)} : undefined,
+ shading: flds.shading || undefined,
x : { columnOrExpr : xName, label : xLabel, unit : xUnit, options : xOptions},
y : { columnOrExpr : yName, label : yLabel, unit : yUnit, options : yOptions}
- };
+ }, isUndefined);
this.props.onOptionsSelected(xyPlotParams);
},
@@ -116,6 +114,54 @@ var XYPlotOptions = React.createClass({
// TODO: do I need to do anything here?
},
+ renderBinningOptions() {
+ const { colValStats, groupKey, xyPlotParams }= this.props;
+ const displayBinningOptions = Boolean(colValStats.find((el) => { return el.numpoints>DECI_ENABLE_SIZE; }));
+ if (displayBinningOptions) {
+ return (
+
+
+
+
+ );
+ } else { return null; }
+ },
render() {
const { colValStats, groupKey, xyPlotParams }= this.props;
@@ -157,11 +203,16 @@ var XYPlotOptions = React.createClass({
+
+ For X and Y, enter a column or an expression
+ ex. log(col); 100*col1/col2; col1-col2
+
+
+ Enter display aspect ratio below.
+ Leave it blank to use all available space.
+
+ {this.renderBinningOptions()}
{
+ if (histogramState[cid].tblId === tbl_id) {
+ const histogramParams = histogramState[cid].histogramParams;
+ HistogramCntlr.dispatchLoadColData(cid, histogramParams, request);
+ }
+ });
}
xyPlotState = flux.getState()[XYPlotCntlr.XYPLOT_DATA_KEY];
@@ -47,13 +59,6 @@ export function* syncCharts() {
}
});
- histogramState = flux.getState()[HistogramCntlr.HISTOGRAM_DATA_KEY];
- Object.keys(histogramState).forEach((cid) => {
- if (histogramState[cid].tblId === tbl_id) {
- const histogramParams = histogramState[cid].histogramParams;
- HistogramCntlr.dispatchLoadColData(cid, histogramParams, request);
- }
- });
break;
}
}