-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Autosize / autorange fixes #2437
Changes from 1 commit
85f0442
9f774c0
d9521e8
04806a2
0ecaaaf
9913afe
f262dc9
3875fcc
8cf8d51
cf48426
247c626
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -18,7 +18,6 @@ module.exports = { | |||
getAutoRange: getAutoRange, | ||||
makePadFn: makePadFn, | ||||
doAutoRange: doAutoRange, | ||||
needsAutorange: needsAutorange, | ||||
expand: expand | ||||
}; | ||||
|
||||
|
@@ -229,24 +228,48 @@ function expand(ax, data, options) { | |||
var len = data.length; | ||||
var extrapad = options.padded || false; | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct me if I'm wrong, but this used to be the only place in plotly.js/src/plots/cartesian/axes.js Line 455 in 8731cb5
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Exactly - taking that out, and instead holding on to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great! That Now, would mind mentioning in the jsDoc above that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fuller docs -> 9913afe |
||||
var tozero = options.tozero && (ax.type === 'linear' || ax.type === '-'); | ||||
var isLog = (ax.type === 'log'); | ||||
|
||||
var i, j, k, v, di, dmin, dmax, ppadiplus, ppadiminus, includeThis, vmin, vmax; | ||||
|
||||
var hasArrayOption = false; | ||||
|
||||
function makePadAccessor(item) { | ||||
if(Array.isArray(item)) { | ||||
hasArrayOption = true; | ||||
return function(i) { return Math.max(Number(item[i]||0), 0); }; | ||||
} | ||||
else { | ||||
var v = Math.max(Number(item||0), 0); | ||||
return function() { return v; }; | ||||
} | ||||
} | ||||
|
||||
var ppadplus = makePadAccessor((ax._m > 0 ? | ||||
options.ppadplus : options.ppadminus) || options.ppad || 0), | ||||
ppadminus = makePadAccessor((ax._m > 0 ? | ||||
options.ppadminus : options.ppadplus) || options.ppad || 0), | ||||
vpadplus = makePadAccessor(options.vpadplus || options.vpad), | ||||
vpadminus = makePadAccessor(options.vpadminus || options.vpad); | ||||
options.ppadplus : options.ppadminus) || options.ppad || 0); | ||||
var ppadminus = makePadAccessor((ax._m > 0 ? | ||||
options.ppadminus : options.ppadplus) || options.ppad || 0); | ||||
var vpadplus = makePadAccessor(options.vpadplus || options.vpad); | ||||
var vpadminus = makePadAccessor(options.vpadminus || options.vpad); | ||||
|
||||
if(!hasArrayOption) { | ||||
// with no arrays other than `data` we don't need to consider | ||||
// every point, only the extreme data points | ||||
vmin = Infinity; | ||||
vmax = -Infinity; | ||||
|
||||
for(i = 0; i < data.length; i++) { | ||||
v = data[i]; | ||||
if(Math.abs(v) < FP_SAFE) { | ||||
// data is not linearized yet so we still have to filter out negative logs | ||||
if(v < vmin && (!isLog || v > 0)) vmin = v; | ||||
if(v > vmax) vmax = v; | ||||
} | ||||
} | ||||
|
||||
data = [vmin, vmax]; | ||||
len = 2; | ||||
} | ||||
|
||||
function addItem(i) { | ||||
di = data[i]; | ||||
|
@@ -259,7 +282,7 @@ function expand(ax, data, options) { | |||
// more than an order of mag, clip it to one order. This is so | ||||
// we don't have non-positive errors or absurdly large lower | ||||
// range due to rounding errors | ||||
if(ax.type === 'log' && vmin < vmax / 10) vmin = vmax / 10; | ||||
if(isLog && vmin < vmax / 10) vmin = vmax / 10; | ||||
|
||||
dmin = ax.c2l(vmin); | ||||
dmax = ax.c2l(vmax); | ||||
|
@@ -269,15 +292,6 @@ function expand(ax, data, options) { | |||
dmax = Math.max(0, dmax); | ||||
} | ||||
|
||||
// In order to stop overflow errors, don't consider points | ||||
// too close to the limits of js floating point | ||||
function goodNumber(v) { | ||||
return isNumeric(v) && Math.abs(v) < FP_SAFE; | ||||
} | ||||
|
||||
function lessOrEqual(v0, v1) { return v0 <= v1; } | ||||
function greaterOrEqual(v0, v1) { return v0 >= v1; } | ||||
|
||||
for(k = 0; k < 2; k++) { | ||||
var newVal = k ? dmax : dmin; | ||||
if(goodNumber(newVal)) { | ||||
|
@@ -329,3 +343,12 @@ function expand(ax, data, options) { | |||
for(i = 0; i < 6; i++) addItem(i); | ||||
for(i = len - 1; i > 5; i--) addItem(i); | ||||
} | ||||
|
||||
// In order to stop overflow errors, don't consider points | ||||
// too close to the limits of js floating point | ||||
function goodNumber(v) { | ||||
return isNumeric(v) && Math.abs(v) < FP_SAFE; | ||||
} | ||||
|
||||
function lessOrEqual(v0, v1) { return v0 <= v1; } | ||||
function greaterOrEqual(v0, v1) { return v0 >= v1; } |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,7 +20,6 @@ var arrayRange = require('array-range'); | |
var Registry = require('../../registry'); | ||
var Lib = require('../../lib'); | ||
var AxisIDs = require('../../plots/cartesian/axis_ids'); | ||
var needsAutorange = require('../../plots/cartesian/autorange').needsAutorange; | ||
var Drawing = require('../../components/drawing'); | ||
var formatColor = require('../../lib/gl_format_color'); | ||
|
||
|
@@ -104,14 +103,10 @@ function calc(gd, trace) { | |
// and an average size for array marker.size inputs. | ||
if(count < TOO_MANY_POINTS) { | ||
ppad = calcMarkerSize(trace, count); | ||
calcAxisExpansion(gd, trace, xa, ya, x, y, ppad); | ||
} else { | ||
if(markerOptions) { | ||
ppad = 2 * (markerOptions.sizeAvg || Math.max(markerOptions.size, 3)); | ||
} | ||
fastAxisExpand(xa, x, ppad); | ||
fastAxisExpand(ya, y, ppad); | ||
} else if(markerOptions) { | ||
ppad = 2 * (markerOptions.sizeAvg || Math.max(markerOptions.size, 3)); | ||
} | ||
calcAxisExpansion(gd, trace, xa, ya, x, y, ppad); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very clean. This is great! To note though, this new combined pathway is little slower. Previously at 1e6 pts, The failing tests are in this new suite that got put in during #2404. Should be an easy fix. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Huh, let's unpack that performance issue. Previously the inner loop was: for(var i = 0; i < vals.length; i += 2) {
var v = vals[i];
if(v < b0) b0 = v;
if(v > b1) b1 = v;
} this afternoon it was: for(i = 0; i < data.length; i++) {
v = data[i];
if(Math.abs(v) < FP_SAFE) {
// data is not linearized yet so we still have to filter out negative logs
if(v < vmin && (!isLog || v > 0)) vmin = v;
if(v > vmax) vmax = v;
}
} The old code was accidentally omitting half the points ( Anyway I noticed I could optimize it a bit by making two versions of the loop, one for log and one for other types. Seems worth a couple of extra lines since this gets so much traffic -> 247c626 Updated the failing test in cf48426 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great! You're latest patch in 247c626 got |
||
|
||
// set flags to create scene renderers | ||
if(options.fill && !scene.fill2d) scene.fill2d = true; | ||
|
@@ -141,26 +136,6 @@ function calc(gd, trace) { | |
return [{x: false, y: false, t: stash, trace: trace}]; | ||
} | ||
|
||
// Approximate Axes.expand results with speed | ||
function fastAxisExpand(ax, vals, ppad) { | ||
if(!needsAutorange(ax) || !vals) return; | ||
|
||
var b0 = Infinity; | ||
var b1 = -Infinity; | ||
|
||
for(var i = 0; i < vals.length; i += 2) { | ||
var v = vals[i]; | ||
if(v < b0) b0 = v; | ||
if(v > b1) b1 = v; | ||
} | ||
|
||
if(ax._min) ax._min = []; | ||
ax._min.push({val: b0, pad: ppad}); | ||
|
||
if(ax._max) ax._max = []; | ||
ax._max.push({val: b1, pad: ppad}); | ||
} | ||
|
||
// create scene options | ||
function sceneOptions(gd, subplot, trace, positions) { | ||
var fullLayout = gd._fullLayout; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I initially pulled this module out of
axes.js
to avoid circular references; then I ended up movingclearCalc
intosetConvert
instead of here, which mooted the circular reference problem, but I still like having these separate from the behemothaxes.js
.