Skip to content

Data-referenced annotations on 3D graphs #751

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

Closed
rudresh-ajgaonkar opened this issue Jul 19, 2016 · 9 comments · Fixed by #1638
Closed

Data-referenced annotations on 3D graphs #751

rudresh-ajgaonkar opened this issue Jul 19, 2016 · 9 comments · Fixed by #1638
Assignees
Labels
feature something new

Comments

@rudresh-ajgaonkar
Copy link

Hey, Is it possible to add labels displaying names(Only Name) of the traces without hover over the data point ?
Also when i hover on the chart, it should show the regular hover text like for example, in case of a 3d scatter plot, on hover it can show x, y , z data and without hover it should show just the trace name. Is this feature implemented ? type:feature

@rudresh-ajgaonkar
Copy link
Author

I have read about Text Annotations but i was trying to see them if they are applicable to 3D scatter plots too.

@etpinard
Copy link
Contributor

Annotations aren't available in 3D graphs yet. I believe you are the first person to ask for that feature, so I'll change the issue title accordingly.

In the meantime, here's how to make a 3D text chart using the scatter3d 'text' mode: http://codepen.io/etpinard/pen/rLJRdN

@etpinard etpinard added the feature something new label Jul 19, 2016
@etpinard etpinard changed the title Adding labels to data points without Hover Data-referenced annotations on 3D graphs Jul 19, 2016
@rudresh-ajgaonkar
Copy link
Author

rudresh-ajgaonkar commented Jul 19, 2016

For Now I have used mode : 'marker + text' and the following is the output.
newplot 5

Only query here is that why does that text appear about legends ? Aa, currently i have kept it hidden by using .pointtext{
display: none;
}

@etpinard
Copy link
Contributor

etpinard commented Jul 19, 2016

Unfortunately there's no way to control the apperence of the legend items at the moment.

I'd suggest making two set of scatter3d traces one with mode: 'markers' (that will appear in the legend) and one with mode: 'text' with showlegend: false (that won't appear in the legend).

@etpinard
Copy link
Contributor

etpinard commented Jan 18, 2017

We should clear up a few things about 3D annotations before implementing them. We'd love any feedback from users watching this issue and of course from @monfera @alexcjohnson @rreusser @cldougl @chriddyp

Appearance

  • Should 3D annotations look like permanent hover labels? That is, their text (or arrow tail) coordinates would be an (x,y) pair and their arrow tip coordinates would be a (x,y,z) on a given 3D subplot (aka scene).

  • Or, should 3D annotations look like { type: 'scatter3d', mode: 'text' } traces? That is, both their arrow tip and tails position would be determined by a (x,y,z) triplet on a given 3D subplot.

  • Or maybe both? In this case, which one should we implement first?

API

Unfortunately, plotly.js annotations very much assume an x/y coordinate system at the moment. Attributes x, y, xref, yref, ax, ay, axref, ayref, xanchor, yanchor, xclick and yclick wouldn't extend well to 3D (and to any other subplot type for that matter).

Case 1

If we choose the permanent hover label appearance, adding z... attribute to layout.annotations items wouldn't be that bad. For example,

annotation = {
  xref: 'scene',  // or more verbosely 'scene.x'
  yref: 'scene',  // or 'scene.y' (but yref: 'paper' would *not* be allowed)
  // no need for zref

  // or maybe
  // sceneref: 'scene'

  // or more generally 
  // subplotref: 'scene'

  x: 1,
  y: 2,
  z: 3, // the only 'new' attribute
  
  axref: 'paper',  // other values would *not* be allowed
  ayref: 'paper',  //  " " "

  // tail/text coordinates in paper as for xy annotations
  ax: 0,
  ay: 1,
  xanchor: 'right',
  yanchor: 'bottom'
}

Case 2

But, for the { type: 'scatter3d', mode: 'text' } appearance, we would have:

annotation = {
  subplotref: 'scene',

  x: 1,
  y: 2,
  z: 3,
  
  // axref and ayref would be *not* be allowed  

  ax: 0,
  ay: 1,
  az: 0,

  // here 'right' / 'left' & 'bottom' / 'top'
  // wouldn't make sense if a scene is rotated 
  //
  // maybe 'positive' / 'negative' as in 
  // 'towards positive/negatives numbers on that axis'
  // is better.
  xanchor: 'pos',
  yanchor: 'neg',
  zanchor: 'pos'
}

where several attributes would not be allowed and the (x|y)anchor values would have to be hijacked.

