Plotly.js: Data-referenced annotations on 3D graphs

Created on 19 Jul 2016  路  9Comments  路  Source: plotly/plotly.js

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

feature

Most helpful comment

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.

All 9 comments

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

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

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;
}

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).

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
}

... 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.

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?

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.

Thanks very much @alexcjohnson I agree with all your points :1st_place_medal:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pynklu picture pynklu  路  3Comments

WG- picture WG-  路  3Comments

maxwell8888 picture maxwell8888  路  3Comments

mithi picture mithi  路  3Comments

etpinard picture etpinard  路  3Comments