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

Multiple y axes -> only one scatter shows up #3074

Closed
jason-curtis opened this issue Oct 4, 2018 · 12 comments
Closed

Multiple y axes -> only one scatter shows up #3074

jason-curtis opened this issue Oct 4, 2018 · 12 comments

Comments

@jason-curtis
Copy link

jason-curtis commented Oct 4, 2018

Issue

When plotting data on multiple Y axes, particularly when nothing is plotted on the primary Y axis, sometimes plotly will only show one series.

Repro

https://codepen.io/jasoncurtis/pen/zmqNMQ?editors=0010

Expected behavior

Two series are plotted.

Actual behavior

Two series show up in the legend, but only one series is plotted.

Workaround

If you change 'y2' in the repro code above to 'y1', both series will show up. However, it's not always reasonable to assume there will be data on y1 - I am trying to write a purpose-specific API that uses plotly in such a way that I cannot guarantee there will be something on y1 without significant extra complexity.

Related:

@etpinard
Copy link
Contributor

etpinard commented Oct 4, 2018

Here's a working version: https://codepen.io/etpinard/pen/LgNaZa?editors=0010

where I deleted yaxis2.overlaying and made yaxis3.overlaying: 'y2'.


Explanations:

we don't allow setting ovelaying value corresponding to

  • axes that themselves have an overlaying key set
  • axes that won't be drawn

The logic is the following:

function getOverlayableAxes(axLetter, axName) {
var list = (axLetter === 'x') ? xNames : yNames;
var out = [];
for(var j = 0; j < list.length; j++) {
var axName2 = list[j];
if(axName2 !== axName && !(layoutIn[axName2] || {}).overlaying) {
out.push(name2id(axName2));
}
}
return out;
}

Also note, we don't draw cartesian axes that have no traces and no layout component (i.e. no annotations/shapes/images) attached to them, except for empty Plotly.newPlot(gd, []) graphs.

I hope this helps.

@jason-curtis
Copy link
Author

Thanks for the response and explanation!

The part about disallowed overlaying values partially explains what I'm seeing - but if what you say is true, then why would the third Y axis display at all? I would expect that 'overlaying': 'y' would be equivalent to 'overlaying': 'y1' , which would mean that y axes 2 and 3 should behave the same (either showing up or not). In fact, if I set 'overlaying': 'y1' I still get the same behavior.

That said, despite having read the docs I admittedly do not understand why the overlaying keyword is necessary at all. I just seem to have to mess with it in order to get my multiple axes to show up. What does it even mean to "overlay"? Is there an alternative? Maybe a more in-depth example is in order? This one got me started, but as you can tell I am (and my colleagues are) still pretty much in the dark.

Thanks again for your help.

@etpinard
Copy link
Contributor

etpinard commented Oct 5, 2018

but if what you say is true, then why would the third Y axis display at all?

The "third" meaning yaxis3? Because the second trace has yaxis: 'y3'.

I would expect that 'overlaying': 'y' would be equivalent to 'overlaying': 'y1' , which would mean that y axes 2 and 3 should behave the same (either showing up or not). In fact, if I set 'overlaying': 'y1' I still get the same behavior.

I'm only a little lost here. overlaying: 'y' should be equivalent to overlaying: 'y1'. y' and 'y1'both link tolayout.yaxis`. Could you share a codepen of the scenario you're seeing?

If you don't see overlaying then the "top" subplot with hide the "bottom" subplot.

@jason-curtis
Copy link
Author

jason-curtis commented Oct 5, 2018

I'm only a little lost here. overlaying: 'y' should be equivalent to overlaying: 'y1'

OK, great, we're on the same page here

Could you share a codepen of the scenario you're seeing?

Given the above, the original codepen shows the scenario. Since both yaxis2 and yaxis3 have overlaying: 'y', I would expect them to act the same (either be both displayed or neither). Instead, it appears that yaxis3 is displayed while yaxis2 is not.

Based on your earlier comment ("we don't allow setting ovelaying value corresponding to..."), it may be that my inputs are invalid and leading to undefined behavior, in which case there might be a validation solution which would provide a helpful error message in this case.

Or maybe the user is required to provide a chain of overlaying where yaxis2 overlays y1, yaxis3 overlays y2, etc?

"If you don't set overlaying then the "top" subplot with hide the "bottom" subplot."

What would a use case be where that is desired? It feels like an antifeature to me but I'm probably missing something that the designers had in mind. It seems like it would be much more straightforward to always "overlay" and rely on visible: false to hide things.

To get back to my original use case, I am hoping to do something dynamic where there may or may not be anything on yaxis1. In the working example you provided, anything on yaxis1 will be hidden. Is there a straightforward way to ensure that all axes are shown?

@etpinard
Copy link
Contributor

etpinard commented Oct 5, 2018

What would a use case be where that is desired?

https://plot.ly/javascript/insets/

@etpinard
Copy link
Contributor

etpinard commented Oct 5, 2018

Since both yaxis2 and yaxis3 have overlaying: 'y',

We don't allow setting overlaying value corresponding to axes that themselves have an overlaying key set.

@alexcjohnson
Copy link
Collaborator

If you want to ensure yaxis is always drawn, put a dummy invisible trace on it, like {visible: false} (which will implicitly be drawn on xaxis and yaxis). If you don't want to see yaxis, just have it there to be overlaid on, you can make it too visible: false https://codepen.io/alexcjohnson/pen/oazbvv?editors=0010

@jason-curtis
Copy link
Author

@alexcjohnson gotcha, I will do that.

@etpinard thanks for the insets example. That makes sense;

We don't allow setting overlaying value corresponding to axes that themselves have an overlaying key set.

I beg to differ - you do allow it. I've been doing it and the resulting undefined behavior is one of the main causes of my confusion! Would it be feasible to add a validation error?

You've both explained a lot to me and now overlaying makes more sense to me. Is this all documented somewhere? I'm not familiar with your docs structure but I'll take a crack at a small suggestion.

jason-curtis pushed a commit to jason-curtis/plotly.js that referenced this issue Oct 5, 2018
@etpinard
Copy link
Contributor

etpinard commented Oct 5, 2018

I beg to differ - you do allow it.

I guess that depends what you mean by allowing it. You're certainly allowed to set things that way, and plotly.js won't error out (it never does on "attribute" errors). In this case, plotly.js simply ignores that invalid overlaying key.

That said, Plotly.validate should log something, which appears to be the case. Trying it out with you original data / layout, I got:

image

@jason-curtis
Copy link
Author

plotly.js won't error out (it never does on "attribute" errors).

Ahhh, OK, I expected a more detailed level of validation because I use plotly.py, which does this kind of validation. ccing @jonmmease to maybe take this issue back across to plotly/plotly.py#1200. would it be reasonable to add validation in plotly.py when invalid value is provided for overlaying? @etpinard has explained the validity rules above.

@etpinard
Copy link
Contributor

etpinard commented Oct 9, 2018

Ok. Looks like this issue won't result in a PR in this PR. Closing.

Thanks for posting and thanks for the documentation PR @thatneat !

@etpinard etpinard closed this as completed Oct 9, 2018
@Tunneller
Copy link

This discussion was incredibly useful to help me debug why I was not getting curves on my plots. You mean that 'overlapping: "y"' is not short-hand for 'overlapping: "yes"'..... I spent 24 sleep deprived hours on this. Now that I've got it all working, everything makes sense. And that solution was to simply insert {visible: false}. Wow. So neat. Er... is this in the documentation yet?

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

No branches or pull requests

4 participants