Is there a faster way to access plot limits than using full_figure_for_development?

I need to access the plot limits of a figure so that I can dynamically reposition some annotations. However the code to access the limits is very slow:

  full_fig = fig.full_figure_for_development(warn=False)
  xlims = full_fig.layout.xaxis.range
  ylims = full_fig.layout.yaxis.range

Is there a faster way to access the limits than using the above method?

Many thanks.

Hi @am1234 yes, in Dash you can use a clientside callback to grab the axis ranges:

import dash
from dash import html, dcc, clientside_callback, Output, Input, State
import plotly.graph_objects as go

app = dash.Dash(__name__)

app.layout = html.Div(
        html.Button(id='btn', children='get range'),

    function(click, fig) {
        const x_range = fig.layout.xaxis.range;
        const y_range = fig.layout.yaxis.range;
        return JSON.stringify([x_range, y_range])
    Output('out', 'children'),
    Input('btn', 'n_clicks'),
    State('graph', 'figure'),

if __name__ == "__main__":

mred cscb range

1 Like

Thank you.

This does open up another problem for me, however. I was previously updating the figure, getting the limits, and then adding some annotations based on the limits, all in one callback. That was possible with full_figure_for_development, but extremely slow!

fig = scatter(**graph_params)
full_fig = fig.full_figure_for_development(warn=False)
x_lims = full_fig.layout.xaxis.range
y_lims = full_fig.layout.yaxis.range

However, now if I’m having to first return the figure from a callback, then in a seperate callback get the limits, I’m unsure how then to go back and add annotations to my already published figure.

If I try and access the figure as a state, it’s just a dictionary object, not the figure object, so I can’t call any methods on it. Is there a known workaround for this? I guess I could return the graph twice in two seperate callbacks, but this seems a bit wasteful, just to extract the limits.

Apologies, very new to dash.

You are very welcome, no need for apologies.

You could add the annotations “manually” by creating the corresponding entries in the figure dictionary but I agree with you, that this is quite cumbersome.

You can always create a Figure object by passing the figure dictionary into go.Figure()

fig_obj = go.Figure(fig_dict)

In general: you could trigger the clientside callback, obtain the ranges, write them into a dcc.Store() and let the second callback be triggered by the change of data in the dcc.Store(). But it really depends on how you want to set it up and what you want to do. If you need further help, please open a new topic for this :raised_hands: