Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React finance precursor #2525

Merged
merged 10 commits into from Apr 5, 2018
@@ -2364,14 +2364,15 @@ plots.doCalcdata = function(gd, traces) {
// clear stuff that should recomputed in 'regular' loop
if(hasCalcTransform) clearAxesCalc(axList);

// 'regular' loop
for(i = 0; i < fullData.length; i++) {
var cd = [];

function calci(i, isContainer) {
trace = fullData[i];
_module = trace._module;

if(!!_module.isContainer !== isContainer) return;

This comment has been minimized.

Copy link
@etpinard

etpinard Apr 5, 2018

Member

Ha. Nice fix. I wonder if other carpet-dependent blocks (e.g. here) could be simplified (or at least generatlized) using _module.isContainer?

This comment has been minimized.

Copy link
@alexcjohnson

alexcjohnson Apr 5, 2018

Author Contributor

Probably some such blocks could... though I don't see much to do with that carpetDependents loop. It might be nice to move it out of plots/plots and into the carpet module, but probably not in this PR.


var cd = [];

if(trace.visible === true) {
_module = trace._module;

// keep ref of index-to-points map object of the *last* enabled transform,
// this index-to-points map object is required to determine the calcdata indices
@@ -2406,6 +2407,11 @@ plots.doCalcdata = function(gd, traces) {
calcdata[i] = cd;
}

// 'regular' loop - make sure container traces (eg carpet) calc before
// contained traces (eg contourcarpet)
for(i = 0; i < fullData.length; i++) calci(i, true);
for(i = 0; i < fullData.length; i++) calci(i, false);

This comment has been minimized.

Copy link
@alexcjohnson

alexcjohnson Apr 4, 2018

Author Contributor

Because I moved convertColumnData and setConvert for carpet traces from the supplyDefaults step to the calc step, we need to ensure carpet.calc happens before contourcarpet.calc and scattercarpet.calc. I'm not sure if we're ever going to have another situation like this where one trace essentially lives inside another, but in case we do this seemed like a reasonably generic way to handle it.


Registry.getComponentMethod('fx', 'calc')(gd);
};

@@ -103,7 +103,10 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, options)
handleCalendarDefaults(containerIn, containerOut, 'calendar', options.calendar);
}

// we need some of the other functions setConvert attaches, but for
// path finding, override pixel scaling to simple passthrough (identity)
setConvert(containerOut, options.fullLayout);
containerOut.c2p = Lib.identity;

var dfltColor = coerce('color', options.dfltColor);
// if axis.color was provided, use it for fonts too; otherwise,
@@ -17,25 +17,37 @@ var calcLabels = require('./calc_labels');
var calcClipPath = require('./calc_clippath');
var clean2dArray = require('../heatmap/clean_2d_array');
var smoothFill2dArray = require('./smooth_fill_2d_array');
var hasColumns = require('./has_columns');
var convertColumnData = require('../heatmap/convert_column_xyz');
var setConvert = require('./set_convert');

module.exports = function calc(gd, trace) {
var xa = Axes.getFromId(gd, trace.xaxis || 'x');
var ya = Axes.getFromId(gd, trace.yaxis || 'y');
var xa = Axes.getFromId(gd, trace.xaxis);
var ya = Axes.getFromId(gd, trace.yaxis);
var aax = trace.aaxis;
var bax = trace.baxis;
var a = trace._a = trace.a;
var b = trace._b = trace.b;

var t = {};
var x;
var x = trace.x;
var y = trace.y;
var cols = [];
if(x && !hasColumns(x)) cols.push('x');
if(y && !hasColumns(y)) cols.push('y');

if(cols.length) {
convertColumnData(trace, aax, bax, 'a', 'b', cols);
}

var a = trace._a = trace._a || trace.a;
var b = trace._b = trace._b || trace.b;
x = trace._x || trace.x;
y = trace._y || trace.y;

var t = {};

if(trace._cheater) {
var avals = aax.cheatertype === 'index' ? a.length : a;
var bvals = bax.cheatertype === 'index' ? b.length : b;
x = cheaterBasis(avals, bvals, trace.cheaterslope);
} else {
x = trace.x;
}

trace._x = x = clean2dArray(x);
@@ -48,6 +60,8 @@ module.exports = function calc(gd, trace) {
smoothFill2dArray(x, a, b);
smoothFill2dArray(y, a, b);

setConvert(trace);

// create conversion functions that depend on the data
trace.setScale();

@@ -16,14 +16,14 @@ module.exports = function calcGridlines(trace, cd, axisLetter, crossAxisLetter)
var eps, bounds, n1, n2, n, value, v;
var j1, v0, v1, d;

var data = trace[axisLetter];
var data = trace['_' + axisLetter];
var axis = trace[axisLetter + 'axis'];

var gridlines = axis._gridlines = [];
var minorgridlines = axis._minorgridlines = [];
var boundarylines = axis._boundarylines = [];

var crossData = trace[crossAxisLetter];
var crossData = trace['_' + crossAxisLetter];
var crossAxis = trace[crossAxisLetter + 'axis'];

if(axis.tickmode === 'array') {
@@ -34,8 +34,8 @@ module.exports = function calcGridlines(trace, cd, axisLetter, crossAxisLetter)
var ycp = trace._yctrl;
var nea = xcp[0].length;
var neb = xcp.length;
var na = trace.a.length;
var nb = trace.b.length;
var na = trace._a.length;
var nb = trace._b.length;

Axes.prepTicks(axis);

@@ -12,7 +12,6 @@
var Lib = require('../../lib');
var handleXYDefaults = require('./xy_defaults');
var handleABDefaults = require('./ab_defaults');
var setConvert = require('./set_convert');
var attributes = require('./attributes');
var colorAttrs = require('../../components/color/attributes');

@@ -49,8 +48,6 @@ module.exports = function supplyDefaults(traceIn, traceOut, dfltColor, fullLayou
// and i goes from 0 to a.length - 1.
var len = handleXYDefaults(traceIn, traceOut, coerce);

setConvert(traceOut);

if(traceOut._cheater) {
coerce('cheaterslope');
}
@@ -16,6 +16,7 @@ Carpet.supplyDefaults = require('./defaults');
Carpet.plot = require('./plot');
Carpet.calc = require('./calc');
Carpet.animatable = true;
Carpet.isContainer = true; // so carpet traces get `calc` before other traces

Carpet.moduleType = 'trace';
Carpet.name = 'carpet';
@@ -25,10 +25,10 @@ var createJDerivativeEvaluator = require('./create_j_derivative_evaluator');
* p: screen-space pixel coordinates
*/
module.exports = function setConvert(trace) {
var a = trace.a;
var b = trace.b;
var na = trace.a.length;
var nb = trace.b.length;
var a = trace._a;
var b = trace._b;
var na = a.length;
var nb = b.length;
var aax = trace.aaxis;
var bax = trace.baxis;

@@ -60,10 +60,6 @@ module.exports = function setConvert(trace) {
return a < amin || a > amax || b < bmin || b > bmax;
};

// XXX: ONLY PASSTHRU. ONLY. No, ONLY.
aax.c2p = function(v) { return v; };
bax.c2p = function(v) { return v; };

trace.setScale = function() {
var x = trace._x;
var y = trace._y;
@@ -9,28 +9,11 @@

'use strict';

var hasColumns = require('./has_columns');
var convertColumnData = require('../heatmap/convert_column_xyz');

module.exports = function handleXYDefaults(traceIn, traceOut, coerce) {
var cols = [];
var x = coerce('x');

var needsXTransform = x && !hasColumns(x);
if(needsXTransform) cols.push('x');

traceOut._cheater = !x;

var y = coerce('y');

var needsYTransform = y && !hasColumns(y);
if(needsYTransform) cols.push('y');

if(!x && !y) return;

if(cols.length) {
convertColumnData(traceOut, traceOut.aaxis, traceOut.baxis, 'a', 'b', cols);
}
traceOut._cheater = !x;

return true;
return !!x || !!y;
};
@@ -70,15 +70,17 @@ function heatmappishCalc(gd, trace) {
bax._minDtick = 0;

if(hasColumns(trace)) convertColumnData(trace, aax, bax, 'a', 'b', ['z']);
a = trace._a = trace._a || trace.a;
b = trace._b = trace._b || trace.b;

a = trace.a ? aax.makeCalcdata(trace, 'a') : [];
b = trace.b ? bax.makeCalcdata(trace, 'b') : [];
a = a ? aax.makeCalcdata(trace, '_a') : [];
b = b ? bax.makeCalcdata(trace, '_b') : [];
a0 = trace.a0 || 0;
da = trace.da || 1;
b0 = trace.b0 || 0;
db = trace.db || 1;

z = clean2dArray(trace.z, trace.transpose);
z = trace._z = clean2dArray(trace._z || trace.z, trace.transpose);

trace._emptypoints = findEmpties(z);
trace._interpz = interp2d(z, trace._emptypoints, trace._interpz);
@@ -58,10 +58,12 @@ module.exports = function calc(gd, trace) {
z = binned.z;
}
else {
var zIn = trace.z;
if(hasColumns(trace)) {
convertColumnData(trace, xa, ya, 'x', 'y', ['z']);
x = trace.x;
y = trace.y;
x = trace._x;
y = trace._y;
zIn = trace._z;
} else {
x = trace.x ? xa.makeCalcdata(trace, 'x') : [];
y = trace.y ? ya.makeCalcdata(trace, 'y') : [];
@@ -72,7 +74,7 @@ module.exports = function calc(gd, trace) {
y0 = trace.y0 || 0;
dy = trace.dy || 1;

z = clean2dArray(trace.z, trace.transpose);
z = clean2dArray(zIn, trace.transpose);

if(isContour || trace.connectgaps) {
trace._emptypoints = findEmpties(z);
@@ -131,7 +133,7 @@ module.exports = function calc(gd, trace) {
x: xArray,
y: yArray,
z: z,
text: trace.text
text: trace._text || trace.text
};

if(xIn && xIn.length === xArray.length - 1) cd0.xCenter = xIn;
@@ -66,14 +66,10 @@ module.exports = function convertColumnData(trace, ax1, ax2, var1Name, var2Name,
}
}

// hack for Plotly.react - save the input arrays for diffing purposes
trace['_input_' + var1Name] = trace[var1Name];
trace['_input_' + var2Name] = trace[var2Name];
trace[var1Name] = col1vals;
trace[var2Name] = col2vals;
trace['_' + var1Name] = col1vals;
trace['_' + var2Name] = col2vals;
for(j = 0; j < arrayVarNames.length; j++) {
trace['_input_' + arrayVarNames[j]] = trace[arrayVarNames[j]];
trace[arrayVarNames[j]] = newArrays[j];
trace['_' + arrayVarNames[j]] = newArrays[j];
}
if(hasColumnText) trace.text = text;
if(hasColumnText) trace._text = text;
};
@@ -174,17 +174,21 @@ describe('heatmap convertColumnXYZ', function() {
var xa = makeMockAxis();
var ya = makeMockAxis();

function checkConverted(trace, x, y, z) {
convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']);
expect(trace._x).toEqual(x);
expect(trace._y).toEqual(y);
expect(trace._z).toEqual(z);
}

it('should convert x/y/z columns to z(x,y)', function() {
trace = {
x: [1, 1, 1, 2, 2, 2],
y: [1, 2, 3, 1, 2, 3],
z: [1, 2, 3, 4, 5, 6]
};

convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']);
expect(trace.x).toEqual([1, 2]);
expect(trace.y).toEqual([1, 2, 3]);
expect(trace.z).toEqual([[1, 4], [2, 5], [3, 6]]);
checkConverted(trace, [1, 2], [1, 2, 3], [[1, 4], [2, 5], [3, 6]]);
});

it('should convert x/y/z columns to z(x,y) with uneven dimensions', function() {
@@ -194,10 +198,7 @@ describe('heatmap convertColumnXYZ', function() {
z: [1, 2, 4, 5, 6]
};

convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']);
expect(trace.x).toEqual([1, 2]);
expect(trace.y).toEqual([1, 2, 3]);
expect(trace.z).toEqual([[1, 4], [2, 5], [, 6]]);
checkConverted(trace, [1, 2], [1, 2, 3], [[1, 4], [2, 5], [, 6]]);
});

it('should convert x/y/z columns to z(x,y) with missing values', function() {
@@ -207,10 +208,7 @@ describe('heatmap convertColumnXYZ', function() {
z: [1, null, 4, 5, 6]
};

convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']);
expect(trace.x).toEqual([1, 2]);
expect(trace.y).toEqual([1, 2, 3]);
expect(trace.z).toEqual([[1, 4], [null, 5], [, 6]]);
checkConverted(trace, [1, 2], [1, 2, 3], [[1, 4], [null, 5], [, 6]]);
});

it('should convert x/y/z/text columns to z(x,y) and text(x,y)', function() {
@@ -222,7 +220,7 @@ describe('heatmap convertColumnXYZ', function() {
};

convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']);
expect(trace.text).toEqual([['a', 'd'], ['b', 'e'], ['c', 'f']]);
expect(trace._text).toEqual([['a', 'd'], ['b', 'e'], ['c', 'f']]);
});

it('should convert x/y/z columns to z(x,y) with out-of-order data', function() {
@@ -253,20 +251,19 @@ describe('heatmap convertColumnXYZ', function() {
]
};

convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']);
expect(trace.x).toEqual(
[-88596, -65484, -42372, -19260, 3852, 26964, 50076, 73188]);
expect(trace.y).toEqual(
[-78096.2, -52106.6, -26117, -127.4, 25862.2, 51851.8, 77841.4]);
expect(trace.z).toEqual([
[,, 4.154291, 4.404264, 4.33847, 4.270931,,, ],
[, 4.339848, 4.39907, 4.345006, 4.315032, 4.295618, 4.262052,, ],
[3.908434, 4.433257, 4.364234, 4.308714, 4.275516, 4.126979, 4.296483, 4.320471],
[4.032226, 4.381492, 4.328922, 4.24046, 4.349151, 4.202861, 4.256402, 4.28972],
[3.956225, 4.337909, 4.31226, 4.259435, 4.146854, 4.235799, 4.238752, 4.299876],
[, 4.210373, 4.32009, 4.246728, 4.293992, 4.316364, 4.361856,, ],
[,, 4.234497, 4.321701, 4.450315, 4.416136,,, ]
]);
checkConverted(trace,
[-88596, -65484, -42372, -19260, 3852, 26964, 50076, 73188],
[-78096.2, -52106.6, -26117, -127.4, 25862.2, 51851.8, 77841.4],
[
[,, 4.154291, 4.404264, 4.33847, 4.270931,,, ],
[, 4.339848, 4.39907, 4.345006, 4.315032, 4.295618, 4.262052,, ],
[3.908434, 4.433257, 4.364234, 4.308714, 4.275516, 4.126979, 4.296483, 4.320471],
[4.032226, 4.381492, 4.328922, 4.24046, 4.349151, 4.202861, 4.256402, 4.28972],
[3.956225, 4.337909, 4.31226, 4.259435, 4.146854, 4.235799, 4.238752, 4.299876],
[, 4.210373, 4.32009, 4.246728, 4.293992, 4.316364, 4.361856,, ],
[,, 4.234497, 4.321701, 4.450315, 4.416136,,, ]
]
);
});

it('should convert x/y/z columns with nulls to z(x,y)', function() {
@@ -282,11 +279,7 @@ describe('heatmap convertColumnXYZ', function() {
z: [0, 50, 100, 50, null, 255, 100, 510, 1010]
};

convertColumnXYZ(trace, xa, ya, 'x', 'y', ['z']);

expect(trace.x).toEqual([0, 5, 10]);
expect(trace.y).toEqual([0, 5, 10]);
expect(trace.z).toEqual([
checkConverted(trace, [0, 5, 10], [0, 5, 10], [
[0, 50, 100],
[50, undefined, 510],
[100, 255, 1010]
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.