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

Dash dashboard won't run when callback is included

Hello everyone! I’m currently using JupyterDash within a Jupyter notebook. My current issue is that I’m having a hard time incorporating a functioning Plot.ly go.FigureWidget with my Dash dashboard.

Information about go.FigureWidget

  • Within this notebook, I have a go.FigureWidget plot with two scatter plots
  • This go.FigureWidget is updated every minute within a separate cell
  • These updates successfully display within the cell containing the code below
fig = go.FigureWidget(layout=go.Layout(title=go.layout.Title(text="Live BTC"),
                                      )
                     )
fig.add_scatter(name='actual')
fig.add_scatter(name='prediction')

Information about the Dash Dashboard

  • My goal is to incorporate the above go.FigureWidget within a Dash dashboard
  • I was able to display the graph with an external dashboard, but I had to physically refresh the page to get the updates
  • As a result, I decided to implement dcc.Interval so that the dashboard would update on its own
  • However, I’m unable to benefit from the dcc.Interval because I’m having issues with @app.callback
  • As soon as I uncomment the @app.callback lines, I get “SyntaxError: invalid syntax”
# Build App
app = JupyterDash(__name__)
app.layout = html.Div([
    html.H1("My dashboard", style= {'text-align':'center', 'font-family':'Viga'}),
    
    #Side-by-Side graphs
    html.Div(children = [
        dcc.Graph(id='g1', figure={'data': [{'y': [1, 2, 3]}]}, style={'display': 'inline-block'}),
        dcc.Graph(id='g2', figure={'data': [{'y': [1, 2, 3]}]}, style={'display': 'inline-block'})
    ]),
    
    #Live BTC
    dcc.Graph(figure=fig, id='live-update-graph'),
    dcc.Interval(
        id = 'interval-component',
        interval = 1 * 1000, #Update graph every second (in milliseconds) 
        n_intervals = 0
    )
], style={'textAlign': 'center'})


# Define callback to update graph
@app.callback(
    Output('live-update-graph', 'figure'),
    [Input('interval-component', 'n_intervals')]
)

# Run app and display result external in the notebook
app.run_server(mode='external')

Does anyone know why this is? The only explanation I can think of is that my @app.callback has errors but I got it directly from an example

This is not how callbacks work. A callback is decorator which decorates a function.

@app.callback(
    Output('live-update-graph', 'figure'),
    [Input('interval-component', 'n_intervals')]
)
def update_some_graph(n_intervals): 
    """Return the figure in this function"""
    fig = go.FigureWidget(layout=go.Layout(title=go.layout.Title(text="Live BTC"),
                                      )
                     )
    fig.add_scatter(name='actual')
    fig.add_scatter(name='prediction')
    return fig 

More info on decorators

An example of live graph

Hope this helps!

Oh that makes sense! Within a cell later on in the notebook, I have a cell where I’m running a machine learning model that continually updates the figure every minute. It goes through the existing data, gets predictions for the next minute, and then updates the figure with those predictions

fig.data[0].y = item1
fig.data[0].x = item2
fig.data[1].y = item3
fig.data[1].x = item4

Where item1 is a numpy.array, item2 is a pandas.Series, and item3 and item4 are lists. As mentioned, these updates successfully display in live time within the cell containing the code for the go.FigureWidget. However, I have to refresh the external dashboard in order for the changes to be reflected in the dashboard.

I’m a bit unsure how to reference these changes within the function (ex: update_some_graph) that the callback is decorating. I’ve tried finding similar examples online, but can’t seem to find any. Would you recommend that I just re-write the ML code in a way that allows it to be a function that is called every minute instead of just continually running in the code cell below?