Case 3

Alternatively, as { type: 'scatter3d', mode: 'text' } annotations could only live on one scene and have no relation the the paper outside the scene, we could place the annotations array container in a layout.scene object:

layout = {
  scene: {
    annotations: [{
      x: 1, y: 2, z: 3,
      ax: 1.5, ay: 2.4, az: 3.5,
      // ...
    }]
   },
  annotations: [ /* other paper-ref annotations if desired */ ]
}

which would result in a much cleaner API for 3D annotations (where no attribute would not be allowed etc.), but some users may not like the fact that a graph's annotations would end up in multiple array container.

Case 4

Or something more future-proof (when we decide to add data-referenced annotation to geo, mapbox, ternary subplots), where we generalize the way coordinate are input in layout.annotations:

annotation = {
  tip: {
    ref: '' | 'x' | 'y' | 'xy' | 'x2y2' | 'scene' | 'geo' | 'ternary'
  
    // where e.g. 'x' -> means { xref: 'x', yref: 'paper' }
    // and 'y' -> means { xref: 'paper', yref: 'y' }
    // and '' -> means { xref: 'paper', yref: 'paper' }

    coords: [/* */] ,  // coordinate pair or triplet of the tip
    anchors: [/* */] 
  },

  tail: {
    // similar to 'tip' but for the coordinates of the tail
  },

  // text + arrow styles
}

@etpinard
Copy link
Contributor

... oh and I should add (or maybe not), from a developer's perspective Case 3 would be by-far the easiest to implement and to extend to other subplot type e.g. layout.ternary.annotations: [/* */] could become a thing too down the road.

@phxnsharp
Copy link

As for whether it should be "permanent hover labels" vs rotating within the x,y,z space obviously in the long run the choice would be great. I was not able to elicit strong feelings from our stakeholders as to which is more important, or should be done first.

The API bothers me though, because it is so complex. Honestly I've spent a fair bit of time looking at the existing API docs and reading this issue and unless I am right in the moment I can never make sense of it. I question whether there perhaps is too much flexibility? Is there really a use case for having the x location tied to the paper, but the y location tied to the axis? Also, you seem to be implying that there is a third choice other than "paper" or "axis", and I'm afraid I'm not following that very well. Is "scene" just a shortcut for x0y0z0 for 3d plots?

@alexcjohnson
Copy link
Collaborator

Appearance

I'd focus on the "permanent hover labels" case. As you point out, we can already get close to the case where both tip and tail are data-referenced by using traces, so the case of absolute pixel arrow length will give us the most immediate benefit. It's also not entirely clear to me how we'd draw the arrow (ie where to cut it off next to the textbox) in the data-referenced case, particularly when it's pointing mostly into or out of the page. Or the arrowhead for that matter, if it's not supposed to be interpreted as parallel to the plane of the page, do we draw it with a 3D rotation (ie squished in one direction)? Do we draw it as a 3D shape, like a cone?

API

I actually think I prefer the structure of case 3 (a separate annotation array for each subplot), and I see the separation of types as an advantage within the philosophy "make impossible states impossible to define" - also this can help reduce the complexity @phxnsharp is rightly concerned by. When we think about all these subplot types, 2D cartesian axes are clearly the outlier in the way you can meaningfully mix and match coordinate references among different axes and the paper.

Take the 2D cartesian example of xref: 'x', yref: 'paper' - this is for the situation where you want to label a certain x value - for example an important event in time - and have that label always appear as long as that time is visible, irrespective of how you zoom the y axis. In certain other cases it might be plausible to have that on another subplot type, but that will be subplot-dependent in very specific ways - For example, label a particular meridian on a geo plot: This really only makes sense for projections with vertical meridians. For other subplot types I guess I can imagine scenarios you might want to label in a similar way, but the API and possibly the display logic will also need to be tailored to the particular subplot to be meaningful.

Re: case 4, future-proofing - some of that is moot if we go with case 3, but I think it would be worthwhile to take a look at cleaning up the API right now while we're making the first subplot extension. Would simple name changes (compatible with cleanLayout) like perhaps changing ax/axref to tailx/tailxref, make this easier to work with? I see the rationale for separate tip and tail containers, though I worry that it makes simple things harder, and doesn't fit with annotations that don't have an arrow.

@etpinard
Copy link
Contributor

etpinard commented Feb 3, 2017

Thanks very much @alexcjohnson I agree with all your points 🥇

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

Successfully merging a pull request may close this issue.

4 participants