Adding per-point metadata from python


#1

I’m generating an HTML report from within python and I would like to associate additional metadata with each point in a scatter plot. I am using this metadata from some custom javascript in the generated report to display an image associated with that data point. I am currently abusing the text attribute for this purpose, but the strings are large and ugly and really make the hovertext difficult to comprehend. I would like to keep the hovertext as it is useful in my application (so simply turning it off is undesireable).

Is it possible to get additional metadata stored with each point in the generated javascript?

Here is what I have so far:

plot.on('plotly_hover', function(data){
    data.points.map(function(d){
      var elem = document.getElementById(d.text);
      if(elem){
        elem.style.display = "inline";
      }
    });

}).on('plotly_unhover', function(data){
    data.points.map(function(d){
      var elem = document.getElementById(d.text);
      if(elem){
        elem.style.display = "none";
      }
    });
});

Ideally I would be able to set some d.custom_key for each data item. Is this possible?


#2

Hi @cheshirekow,

You can use the scatter.customdata property for this. Here’s an example on the JavaScript side: https://codepen.io/etpinard/pen/YxOKpq?editors=0010

Hope that helps!
-Jon


#3

Perfect, thanks @jmmease. I looked this up in the reference and it works perfectly. From python:

  data.append(
      go.Scatter(x=x, y=y,
                 customdata=["img-{}-{}".format(session_id, ts)
                             for ts in imgs],
                 name="actual",
                 mode="lines"))

and then from javascript:

plot.on('plotly_hover', function(data){
    data.points.map(function(d){
      var elem = document.getElementById(d.customdata);
      if(elem){
        elem.style.display = "inline";
      }
    });

}).on('plotly_unhover', function(data){
    data.points.map(function(d){
      var elem = document.getElementById(d.customdata);
      if(elem){
        elem.style.display = "none";
      }
    });
});