Cannot extract data using 'Box Select' option from figure Scatter subplots

Hi,

I have a problem when trying to use ‘Box Select’ option for extracting selected points. Namely, I’ve created a figure which enables multiple subplots on it. First subplot acts like a main subplot and it has ‘secondary_y’ option disabled. All others have that option enabled because they have different y-axis values. Common thing for all subplots is that they have common x-axis.


fig = make_subplots(specs=[[{"secondary_y": True}]])

...

fig.add_trace(
                go.Scatter(
                    x=x_data,
                    y=y_data,
                    mode=some_mode,
                    name=some_name,
                    yaxis="y" + str(i+1), # property defined only for subplots except the main one
                ),
                secondary_y=True, # or False in case of main plot
            )

I’ve created a callback which reacts upon triggering ‘selectedData’ property. When I’m creating selection box on the figure, it captures all the points within that box from all the plots. Problem emerges when I’m trying to resize that box. In that case, only points from the main subplot are recognized (markers are being shown and ‘selectedData’ points field has some values) while points from other subplots aren’t recognized at all (neither on the plot, nor within ‘selectedData’ points list).

When in debug mode, I see that ‘selectedPoints’ field is empty for each Scatter plot, if they’re not selected initially.

I’d like to know, how could I extract those selected points from those subplots?

Welcome to the community, @draganb .
Do you mind sharing your full code with data, as a minimal reproducible example?

I would like to run the code locally to try to replicate the issue you’re having.

Thanks for the warm welcome, Adam!

I can’t post original code but here is the example which completely simulates situation I have (file called main.py).

from dash import Dash, html, dcc, callback, Input, Output, State, ALL
import dash_mantine_components as dmc
import plotly.graph_objects as go
from plotly.subplots import make_subplots


def create_figure():
    # Create figure with secondary y-axis
    fig = make_subplots(specs=[[{"secondary_y": True}]])

    # Add traces
    fig.add_trace(
        go.Scatter(x=[1, 2, 3], y=[40, 50, 60], name="yaxis data"),
        secondary_y=False,
    )

    fig.add_trace(
        go.Scatter(x=[2, 3, 4], y=[4, 5, 6], name="yaxis2 data", yaxis="y2"),
        secondary_y=True,
    )

    fig.add_trace(
        go.Scatter(x=[3, 4, 5], y=[400, 500, 600], name="yaxis3 data", yaxis="y3"),
        secondary_y=True,

    )

    # Add figure title
    fig.update_layout(
        title_text="Triple Y Axis Example"
    )

    # Set x-axis title
    fig.update_xaxes(title_text="xaxis title")

    return fig


@callback(
    Output("output_object", "children"),
    Input("plot_graph_button", "n_clicks"),
    prevent_initial_call=True,
)
def display_plot(preview_nodes_button):
    test_plot = create_figure()

    return dcc.Graph(figure=test_plot, id="output_figure")


@callback(
    Output("store_obj", "data"),
    Input("output_figure", "selectedData"),
    State("output_figure", "figure"),
)
def get_statistics_from_data_selected(selected_data, plot_figure):
    if selected_data is not None and selected_data['points']:
        # Extract timestamp range
        x_axis_range = selected_data["range"]["x"]
        x_axis_range[0] = int(x_axis_range[0])
        x_axis_range[1] = int(x_axis_range[1])

    return True


app = Dash(__name__)

app.layout = html.Div([
    html.Div(
        dmc.Button(
            "Plot Graph",
            id="plot_graph_button"
        ),
    ),
    html.Br(),
    dmc.Stack(
        id="output_object",
        children=[
            dcc.Graph(id="output_figure")
        ]
    ),
    html.Br(),
    dcc.Store(
        id="store_obj"
    )
])

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

I’ve used example from official website (https://plotly.com/python/multiple-axes/#multiple-axes).

After pressing Plot Graph button, tutorial graph is shown. Selecting two points by Box Selection option, initially, works flawlessly:

As it can be seen, two points have markers on them and they’re detected within get_statistics_from_data_selected callback function I’ve created. Upon resizing the box, I got following plot:

As you can see, only point from the first subplot is being detected on the plot. In the callback function, number of detected points is increased to three, not five, as it should be.

Let me know if there is anything more needed.