Skip to content

Commit ecec280

Browse files
committed
Merge branch 'master' into ohlc-global-offset
2 parents 4352dd8 + e1d440d commit ecec280

15 files changed

+4124
-77
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
"gl-line3d": "^1.1.0",
6767
"gl-mat4": "^1.1.2",
6868
"gl-mesh3d": "^1.2.0",
69-
"gl-plot2d": "^1.1.8",
69+
"gl-plot2d": "^1.1.9",
7070
"gl-plot3d": "^1.5.1",
7171
"gl-pointcloud2d": "^1.0.0",
7272
"gl-scatter2d": "^1.0.5",

src/plots/cartesian/axes.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1207,7 +1207,7 @@ axes.getSubplots = function(gd, ax) {
12071207
var i, j, sp;
12081208

12091209
// look for subplots in the data
1210-
var data = gd.data || [];
1210+
var data = gd._fullData || gd.data || [];
12111211

12121212
for(i = 0; i < data.length; i++) {
12131213
var trace = data[i];

src/plots/cartesian/axis_autotype.js

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* Copyright 2012-2016, Plotly, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
10+
'use strict';
11+
12+
var isNumeric = require('fast-isnumeric');
13+
14+
var Lib = require('../../lib');
15+
var cleanDatum = require('./clean_datum');
16+
17+
module.exports = function autoType(array) {
18+
if(moreDates(array)) return 'date';
19+
if(category(array)) return 'category';
20+
if(linearOK(array)) return 'linear';
21+
else return '-';
22+
};
23+
24+
// is there at least one number in array? If not, we should leave
25+
// ax.type empty so it can be autoset later
26+
function linearOK(array) {
27+
if(!array) return false;
28+
29+
for(var i = 0; i < array.length; i++) {
30+
if(isNumeric(array[i])) return true;
31+
}
32+
33+
return false;
34+
}
35+
36+
// does the array a have mostly dates rather than numbers?
37+
// note: some values can be neither (such as blanks, text)
38+
// 2- or 4-digit integers can be both, so require twice as many
39+
// dates as non-dates, to exclude cases with mostly 2 & 4 digit
40+
// numbers and a few dates
41+
function moreDates(a) {
42+
var dcnt = 0,
43+
ncnt = 0,
44+
// test at most 1000 points, evenly spaced
45+
inc = Math.max(1, (a.length - 1) / 1000),
46+
ai;
47+
48+
for(var i = 0; i < a.length; i += inc) {
49+
ai = a[Math.round(i)];
50+
if(Lib.isDateTime(ai)) dcnt += 1;
51+
if(isNumeric(ai)) ncnt += 1;
52+
}
53+
54+
return (dcnt > ncnt * 2);
55+
}
56+
57+
// are the (x,y)-values in td.data mostly text?
58+
// require twice as many categories as numbers
59+
function category(a) {
60+
// test at most 1000 points
61+
var inc = Math.max(1, (a.length - 1) / 1000),
62+
curvenums = 0,
63+
curvecats = 0,
64+
ai;
65+
66+
for(var i = 0; i < a.length; i += inc) {
67+
ai = cleanDatum(a[Math.round(i)]);
68+
if(isNumeric(ai)) curvenums++;
69+
else if(typeof ai === 'string' && ai !== '' && ai !== 'None') curvecats++;
70+
}
71+
72+
return curvecats > curvenums * 2;
73+
}

src/plots/cartesian/axis_defaults.js

+1-59
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ var handleTickLabelDefaults = require('./tick_label_defaults');
2323
var handleCategoryOrderDefaults = require('./category_order_defaults');
2424
var setConvert = require('./set_convert');
2525
var orderedCategories = require('./ordered_categories');
26-
var cleanDatum = require('./clean_datum');
2726
var axisIds = require('./axis_ids');
27+
var autoType = require('./axis_autotype');
2828

2929

3030
/**
@@ -207,13 +207,6 @@ function isBoxWithoutPositionCoords(trace, axLetter) {
207207
);
208208
}
209209

210-
function autoType(array) {
211-
if(moreDates(array)) return 'date';
212-
if(category(array)) return 'category';
213-
if(linearOK(array)) return 'linear';
214-
else return '-';
215-
}
216-
217210
function getFirstNonEmptyTrace(data, id, axLetter) {
218211
for(var i = 0; i < data.length; i++) {
219212
var trace = data[i];
@@ -228,54 +221,3 @@ function getFirstNonEmptyTrace(data, id, axLetter) {
228221
}
229222
}
230223
}
231-
232-
// is there at least one number in array? If not, we should leave
233-
// ax.type empty so it can be autoset later
234-
function linearOK(array) {
235-
if(!array) return false;
236-
237-
for(var i = 0; i < array.length; i++) {
238-
if(isNumeric(array[i])) return true;
239-
}
240-
241-
return false;
242-
}
243-
244-
// does the array a have mostly dates rather than numbers?
245-
// note: some values can be neither (such as blanks, text)
246-
// 2- or 4-digit integers can be both, so require twice as many
247-
// dates as non-dates, to exclude cases with mostly 2 & 4 digit
248-
// numbers and a few dates
249-
function moreDates(a) {
250-
var dcnt = 0,
251-
ncnt = 0,
252-
// test at most 1000 points, evenly spaced
253-
inc = Math.max(1, (a.length - 1) / 1000),
254-
ai;
255-
256-
for(var i = 0; i < a.length; i += inc) {
257-
ai = a[Math.round(i)];
258-
if(Lib.isDateTime(ai)) dcnt += 1;
259-
if(isNumeric(ai)) ncnt += 1;
260-
}
261-
262-
return (dcnt > ncnt * 2);
263-
}
264-
265-
// are the (x,y)-values in td.data mostly text?
266-
// require twice as many categories as numbers
267-
function category(a) {
268-
// test at most 1000 points
269-
var inc = Math.max(1, (a.length - 1) / 1000),
270-
curvenums = 0,
271-
curvecats = 0,
272-
ai;
273-
274-
for(var i = 0; i < a.length; i += inc) {
275-
ai = cleanDatum(a[Math.round(i)]);
276-
if(isNumeric(ai)) curvenums++;
277-
else if(typeof ai === 'string' && ai !== '' && ai !== 'None') curvecats++;
278-
}
279-
280-
return curvecats > curvenums * 2;
281-
}

src/plots/cartesian/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ exports.rangePlot = function(gd, plotinfo, cdSubplot) {
214214

215215
function makeSubplotData(gd) {
216216
var fullLayout = gd._fullLayout,
217-
subplots = Axes.getSubplots(gd);
217+
subplots = Object.keys(fullLayout._plots);
218218

219219
var subplotData = [],
220220
overlays = [];

src/plots/plots.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ plots.linkSubplots = function(newFullData, newFullLayout, oldFullData, oldFullLa
569569
newSubplots = newFullLayout._plots = {};
570570

571571
var mockGd = {
572-
data: newFullData,
572+
_fullData: newFullData,
573573
_fullLayout: newFullLayout
574574
};
575575

src/traces/scattergl/convert.js

+50-14
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ var isNumeric = require('fast-isnumeric');
1717

1818
var Lib = require('../../lib');
1919
var Axes = require('../../plots/cartesian/axes');
20+
var autoType = require('../../plots/cartesian/axis_autotype');
2021
var ErrorBars = require('../../components/errorbars');
2122
var str2RGBArray = require('../../lib/str2rgbarray');
2223
var truncate = require('../../lib/float32_truncate');
@@ -114,11 +115,13 @@ proto.handlePick = function(pickResult) {
114115
index = this.idToIndex[pickResult.pointId];
115116
}
116117

118+
var x = this.pickXData[index];
119+
117120
return {
118121
trace: this,
119122
dataCoord: pickResult.dataCoord,
120123
traceCoord: [
121-
this.pickXData[index],
124+
isNumeric(x) || !Lib.isDateTime(x) ? x : Lib.dateTime2ms(x),
122125
this.pickYData[index]
123126
],
124127
textLabel: Array.isArray(this.textLabels) ?
@@ -135,7 +138,7 @@ proto.handlePick = function(pickResult) {
135138

136139
// check if trace is fancy
137140
proto.isFancy = function(options) {
138-
if(this.scene.xaxis.type !== 'linear') return true;
141+
if(this.scene.xaxis.type !== 'linear' && this.scene.xaxis.type !== 'date') return true;
139142
if(this.scene.yaxis.type !== 'linear') return true;
140143

141144
if(!options.x || !options.y) return true;
@@ -259,6 +262,29 @@ proto.update = function(options) {
259262
this.color = getTraceColor(options, {});
260263
};
261264

265+
// We'd ideally know that all values are of fast types; sampling gives no certainty but faster
266+
// (for the future, typed arrays can guarantee it, and Date values can be done with
267+
// representing the epoch milliseconds in a typed array;
268+
// also, perhaps the Python / R interfaces take care of String->Date conversions
269+
// such that there's no need to check for string dates in plotly.js)
270+
// Patterned from axis_defaults.js:moreDates
271+
// Code DRYing is not done to preserve the most direct compilation possible for speed;
272+
// also, there are quite a few differences
273+
function allFastTypesLikely(a) {
274+
var len = a.length,
275+
inc = Math.max(0, (len - 1) / Math.min(Math.max(len, 1), 1000)),
276+
ai;
277+
278+
for(var i = 0; i < len; i += inc) {
279+
ai = a[Math.floor(i)];
280+
if(!isNumeric(ai) && !(ai instanceof Date)) {
281+
return false;
282+
}
283+
}
284+
285+
return true;
286+
}
287+
262288
proto.updateFast = function(options) {
263289
var x = this.xData = this.pickXData = options.x;
264290
var y = this.yData = this.pickYData = options.y;
@@ -272,24 +298,34 @@ proto.updateFast = function(options) {
272298

273299
var xx, yy;
274300

301+
var fastType = allFastTypesLikely(x);
302+
var isDateTime = !fastType && autoType(x) === 'date';
303+
275304
// TODO add 'very fast' mode that bypasses this loop
276305
// TODO bypass this on modebar +/- zoom
277-
for(var i = 0; i < len; ++i) {
278-
xx = x[i];
279-
yy = y[i];
306+
if(fastType || isDateTime) {
280307

281-
// check for isNaN is faster but doesn't skip over nulls
282-
if(!isNumeric(xx) || !isNumeric(yy)) continue;
308+
for(var i = 0; i < len; ++i) {
309+
xx = x[i];
310+
yy = y[i];
283311

284-
idToIndex[pId++] = i;
312+
if(isNumeric(yy)) {
285313

286-
positions[ptr++] = xx;
287-
positions[ptr++] = yy;
314+
if(!fastType) {
315+
xx = Lib.dateTime2ms(xx);
316+
}
317+
318+
idToIndex[pId++] = i;
288319

289-
bounds[0] = Math.min(bounds[0], xx);
290-
bounds[1] = Math.min(bounds[1], yy);
291-
bounds[2] = Math.max(bounds[2], xx);
292-
bounds[3] = Math.max(bounds[3], yy);
320+
positions[ptr++] = xx;
321+
positions[ptr++] = yy;
322+
323+
bounds[0] = Math.min(bounds[0], xx);
324+
bounds[1] = Math.min(bounds[1], yy);
325+
bounds[2] = Math.max(bounds[2], xx);
326+
bounds[3] = Math.max(bounds[3], yy);
327+
}
328+
}
293329
}
294330

295331
positions = truncate(positions, ptr);

test/image/baselines/dendrogram.png

106 KB
Loading

test/image/baselines/gl2d_10.png

63 Bytes
Loading

test/image/baselines/gl2d_12.png

37 Bytes
Loading

test/image/baselines/gl2d_14.png

-5 Bytes
Loading

test/image/baselines/gl2d_17.png

-12 Bytes
Loading
60 Bytes
Loading

0 commit comments

Comments
 (0)