Position Plotly Tooltip at XY coord on line with code

Working from slightly modified code found here shown below

from jupyter_dash import JupyterDash
from dash import Dash, dcc, html, Input, Output, no_update, dash_table
import plotly.express as px
import pandas as pd


dict_list = [{'id':1, 'field1':'test1', 'x':1, 'y':1}, {'id':2, 'field1':'test2', 'x':2, 'y':2}, {'id':3, 'field1':'test3', 'x':3, 'y':1}]
df = pd.DataFrame(dict_list)
fig = px.line(df, x='x', y='y', hover_data=[df.id])
fig.update_traces(
    hoverinfo="none",
    hovertemplate=None,
    marker=dict(size=30)
)

app = JupyterDash(__name__)

app.layout = html.Div(
    className="container",
    children=[dash_table.DataTable(id='table-paging-with-graph', data = dict_list,
                columns=[{"name": i, "id": i} for i in ['id', 'field1']],
                page_current=0,
                page_size=20,
                page_action='custom',
                filter_action='custom',
                filter_query='',
                sort_action='custom',
                sort_mode='multi',
                sort_by=[],
                style_filter_conditional=[{
                'if': {'column_id': 'date_processed'},
                'pointer-events': 'None'}]),
            
        dcc.Graph(
            id="graph-3",
            figure=fig,
            clear_on_unhover=True),
        dcc.Tooltip(
            id="graph-tooltip-3",
            background_color="lightgrey",
            border_color="blue"),
    ],
)

@app.callback(
    Output("graph-tooltip-3", "show"),
    Output("graph-tooltip-3", "bbox"),
    Output("graph-tooltip-3", "children"),
    Input("graph-3", "hoverData"),
)
def update_tooltip_content(hoverData):
    if hoverData is None:
        return no_update

    pt = hoverData["points"][0]
    bbox = pt["bbox"]

    children = [
        html.P(f"x: {pt['x']}, y: {pt['y']}")
    ]
    return True, bbox, children

app.run_server(mode='inline')

I am trying to position a tool tip with code at an x, y coord found in fig.data, rather than through pointing on the graph.

fig.data
(Scatter({
     'customdata': array([[1],
                          [2],
                          [3]], dtype=int64),
     'hoverinfo': 'none',
     'legendgroup': '',
     'line': {'color': '#636efa', 'dash': 'solid'},
     'marker': {'size': 30, 'symbol': 'circle'},
     'mode': 'lines',
     'name': '',
     'orientation': 'v',
     'showlegend': False,
     'x': array([1, 2, 3], dtype=int64),
     'xaxis': 'x',
     'y': array([1, 2, 1], dtype=int64),
     'yaxis': 'y'
 }),)

I could achieve the desired result with Plotly.Fx.hover as described here, but I would prefer to not use a client side callback and to avoid the undocumented Plotly.Fx.hover function which I read was going to be deprecated.

Ultimately, I want to link a graph with a dash table using callbacks. When I click on a table cell, I want to see the same tooltip as when I hover on the graph. When I hover on the graph, I want to see a row of the table highlighted.

I have also asked this question on stackoverflow here.

1 Like

This sounds like a really cool idea.

Do you have any test data that we can do? Would you be satisfied with just highlighting the row of the data, or does it have to be the cell specifically?

Thanks for the fast reply. I have updated the question with sample data that includes a dash table. Either highlighting the entire row or a specific column is fine. Ideally I’d like a generic solution that could be expanded and used with mapbox or dash-leaflet maps as well.

1 Like

Hello @jgm,

hoverData is read-only, so you cannot update it. You would need to know the bbox location in order to display it properly.

However, I was able to get it to highlight the information on the table:

#from jupyter_dash import JupyterDash
from dash import Dash, dcc, html, Input, Output, no_update, dash_table, ctx
from dash.exceptions import PreventUpdate
import plotly.express as px
import pandas as pd

dict_list = [{'id': 1, 'field1': 'test1', 'x': 1, 'y': 1}, {'id': 2, 'field1': 'test2', 'x': 2, 'y': 2},
             {'id': 3, 'field1': 'test3', 'x': 3, 'y': 1}]
df = pd.DataFrame(dict_list)
fig = px.line(df, x='x', y='y', hover_data=[df.id])
fig.update_traces(
    hoverinfo="none",
    hovertemplate=None,
    marker=dict(size=30)
)

app = Dash(__name__)

app.layout = html.Div(
    className="container",
    children=[dash_table.DataTable(id='table-paging-with-graph', data=dict_list,
                                   columns=[{"name": i, "id": i} for i in ['id', 'field1']],
                                   page_current=0,
                                   page_size=20,
                                   page_action='custom',
                                   filter_action='custom',
                                   filter_query='',
                                   sort_action='custom',
                                   sort_mode='multi',
                                   sort_by=[],
                                   style_filter_conditional=[{
                                       'if': {'column_id': 'date_processed'},
                                       'pointer-events': 'None'}]),

              dcc.Graph(
                  id="graph-3",
                  figure=fig,
                  clear_on_unhover=True),
              dcc.Tooltip(
                  id="graph-tooltip-3",
                  background_color="lightgrey",
                  border_color="blue"),
              ],
)


@app.callback(
    Output("graph-tooltip-3", "show"),
    Output("graph-tooltip-3", "bbox"),
    Output("graph-tooltip-3", "children"),
    Output("table-paging-with-graph", "active_cell"),
    Input("graph-3", "hoverData"),
)
def update_tooltip_content(hoverData):
    if hoverData is None:
        return no_update

    pt = hoverData["points"][0]
    bbox = pt["bbox"]

    children = [
        html.P(f"x: {pt['x']}, y: {pt['y']}")
    ]
    return True, bbox, children, {'column':0, 'row':pt['x']-1}


app.run_server(debug=True)

You’d have to determine what information was presented in order to highlight it in the table though.

Thanks again. If there is no way to display a tooltip, is it possible to highlight or place a marker on the vertex that corresponds to the table row? The highlight/marker would need to be removed when a new table cell was clicked.