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

Contour legend #2891

Merged
merged 9 commits into from
Aug 15, 2018
Merged

Contour legend #2891

merged 9 commits into from
Aug 15, 2018

Conversation

alexcjohnson
Copy link
Collaborator

Addresses most of #2880, all but the question about colorscales avoiding the legend.

  • Any contour (or contourcarpet) trace can now appear in the legend
  • Fills or lines with colorscales get a matching gradient in the legend
  • Drawing.gradient is extended to support arbitrary stops, as used by our built-in and custom colorscales. (Side note: we could use this to simplify continuous colorbar drawing, ie instead of making lots of little constant-color rectangles just make one rectangle with the colorscale applied as a gradient. I did not do that in this PR. But doing so would probably make it easier to finally close colorbar draws outside the bounds #970)
  • Two more bugs showed up while I was working on this, and I fixed them both here:
    • It was not possible to make two contour traces both with heatmap coloring. I moved heatmap coloring into the contour group, rather than at the root of the contour layer, to solve this.
    • Hiding and reshowing a contour trace (which is now easy with them all available in the legend) would result in the wrong ordering. Particularly problematic if you have one trace with colored fills and various others in front of it. Fixed this (for contour and contourcarpet) by, surprise surprise, moving to more standard d3 enter/exit/each(order) logic.
  • Moved the legend symbols for traces with fills up a bit - centered if fill-only, and slightly below center if fill-and-line, but no change if there are also markers or text.

cc @etpinard

@alexcjohnson alexcjohnson added bug something broken feature something new status: reviewable labels Aug 9, 2018
@alexcjohnson alexcjohnson added this to the v1.40.0 milestone Aug 9, 2018
Copy link
Contributor

@etpinard etpinard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great PR 💪

I misread parts of #2880, where I thought the individual contour levels would optionally get corresponding legend items too. Was this ever discussed?

Thanks for fixing those heatmap/contour ordering bugs that I probably encountered before in #2574, but didn't bother fixing. My bad.

I made a few comments. I found one potential red flag: the additional showlegend: false in colorscale_opacity,json and contour_scatter.json.

var markersOrText = subTypes.hasMarkers(trace) || subTypes.hasText(trace);
var anyFill = showFill || showGradientFill;
var anyLine = showLine || showGradientLine;
var pathStart = (markersOrText || !anyFill) ? 'M5,0' :
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice touch!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

peek 2018-08-10 14-46

@@ -28,32 +27,35 @@ var constants = require('./constants');
var costConstants = constants.LABELOPTIMIZER;

exports.plot = function plot(gd, plotinfo, cdcontours, contourLayer) {
var uidLookup = getUidsFromCalcData(cdcontours);
var contours = contourLayer.selectAll('g.contour')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yeah. Way better.

By the looks of it, heatmap and carpet probably suffer from similar bugs:

image

From which we could 🔪 getUidsFromCalcdata entirely:

image

No need to do this in this PR of course, but opening a new issue about it would be nice.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call -> #2907

@@ -439,21 +441,21 @@ describe('contour plotting and editing', function() {
.then(function() {
_assert({
hmIndex: 0,
contoursIndex: 1
contoursIndex: 3
Copy link
Contributor

@etpinard etpinard Aug 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh ok, that's tricky. Now that <.hm> is inside <g.contour>, this test is a little tricky to interpret.

Maybe we could instead assert:

Array.prototype.slice.call(contourPlot.children).map(n => n.classList[0])
// to check ordering

Array.prototype.slice.call(contourPlot.children).map(n => n.children.length)
// to check the number of children

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is really about layer ordering, which is a consistently testable feature in SVG and likely to be useful elsewhere in our tests, I added a generic custom assertion for this. See what you think e25b9ff

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See what you think e25b9ff

💯

@@ -501,4 +503,34 @@ describe('contour plotting and editing', function() {
.catch(fail)
.then(done);
});

it('keeps the correct ordering after hide and show', function(done) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice test. Thanks!

expect(getIndices()).toEqual([0, 1]);
})
.catch(fail)
.then(done);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh would you mind s/fail/failTest in this file?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

failTest in contour & carpet -> 7843d83

expect(getIndices()).toEqual([1, 2]);
})
.catch(fail)
.then(done);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one more s/fail/failTest - we must be getting pretty close 🤞

function lineGradient(s) {
if(s.size()) {
var gradientID = 'legendline-' + trace.uid;
Drawing.lineGroupStyle(s);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should double-check that this works ok with line.dash and other line stylings.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, added to a mock in 73f279b

@@ -27,6 +27,10 @@ module.exports = function handleStyleDefaults(traceIn, traceOut, coerce, layout,
}

if(coloring !== 'none') {
// plots/plots always coerces showlegend to true, but in this case
// we default to false and (by default) show a colorbar instead
if(traceIn.showlegend !== true) traceOut.showlegend = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah nice ♻️ . This gets used in

image

@@ -0,0 +1,54 @@
{
"data":[{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice mock! Could we lock down the contourcarpet legend behavior in a mock as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... and for histogram2dcontour.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, histogram2dcontour didn't get this functionality before -> added and tested in 73f279b

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and contourcarpet colored contours in 74e7f84

@etpinard
Copy link
Contributor

and referencing #2642 where work in this PR could somewhat easily be extended to heatmap, histogram2d and surface traces.

@@ -9,16 +9,6 @@

'use strict';

exports.legendGetsTrace = function legendGetsTrace(trace) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was used in getLegendData and in legendDefaults, but even before one of them overrode half the logic, and now that logic has diverged further, so it didn't make sense to pull it out.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice 🔪 job here

coerce('showlegend');
coerce('legendgroup');
}
else {
traceOut._dfltShowLegend = false;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#749 🙄

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record: I added _dfltShowLegend because there's otherwise no robust way to tell from just traceIn and traceOut what the default is... so there would be some situations where we would NOT show a legend (eg scatter + colored contour) but then setting showlegend: false explicitly in the trace that already defaults to showlegend: false would make the legend appear 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, that's what I expected. I don't think there's a nicer way to do this than what you coded in this commit 👌

'a) Two or more traces would by default be shown in the legend.',
'b) One pie trace is shown in the legend.',
'c) One trace is explicitly given with `showlegend: true`.'
].join(' ')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for 📚

@etpinard
Copy link
Contributor

Thanks for restoring backward-compatibility in 1d05081

All my blocking comments have been addressed, so 💃

We should still open an issue about (potential) heatmap and carpet layer ordering bugs as mentioned in #2891 (comment)

@alexcjohnson
Copy link
Collaborator Author

I misread parts of #2880, where I thought the individual contour levels would optionally get corresponding legend items too. Was this ever discussed?

Ah no, that's not what we're after here. Interesting though, kind of an alternative a colorbar, I guess? Related to #1747 and #1785

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug something broken feature something new
Projects
None yet
Development

Successfully merging this pull request may close these issues.

colorbar draws outside the bounds
2 participants