Plotly Dash Heatmap customdata

I’m using Dash, and I made a heatmap (go.Heatmap). It works, it’s visible, it’s gorgeous.

Now I’m trying to add customdata to it (to be used on a click event later, aka I’m accessing clickdata later). I have two bar graphs were I put in customdata and when I click on them, I get the customdata field in my clickdata. I have tried and failed to do the same with the heatmap. Here is a dummy example of what I’m writing:

trace_heatmap = go.Heatmap(
        x=xlabels,
        y=ylabels,
        z=zdata,
        customdata=my_list_that_works_correctly_for_text,
        colorscale=colorscale,
        text=my_list_that_works_correctly_for_text,
        hoverinfo='text+x+y')

Everything works, except the customdata. In this example, I’ve set it equal to the same thing as what I’m using for the text field, as both are lists and the text one worked, so I thought it’d be a good thing to test with. But, as said above, when I click a point and access the clickdata, there is no customdata at all. Any guidance would be appreciated!

2 Likes

Thanks for reporting @raaid!

I have replicated the issue with this example:

import dash
from dash.dependencies import Input, Output
import dash_html_components as html
import dash_core_components as dcc

import json

app = dash.Dash()
app.layout = html.Div([
    dcc.Graph(
        id='heatmap',
        figure={
            'data': [{
                'z': [
                    [1, 2, 3],
                    [4, 5, 6]
                ],
                'text': [
                    ['a', 'b', 'c'],
                    ['d', 'e', 'f']
                ],
                'customdata': [
                    ['c-a', 'c-b', 'c-c'],
                    ['c-d', 'c-e', 'c-f'],
                ],
                'type': 'heatmap'
            }]
        }
    ),
    html.Div(id='output')
])


@app.callback(
    Output('output', 'children'),
    [Input('heatmap', 'hoverData'),
     Input('heatmap', 'clickData')])
def display_hoverdata(hoverData, clickData):
    return [
        json.dumps(hoverData, indent=2),
        html.Br(),
        json.dumps(clickData, indent=2)
    ]


if __name__ == '__main__':
    app.run_server(debug=True)

Looks like a bug to me, I’ll have to look into this a little bit deeper.

Thanks for responding and looking into it! =)

Any updates in looking into this, @chriddyp ?

No updates on this yet

It looks like this is possible in plotly.js: https://codepen.io/chriddyp/pen/NagXpM?editors=1011, so this is probably a bug in the Graph component itself

Hi @chriddyp I am also experiencing this issue in Scatter traces using mode=‘lines’. The bug does indeed seem to be in the Graph component, although my JS knowledge is very limited, I am identifying the conditional below as the likely culprit:

            if (has('curveNumber', fullPoint) &&
                has('pointNumber', fullPoint) &&
                has('customdata', data[pointData.curveNumber])
            ) {
                pointData['customdata'] = data[
                    pointData.curveNumber
                ].customdata[fullPoint.pointNumber];
            }

The bug seems to be that elements (such as lines) which do not have pointNumber attributes are then being cut off from having customdata.

Any chance this bug will be addressed in the near future?

Btw, first plotly comment of mine and just want to say thanks for the amazing work Chris!

Hm, odd. I thought that mode: 'lines' would still have pointNumber. Can you make a small, reproducable example?

Also, welcome to dash! :slightly_smiling_face:

1 Like

A post was split to a new topic: dcc.Graph - only curveNumber is showing up

This still appears to be a problem today (dash==1.13.4, plotly==4.8.1). customdata from go.Heatmap can appear in the figure’s hovertemplate but not in clickdata.

My current solution is to include the necessary data in the figure’s text attribute and parse it out from clickdata['points'][0]['text'] but this is less than ideal.

2 Likes

Can you clarify what you mean by text attribute? I am also trying to navigate this issue. Thanks for the help!

I’ve also been looking at this issue with @bwander.

There are two aspects of current behaviour that was unexpected but we’re not sure if they’re bugs:

  1. customdata is not returned on a clickData event with a go.Heatmap figure

  2. If text is a list, there is no complaint from plotly, however the list is not returned on a clickData event – maybe this should throw an error?

1 Like

Just wanted to revive this topic because this is a real headache to workaround, especially if you want to use both text and customdata for different purposes.

Bump because i have the same issue. I have long labels that have to be shortened before using as the y data, so I add the full text to the customdata for the hovertemplate. In a callback I would like to get the full text.

I think I ran into the same issue as well, here a simple example to reproduce:

import plotly.graph_objects as go
labels = ["a", "b", "c"]
z = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
customdata = [["http://google.com", "http://google.com", "http://google.com"], ["http://google.com", "http://google.com", "http://google.com"], ["http://google.com", "http://google.com", "http://google.com"]]
fig = go.Figure(data=go.Heatmap(x=labels, y=labels,
                                z=z,
                                customdata=customdata,
                                texttemplate="""<a href="%{customdata}">%{z}</a>""",
                                hovertemplate='%{customdata}<extra></extra>',
                                textfont={"size": 20}))
fig.show()

How does the workaround work, how do you parse data from the text?

And another bump, because I too have the issue that if the customdata is an array on any datum, it is not returned in the clickData