Black Lives Matter. Please consider donating to Black Girls Code today.

Multiple callbacks from go.Figure() rangeslider

Hi all,

I am a real newbie with Dash but it looks really great! I have however run into smth that I can’t solve (spent half a day googling, still no dice).

I have a simple barchart that represents a pandas dataframe values over time period. I would like to use Plotly go.Figure() because I really like a rangeslider that comes with it (I like that it shows a “mini” version of the chart).
Example from here: https://plotly.com/python/range-slider/#basic-range-slider-and-range-selectors

I’ve done it like this:

fig = go.Figure()
fig.add_trace(
    go.Bar(x=dfAlarmsPerDay['Date'], y=dfAlarmsPerDay['Count']))
# Add range slider
fig.update_layout(
    xaxis=dict(
        rangeslider=dict(
            visible=True,
            yaxis=dict(
                    rangemode='auto'
                    )
        ),
        type="date"
    )
)

app.layout = html.Div(children=[
        html.H1('Alarm Report (based on IEC 62682)',
                style={'textAlign': 'center'}
                ),
        
        html.H3('Activated alarms per day',
                style={'textAlign': 'center'}
                ),
        
        dcc.Graph(
                id='activated-alarms-per-day',
                figure=fig
                )])

Now I would like to add a pie-chart that shows some aggregates calculated with pandas. So, I added this to my layout:

dcc.Graph(id='annunciated-alarm-priority-distribution-4-priorities',
                figure=fig2
                )

and then added a callback like this:

@app.callback(
        [        
         Output('annunciated-alarm-priority-distribution-4-priorities', 'figure')
         ],
        [Input('activated-alarms-per-day', 'relayoutData')]
        )
def update_output_div(zoom):
  t = timeit.default_timer()
  print('Callback ''update_output_div'' trigerred...')

   ----calculations of aggregates here

  ret_fig2 = px.pie(
            dfPriorityDistribution4, 
            values='Count', 
            names='Priority'
            )
  print('Callback ''update_output_div'' completed in {} sec...'.format(timeit.default_timer() - t))
  return ret_fig2

This callback uses “relayoutData” to get the new start and end times, filter pandas dataframe for this time period

Here’s my problem:
When I use the main area of the barchart to perform a horizontal zoom, I only see 1 callback happening when I release the left mouse button. The resulting output chart is updated in 0.5 seconds or so. This is good.
In my terminal I see smth like this:

Callback update_output_div trigerred...
Callback update_output_div completed in 0.5864191540001684 sec...

But when I use the range slider underneath the barchart, I see multiple callbacks firing one after another. They seem to clog up the processing and it takes quite a long time for the result to update. If I move the slider about a little bit I can see 5 to 10 or even more callbacks firing and the resulting output chart is not updated for good 30 seconds. Moreover, the callbacks seem to become much slower to process.
In my terminal I see smth like this:

Callback update_output_div trigerred...
Callback update_output_div trigerred...
Callback update_output_div trigerred...
Callback update_output_div trigerred...
Callback update_output_div trigerred...
Callback update_output_div trigerred...
Callback update_output_div completed in 2.141093986999998 sec...
Callback update_output_div trigerred...
Callback update_output_div completed in 5.213249470000001 sec...
Callback update_output_div trigerred...
Callback update_output_div completed in 5.566420781000005 sec...
Callback update_output_div completed in 5.725463563999995 sec...
Callback update_output_div trigerred...
Callback update_output_div completed in 5.955499562 sec...
Callback update_output_div completed in 5.742751425000002 sec...
Callback update_output_div completed in 4.652570503 sec...
Callback update_output_div completed in 2.0965169069999945 sec...
Callback update_output_div completed in 1.6928619630000057 sec...

Is there any way to prevent this behavior?
I was thinking:
a) somehow only fire callback on mouse release?
b) somehow every “next” callback should “kill” the previous one?
c) any other way?

Or am I, due to my lack of knowledge, doing it all wrong?

Hi all,

I’ve been poking at this for a couple more days now and still can’t seem to find a solution.
I’s not just the go.Figure() rangeslider that can potentially cause multiple callbacks. Ultimately, I can achieve the same if I trigger callback with a button several times in a row. If the callback take sometime to process, I end up with a queue…
Any ideas on how to deal with this?

Did you try with the new Dash release, version 1.11.0?

Just tried it with 1.11.0, unfortunately it’s the same problem: multiple callbacks triggered:

Callback trigerred...
Callback trigerred...
Callback trigerred...
Callback trigerred...
Callback trigerred...
Callback trigerred...
Callback completed in 3.073383564000011 sec...
Callback trigerred...
Callback completed in 3.53843479599999 sec...
Callback trigerred...
Callback completed in 4.793704132999977 sec...
Callback trigerred...
Callback completed in 5.071845191999984 sec...
Callback completed in 5.240817178000015 sec...
Callback completed in 4.879819362000006 sec...
Callback completed in 3.687503555999996 sec...
Callback completed in 3.4655952319999983 sec...
Callback completed in 2.0417987490000087 sec...