Triggering Hover Events in python

Hey,

I am currently creating a dashboard for debugging purposes. So far I have a plot with data points. Upon a click event a data point is chosen, meaning hover data is displayed. However, I’d like to have an input field where one can choose the data point manually, as having to search through all data points to find one specific one is not very handy.
So I wondered whether it’s possible in python to trigger a hover event when the position of the data point is known?
I have been looking through a few attempts in JavaScript but couldn’t really figure out how to include this into my code:

  1. plotly.Fx.hover(figure, {curveNumber: curveNumber, pointNumber: pointNumber}, “mapbox”)
  2. Hover events in JavaScript

Appreciate if anyone knows something. Thanks!

Hi @Vale1
What do you need to display? Do you have an example?
Maybe you can use an annotation instead or custom labels on points and show/hide them

Hey @Skiks,

thank you very much for your response!
It is just a normal scatter plot and I would like to highlight one data point after another by choosing its number. However, the scatter contains many data points and the processing time is rather long. So I’m trying to avoid manually changing it and having to rerun the callback function as this would mean recalculating the whole scatter.

Please let me know if you have any idea on how to approach this!

Cheers!

Hello @Vale1,

It sounds like you could use Partial updates new from Dash 2.9.

With this, you can implement @Skiks suggestion of making an annotation, without having to rerender the whole plot.

If you are looking for displaying data quickly by hovering, you should check out here:

1 Like

Indeed, Patch() + annotation seem to work fine, also using go.Scattergl() instead of go.Scatter() should help if you have lot of points.

Here an example with 10,000 points:

import dash
from dash import dcc, html, Input, Output, Patch
import dash_bootstrap_components as dbc
import plotly.graph_objects as go
import numpy as np

app = dash.Dash(__name__, external_stylesheets=[dbc.themes.SPACELAB])

N = 10000
r = np.random.uniform(0, 1, N)
theta = np.random.uniform(0, 2 * np.pi, N)

fig = go.Figure(data=go.Scattergl(
    x=r * np.cos(theta),
    y=r * np.sin(theta),
    mode='markers',
    marker=dict(
        colorscale='Viridis',
        line_width=1
    ),
))

fig.add_annotation()

fig.update_layout(height=1000)

app.layout = html.Div(
    [
        dbc.Input(id="input-id", type="number", min=0, max=N - 1, step=1, placeholder='Select ID',
                  className='text-center', style={'width': 150}),
        dcc.Graph(id="graph-scatergl", figure=fig),
    ]
)


@app.callback(
    Output("graph-scatergl", "figure"),
    Input("input-id", "value"),
)
def highlight_point(point_id):
    fig_patch = Patch()

    if point_id is None:
        fig_patch['data'][0]['marker']['color'] = r
        fig_patch['data'][0]['marker']['opacity'] = 1
        fig_patch['layout']['annotations'][0]['visible'] = False
        return fig_patch

    x = round(r[point_id] * np.cos(theta[point_id]), 2)
    y = round(r[point_id] * np.sin(theta[point_id]), 2)
    text = f'x = {x}<br>y = {y}'
    marker_opacity = [0.2] * N
    marker_opacity[point_id] = 1

    fig_patch['data'][0]['marker']['opacity'] = marker_opacity
    fig_patch['layout']['annotations'][0].update(
        visible=True,
        x=x, y=y,
        text=text,
        showarrow=False,
        xshift=35,
        bgcolor="rgba(255,255,255,0.8)",
    )

    return fig_patch


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

:information_source: I made no comments in the code, don’t hesitate to ask me for details.

I used markers opacity to have a nice fading effect to have a better highlight on the selected point.
But if you have performance issues, you may remove opacity modification, as it updates an array of size N and maybe use an arrow with the annotation to point on the … point :laughing: to be more precise.

And you can customize your annotation as you like, see Styling and Coloring Annotations

2 Likes