-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Contour bg fix #1280
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
Contour bg fix #1280
Changes from all commits
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 |
---|---|---|
|
@@ -44,13 +44,15 @@ module.exports = extendFlat({}, { | |
}, | ||
ncontours: { | ||
valType: 'integer', | ||
dflt: 0, | ||
dflt: 15, | ||
min: 1, | ||
role: 'style', | ||
description: [ | ||
'Sets the maximum number of contour levels. The actual number', | ||
'of contours will be chosen automatically to be less than or', | ||
'equal to the value of `ncontours`.', | ||
'Has an effect only if `autocontour` is *true*.' | ||
'Has an effect only if `autocontour` is *true* or if', | ||
'`contours.size` is missing.' | ||
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. So if you specify Note that the converse is not allowed: you can't specify 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.
I can't think of one. Nice addition 👍
So, autocontour: true,
contours: {
size: 10
} ignores autocontour: false,
contours: {
size: 10
} pick 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. Hmm, I was starting to think
I don't think there's anything backward-incompatible in this proposal, except in partial information cases, where we had a bunch of bugs anyway. 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. deferred to #1282 |
||
].join(' ') | ||
}, | ||
|
||
|
@@ -59,19 +61,29 @@ module.exports = extendFlat({}, { | |
valType: 'number', | ||
dflt: null, | ||
role: 'style', | ||
description: 'Sets the starting contour level value.' | ||
description: [ | ||
'Sets the starting contour level value.', | ||
'Must be less than `contours.end`' | ||
].join(' ') | ||
}, | ||
end: { | ||
valType: 'number', | ||
dflt: null, | ||
role: 'style', | ||
description: 'Sets the end contour level value.' | ||
description: [ | ||
'Sets the end contour level value.', | ||
'Must be more than `contours.start`' | ||
].join(' ') | ||
}, | ||
size: { | ||
valType: 'number', | ||
dflt: null, | ||
min: 0, | ||
role: 'style', | ||
description: 'Sets the step between each contour level.' | ||
description: [ | ||
'Sets the step between each contour level.', | ||
'Must be positive.' | ||
].join(' ') | ||
}, | ||
coloring: { | ||
valType: 'enumerated', | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ | |
'use strict'; | ||
|
||
var Axes = require('../../plots/cartesian/axes'); | ||
var extendFlat = require('../../lib').extendFlat; | ||
var heatmapCalc = require('../heatmap/calc'); | ||
|
||
|
||
|
@@ -22,30 +23,72 @@ module.exports = function calc(gd, trace) { | |
|
||
// check if we need to auto-choose contour levels | ||
if(trace.autocontour !== false) { | ||
var dummyAx = { | ||
type: 'linear', | ||
range: [trace.zmin, trace.zmax] | ||
}; | ||
var dummyAx = autoContours(trace.zmin, trace.zmax, trace.ncontours); | ||
|
||
Axes.autoTicks( | ||
dummyAx, | ||
(trace.zmax - trace.zmin) / (trace.ncontours || 15) | ||
); | ||
contours.size = dummyAx.dtick; | ||
|
||
contours.start = Axes.tickFirst(dummyAx); | ||
contours.size = dummyAx.dtick; | ||
dummyAx.range.reverse(); | ||
contours.end = Axes.tickFirst(dummyAx); | ||
|
||
if(contours.start === trace.zmin) contours.start += contours.size; | ||
if(contours.end === trace.zmax) contours.end -= contours.size; | ||
|
||
// so rounding errors don't cause us to miss the last contour | ||
contours.end += contours.size / 100; | ||
// if you set a small ncontours, *and* the ends are exactly on zmin/zmax | ||
// there's an edge case where start > end now. Make sure there's at least | ||
// one meaningful contour, put it midway between the crossed values | ||
if(contours.start > contours.end) { | ||
contours.start = contours.end = (contours.start + contours.end) / 2; | ||
} | ||
|
||
// copy auto-contour info back to the source data. | ||
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. this is actually already dealt with in 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. nice catch 👍 |
||
trace._input.contours = contours; | ||
trace._input.contours = extendFlat({}, contours); | ||
} | ||
else { | ||
// sanity checks on manually-supplied start/end/size | ||
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. looks good 👍 |
||
var start = contours.start, | ||
end = contours.end, | ||
inputContours = trace._input.contours; | ||
|
||
if(start > end) { | ||
contours.start = inputContours.start = end; | ||
end = contours.end = inputContours.end = start; | ||
start = contours.start; | ||
} | ||
|
||
if(!(contours.size > 0)) { | ||
var sizeOut; | ||
if(start === end) sizeOut = 1; | ||
else sizeOut = autoContours(start, end, trace.ncontours).dtick; | ||
|
||
inputContours.size = contours.size = sizeOut; | ||
} | ||
} | ||
|
||
return cd; | ||
}; | ||
|
||
/* | ||
* autoContours: make a dummy axis object with dtick we can use | ||
* as contours.size, and if needed we can use Axes.tickFirst | ||
* with this axis object to calculate the start and end too | ||
* | ||
* start: the value to start the contours at | ||
* end: the value to end at (must be > start) | ||
* ncontours: max number of contours to make, like roughDTick | ||
* | ||
* returns: an axis object | ||
*/ | ||
function autoContours(start, end, ncontours) { | ||
var dummyAx = { | ||
type: 'linear', | ||
range: [start, end] | ||
}; | ||
|
||
Axes.autoTicks( | ||
dummyAx, | ||
(end - start) / (ncontours || 15) | ||
); | ||
|
||
return dummyAx; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,10 +33,19 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout | |
|
||
var contourStart = Lib.coerce2(traceIn, traceOut, attributes, 'contours.start'), | ||
contourEnd = Lib.coerce2(traceIn, traceOut, attributes, 'contours.end'), | ||
autocontour = coerce('autocontour', !(contourStart && contourEnd)); | ||
missingEnd = (contourStart === false) || (contourEnd === false), | ||
|
||
if(autocontour) coerce('ncontours'); | ||
else coerce('contours.size'); | ||
// normally we only need size if autocontour is off. But contour.calc | ||
// pushes its calculated contour size back to the input trace, so for | ||
// things like restyle that can call supplyDefaults without calc | ||
// after the initial draw, we can just reuse the previous calculation | ||
contourSize = coerce('contours.size'), | ||
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. This line - always coercing 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. 👍 |
||
autoContour; | ||
|
||
if(missingEnd) autoContour = traceOut.autocontour = true; | ||
else autoContour = coerce('autocontour', false); | ||
|
||
if(autoContour || !contourSize) coerce('ncontours'); | ||
|
||
handleStyleDefaults(traceIn, traceOut, coerce, layout); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -80,8 +80,9 @@ function plotOne(gd, plotinfo, cd) { | |
} | ||
|
||
function emptyPathinfo(contours, plotinfo, cd0) { | ||
var cs = contours.size || 1, | ||
var cs = contours.size, | ||
pathinfo = []; | ||
|
||
for(var ci = contours.start; ci < contours.end + cs / 10; ci += cs) { | ||
pathinfo.push({ | ||
level: ci, | ||
|
@@ -103,6 +104,11 @@ function emptyPathinfo(contours, plotinfo, cd0) { | |
z: cd0.z, | ||
smoothing: cd0.trace.line.smoothing | ||
}); | ||
|
||
if(pathinfo.length > 1000) { | ||
Lib.warn('Too many contours, clipping at 1000', contours); | ||
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. somewhat arbitrary... but consistent with what we do for cartesian ticks - here I included the warning as the consequences (in terms of super slow perf) are likely much more severe and you will want to see the |
||
break; | ||
} | ||
} | ||
return pathinfo; | ||
} | ||
|
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.
@etpinard I included this change bcs contours uses coerce2 on some numeric values that can be 0. This still seems a little weird, ie you have to know to check for exactly
false
, and iffalse
is an allowed value it still won't be telling you what you think it is. But this fixes it for the exact case I was worried about here.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.
Nice.
I've been wanting to merge
coerce2
withvalidate
for a while now.Good enough for now 👍