I would like to generate a graph and table from a dash callback, but the code outputs one or the other.
Below is the final part of the code. The data is filtered by chained callbacks (two drop-downs - LGA and SMA) and a radio button (standard deviation picker).
Is there a simple way to generate the two outputs or do I need to add in another callback and define additional functions?
html.Div(
id='graph-container',
children=[]),
dash_table.DataTable(
id='table-container',
columns = [{"name": i, "id": i} for i in df],
data=df.to_dict('records'),
),
])
Populate the SMA's dropdown with options and values
#app.callback(
Output('SMA-dpdn', 'options'),
Output('SMA-dpdn', 'value'),
Input('LGA-dpdn', 'value'),
)
def set_LGA_options(chosen_LGA):
dff = df[df.LGA==chosen_LGA]
SMAs_of_LGAs = [{'label': c, 'value': c} for c in sorted(dff.SMA.unique())]
values_selected = [x['value'] for x in SMAs_of_LGAs]
return SMAs_of_LGAs, values_selected
#app.callback(
Output('graph-container', 'children'),
Output('table-container', 'data'),
Input('radio_items', 'value'),
Input('SMA-dpdn', 'value'),
Input('LGA-dpdn', 'value'),
prevent_initial_call=True
)
Create graph/table component and populate
def graph(max_deviations, selected_SMA, selected_LGA):
if len(selected_SMA) == 0:
return dash.no_update
else:
dff = df[(df.LGA==selected_LGA) & (df.SMA.isin(selected_SMA))]
data = pd.DataFrame(data=dff)
x = dff.TIME
y = dff.CHANGE
mean = np.mean(y)
standard_deviation = np.std(y)
distance_from_mean = abs(y - mean)
not_outlier = distance_from_mean < max_deviations * standard_deviation
no_outliers = y[not_outlier]
trim_outliers = pd.DataFrame(data=no_outliers)
dfd = pd.merge(trim_outliers, dff, left_index=True, right_index=True)
dfd['CHANGE'] = dfd['CHANGE_x']
fig = px.scatter(dfd, x='TIME', y='CHANGE', color ='SMA', trendline='ols', size='PV', height=500, width=800, hover_name='SMA')
return dfd.to_dict('records')
return dcc.Graph(id='display-map', figure=fig)
if __name__ == '__main__':
app.run_server(debug=False)
Your have correctly defined two Outputs on your callback, but then you are only returning a single value which is incorrect.
The code below is your example stripped down and demonstrates the correct way to return multiple values. I have also switched the no_update logic around to demonstrate a cleaner way to structure the code which reduces the risk of introducing a bug on return:
#app.callback(
Output('graph-container', 'children'),
Output('table-container', 'data'),
Input('radio_items', 'value'),
Input('SMA-dpdn', 'value'),
Input('LGA-dpdn', 'value'),
prevent_initial_call=True
)
def graph(max_deviations, selected_SMA, selected_LGA):
if len(selected_SMA) > 0:
# Do processing to create a dfd record and the figure for the Graph
return dcc.Graph(id='display-map', figure=fig), dfd.to_dict('records')
# No update if length was zero.
return dash.no_update, dash.no_update
Related
I am trying to set up a dash app which has 2 layers:
1st page has a couple of input forms, and based on these inputs - app_layout
2nd page - which has a different set of intputs (layout_more_inputs) which pop up depending on what 1st page input is.
I am trying to return layout_more_inputs from a callback but it doesn't work.
app.layout = html.Div([
html.H3('welcome to app'),html.Br(),
dcc.Input(id='input-00-state', type='text', value='QQQ'),
dcc.Input(id='input-01-state', type='text', value='MOVE'),
html.Button(id='submit-button-state', n_clicks=0, children='Go!'),
html.Div(id='output-state'),
dcc.Graph(id='graph-with-slider'),
])
layout_more_inputs = html.Div([
dcc.Input(id='input-10-state', type='number', value='0.11'),
dcc.Input(id='input-11-state', type='number', value=0.12),
html.Button(id='submit-button-state2', n_clicks=0, children='Go Go!'),
])
#front page - 0
#app.callback(
Output('container', 'children'),
Input('submit-button-state', 'n_clicks'),
State('input-00-state', 'value'),
State('input-01-state', 'value'),
)
def ask_for_more_inputs(n_clicks,asset_str,event_str):
print("input summary:")
print(n_clicks,asset_str,event_str)
return layout_more_inputs #<<--DOES NOT WORK
#front page - 1
#app.callback(
Output('graph-with-slider', 'figure'),
Output('output-state', 'children'),
Input('submit-button-state2', 'n_clicks'),
State('input-10-state', 'value'),
State('input-11-state', 'value'),
)
def more_inputs(n_clicks,input0,input1):
d = {'x': [input0, input1], 'y': [input0, input1]}
df = pd.DataFrame(data=d)
filtered_df = df
fig = px.scatter(filtered_df, x="x", y="y")
fig.update_layout(transition_duration=500)
return fig, u'''Button pressed {} times, 1 is "{}", and 2 is "{}"'''.format(n_clicks,state1,state2)
if __name__ == '__main__':
app.run_server(debug=True)
I'm not 100% on what exactly is is you're attempting to deliver, but one options would be to use Dash's dcc.Tabs property.
I've started & laid the groundwork, sort of, for you:
import sys
import dash
from dash import html
from dash import dcc
from dash import no_update
from dash.dependencies import Input, Output, State
# app = dash.Dash(__name__)
app = JupyterDash()
layout = html.Div([
html.H3('welcome to app'),
html.Br(),
dcc.Input(id='input-00-state', type='text', value='QQQ'),
dcc.Input(id='input-01-state', type='text', value='MOVE'),
html.Button(id='submit-button-state', n_clicks=0, children='Go!'),
html.Div(id='output-state'),
dcc.Graph(id='graph-with-slider'),
])
layout_more_inputs = html.Div([
dcc.Input(id='input-10-state', type='number', value=0.11),
dcc.Input(id='input-11-state', type='number', value=0.12),
html.Button(id='submit-button-state2', n_clicks=0, children='Go Go!'),
])
tabs = [
dcc.Tab(label="Front Page - 0", children=layout),
dcc.Tab(label="Front Page - 1", children=layout_more_inputs)
]
multitab_layout = [dcc.Tabs(id="tabs", children=tabs)]
app.layout = html.Div(
[html.Div(id="multitab_layout", children=multitab_layout)])
# front page - 0
#app.callback(
Output('container', 'children'),
Input('submit-button-state', 'n_clicks'),
[State('input-00-state', 'value'),
State('input-01-state', 'value')]
)
def ask_for_more_inputs(n_clicks, asset_str, event_str):
print("input summary:")
print(n_clicks, asset_str, event_str)
return layout_more_inputs # <<--DOES NOT WORK
# front page - 1
#app.callback([
Output('graph-with-slider', 'figure'),
Output('output-state', 'children')
], Input('submit-button-state', 'n_clicks'),
Input('submit-button-state2', 'n_clicks'), [
State('input-00-state', 'value'),
State('input-01-state', 'value'),
State('input-10-state', 'value'),
State('input-11-state', 'value')
])
def more_inputs(n_clicks, n_cliks2, input0, input1, state0, state1, state10,
state11):
d = {'x': [input0, input1], 'y': [input0, input1]}
df = pd.DataFrame(data=d)
filtered_df = df
fig = px.scatter(filtered_df, x="x", y="y")
fig.update_layout(transition_duration=500)
return fig, u'''Button pressed {} times, 1 is "{}", and 2 is "{}"'''.format(
n_clicks, state1, state2)
if __name__ == '__main__':
app.run_server(debug=True)
using your provided code; but not entirely sure where exactly you'd want it to go from here. In terms of UI/EX behavior etc. Perhaps this may be enough of a clue to get you going as you need to...
I am trying to handle a callback by return a simple Graph based on Drop-Down and Date-Picker Inputs after Click Submit Button....
So to explain in deep,
Example:
As for the below Image, let's imagine that this is the final result I need to be looks like:
So Here's a simple of Data-base looks like I use as the Below Image:
Ok Lets Explain In-Deep:
Now I need to Out-Put a Simple Graph That's Shows a simple line with the values based on the below Input:
1st Drop-Down contains the CellName values like in the Database
2nd Drop-Down Contains the list of specific Column Names I want to out-put in the Graph.
3rd Date-Picker Contains all the dates which was in the Date Column in the previous DB Picture.
Finally I want Click this button to Generate the Graph.
So Here's My Code as the below:
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
from sqlalchemy import create_engine
import datetime
from datetime import datetime as dt
from dash.dependencies import Input, Output
# connect db
engine = create_engine('mssql+pyodbc://WWX542337CDCD\SMARTRNO_EXPRESS/myDB?driver=SQL+Server+Native+Client+11.0')
cursor = engine.raw_connection().cursor()
start = datetime.datetime(2019, 12, 2)
end = datetime.datetime(2019, 12, 15)
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
gsm_kpis = pd.read_sql('SELECT * FROM [myDB].[dbo].[mnm_rotterdam_5_daily_details-20191216081027]',
engine)
gsm_kpis_raw = pd.read_sql('SELECT Voice_SetupFailRate_2G, '
'Voice_DropRate_2G, Packet_SetupFailRate_2G, '
'OutgHandover_SuccesRate_2G, Voice_ErlHr_2G, Packet_DLMBytes_2G, Packet_ULMBytes_2G, '
'Availability_2G FROM [myDB].[dbo].[mnm_rotterdam_5_daily_details-20191216081027]',
engine)
pd.set_option('display.max_columns', 500)
pd.set_option('display.width', 1000)
availble_cell = gsm_kpis['CellName'].unique()
app.layout = html.Div([
dcc.Dropdown(
id='cell-name-xaxis-column',
options=[{'label': i, 'value': i} for i in availble_cell],
value='11063'
),
dcc.Dropdown(
id='myColumns',
options=[{'label': col, 'value': col} for col in gsm_kpis_raw.columns],
value='Voice_SetupFailRate_2G'
),
dcc.DatePickerRange(
id='my-date-picker-range',
min_date_allowed=dt(1995, 8, 5),
max_date_allowed=dt(2030, 9, 19),
initial_visible_month=dt(2019, 10, 5),
start_date=dt(2019, 10, 1),
end_date=dt(2020, 1, 1)
),
html.Div(id='output-container-date-picker-range'),
html.Button('Submit', id='button'),
dcc.Graph(
style={'height': 300},
id='my-graph'
)
])
#app.callback(
Output('my-graph', 'figure'),
[Input('cell-name-xaxis-column', 'value'),
Input('myColumns', 'value')])
def update_graph(xaxis_column_name, yaxis_column_name, date_value):
dff = gsm_kpis[gsm_kpis['Date'] == date_value]
return {
'data': [dict(
x = dff[dff['Date'] == xaxis_column_name]['Value'],
y = dff[dff['Date'] == yaxis_column_name]['Value'],
text = dff[dff['Date'] == yaxis_column_name]['Cell Name'],
mode = 'line',
line = {
'size': 15,
'opacity': 0.5
}
)],
}
if __name__ == '__main__':
app.run_server(debug=True)
and this is the Error I find:
TypeError: update_graph() missing 1 required positional argument: 'date_value'
I think there's a problem with handeling the Call-Back function...
Anyone Could help me how Can I handle this?
I hope everything will be clear...
Note: not Important to use the Submit button
In this part:
#app.callback(
Output('my-graph', 'figure'),
[Input('cell-name-xaxis-column', 'value'),
Input('myColumns', 'value')])
def update_graph(xaxis_column_name, yaxis_column_name, date_value):
You have not made an Input for date_value, but as your date selection control is a range picker, you'll need to supply a start and end Input, as follows:
#app.callback(
Output('my-graph', 'figure'),
[Input('cell-name-xaxis-column', 'value'),
Input('myColumns', 'value'),
Input('my-date-picker-range', 'start_date'),
Input('my-date-picker-range', 'end_date')])
def update_graph(xaxis_column_name, yaxis_column_name, start_date, end_date):
And change your update_graph code as appropriate.
I have a basic dash app that graphs some data from a dictionary of dataframes. The first dropdown selects the df, while the second selects the columns of the df to be plotted.
This works well, but I can't seem to add a new yaxis for each of the plotted columns. I have a large number of columns in each df and they change depending on the df that is selected.
First, I tried to change the updateGraph callback to include yaxis=i after defining x, y & name. Looking at the documentation, it seems that I can define the yaxis in go.Scatter but that I would need to set them as 'y2', 'y3, 'y4' etc. I've also tried to update the layout via go.Figure.add_trace in this way but neither has worked. The code is below, where dict_main is a dictionary of dataframes of various sizes.
All help is appreciated!
data = list(dict_main.keys())
channels = dict_main[data[0]]
app.layout = html.Div(
[
html.Div([
dcc.Dropdown(
id='data-dropdown',
options=[{'label': speed, 'value': speed} for speed in data],
value=list(dict_main.keys())[0],
searchable=False
),
], style={'width': '49%', 'display': 'inline-block'}),
html.Div([
dcc.Dropdown(
id='channel-dropdown',
multi=True
),
], style={'width': '49%', 'display': 'inline-block'}
),
html.Div([
dcc.Graph(
id='Main-Graph',
),
], style={'width': '98%', 'display': 'inline-block'}
)
]
)
#app.callback(
Output('channel-dropdown', 'options'),
[Input('data-dropdown', 'value')])
def update_date_dropdown(speed):
return [{'label': i, 'value': i} for i in dict_main[speed]]
#app.callback(
Output('Main-Graph', 'figure'),
[Input('channel-dropdown', 'value')],
[State('data-dropdown', 'value')])
def updateGraph(channels, speed):
if channels:
return go.Figure(data=[go.Scatter(x=dict_main[speed].index, y=dict_main[speed][i], name=i, yaxis='y2') for i in channels])
else:
return go.Figure(data=[])
if __name__ == '__main__':
app.run_server()
UPDATE! This works, although some small changes to color and position are still needed - Thanks to #Philipp for all the help;
#app.callback(
Output('Main-Graph', 'figure'),
[Input('channel-dropdown', 'value')],
[State('rpm-dropdown', 'value')])
def updateGraph(channels, test):
if channels:
j=1
my_layout = {}
my_axis = list("")
for index, column in enumerate(list(channels)):
my_layout['yaxis' + str(j) if j > 1 else 'yaxis'] = {}
my_layout['yaxis' + str(j) if j > 1 else 'yaxis']['title'] = column
my_layout['yaxis' + str(j) if j > 1 else 'yaxis']['overlaying'] = 'y' if j > 1 else 'free'
my_layout['yaxis' + str(j) if j > 1 else 'yaxis']['anchor'] = 'free'
my_layout['yaxis' + str(j) if j > 1 else 'yaxis']['side'] = 'left'
my_axis.append('y' + str(j) if j > 1 else 'y')
j+=1
return go.Figure(data=[go.Scatter(x=dict_main[test].index, y=dict_main[test][column], name=column, yaxis=my_axis[index]) for index, column in enumerate(channels)],layout=my_layout)
else:
return go.Figure(data=[])
You have to define every y-axis in the layout property of your graph (right now you're only setting the data property). See this example.
If you don't want to draw all y-axes (if your df has many columns) you have to set some of them invisible via setting variables like [overlaying, ticks, showticklabels, showgrid, zeroline] (you can find info about them here) but they still have to be defined accordingly in the layout so you can refer to them in the scatter function.
I am trying to create dash table on Web using Inputs. However the issue is that the data is created from database from the callback and a priori,
I do not know the names of the columns unless the pandas dataframeis created using the callback function.
I have checked that I getting correct data. However not able to display it. I have used multiple output options (using Dash 0.41)
My code looks as follows: ( I have not provided the details of the function which generates the pandas dataframe in the callback someFunc,
as that was not important for the purpose of this Dash code TroubleShooting.
import dash_table as dt
def someFunc(ID, pattern_desc, file_path):
## do something
return df # pandas dataframe
#
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
server = app.server
app = dash.Dash(__name__)
app.config.suppress_callback_exceptions = True
app.css.config.serve_locally = True
app.scripts.config.serve_locally = True
app.layout = html.Div(
children = [
html.Div(
id = 'title',
children = appTitle,
className = 'titleDiv'
),
html.Div(
children = [
html.Div(
children = "Enter ID:",
className = 'textDiv'
),
dcc.Input(
id = 'ID',
type = 'text',
value = 'ABCER1',
size = 8),
html.Div(
children = "Enter Test Pattern",
className = 'textDiv'
),
dcc.Input(
id = 'pattern_desc',
type = 'text',
value = 'Sample',
size = 20),
html.Div(
children = "Enter File OutPut Path:",
className = 'textDiv'
),
dcc.Input(
id = 'file_path',
type = 'text',
value = '',
size = 30),
html.Button(
id = 'submit',
n_clicks = 0,
children = 'Search'
)
]
),
html.Div(
id = 'tableDiv',
children = dash_table.DataTable(
id = 'table',
style_table={'overflowX': 'scroll'},
style_as_list_view=True,
style_header={'backgroundColor': 'white','fontWeight':
'bold'},
),
className = 'tableDiv'
)
]
)
# callback to update the table
#app.callback([Output('table', 'data'),Output('table', 'columns')]
[Input('submit', 'n_clicks')],
[State('ID', 'value'), State('pattern_desc', 'value'),
State('file_path', 'value')])
def update_table(n_clicks, ID, pattern_desc, file_path):
df = someFunc(ID, pattern_desc, file_path)
mycolumns = [{'name': i, 'id': i} for i in df.columns]
return html.Div([
dt.DataTable(
id='table',
columns=mycolumns,
data=df.to_dict("rows")
)
])
So in this case the function someFunc which takes the 3 input arguments returns a pandas dataframe which can have different columns based on the inputs. Thus the app layout should display
those columns as given by the output of the callback function dynamically based on the inputs.
I should be getting the webpage populated with table and columns, But instead getting an error. When I run this, I am getting the data generated through the function to the file, but dash is not able to
generated the table on webpage. I get the following error:
dash.exceptions.InvalidCallbackReturnValue: The callback ..table.data...table.columns.. is a multi-output.
Expected the output type to be a list or tuple but got Div([DataTable(columns=[{'name': 'pattern_desc', 'id': 'pattern_desc'}, ......
Not Sure How I can achieve that. Any help will be appreciated.
In your Dash callback you are supposed to be returning 2 separate values to the 2 separate outputs:
[Output('table', 'data'),Output('table', 'columns')]
You are returning:
return html.Div([
dt.DataTable(
id='table',
columns=mycolumns,
data=df.to_dict("rows")
)
])
which is only 1 output.
Dash expects 2 return values in either a list, or a tuple like so:
return("output1" , outputVariable2)
or
return[ Html.Div("text") , "output Text 2"]
in order to fix the problem, either return 2 values in a tuple or list, or edit your output requirements so only one value is necessary.
From the looks of it you are trying to return a Div with a Datatable in it, so you could just make the following changes:
html.Div(
id = 'tableDiv',
className = 'tableDiv'
)
...
#app.callback([Output('tableDiv', 'children')]
[Input('submit', 'n_clicks')],
[State('ID', 'value'), State('pattern_desc', 'value'),
State('file_path', 'value')])
def update_table(n_clicks, ID, pattern_desc, file_path):
df = someFunc(ID, pattern_desc, file_path)
mycolumns = [{'name': i, 'id': i} for i in df.columns]
return html.Div([
dt.DataTable(
id='table',
columns=mycolumns,
data=df.to_dict("rows")
)
])
If I've understood you correctly, then you can simply create another callback which outputs the updated value for the columns prop. You could also use a multi-output callback to update both at the same time.
#app.callback(Output('table', 'columns'),
[Input('submit', 'n_clicks')],
[State('ID', 'value'), State('pattern_desc', 'value'),
State('file_path', 'value')])
def update_table(n_clicks, ID, pattern_desc, file_path):
mydata = someFunc(ID, pattern_desc, file_path)
# here you would use the dataframe columns to create the new column values
return new_column_values
I have a function that takes a matplotlib plot and turns it into a plotly plot using tls.matplotlib_to_pyplot. In the end I named it plotly_fig. Now I'm trying to add sliders to a dash webapp. But when I compile it, I get an error saying plotly_fig is not defined.
The following is some sample code that recreates the error.
import dash
import dash_core_components as dcc
import dash_html_components as html
import numpy as np
from numpy.linalg import matrix_power
import matplotlib.pyplot as plt
import plotly.tools as tls
from mpl_toolkits.mplot3d import Axes3D
from dash.dependencies import Input, Output
app = dash.Dash()
#begin with the knobs
app.layout = html.Div([
dcc.Graph(
id = 'graph',
figure = plotly_fig),
html.Label('Config L'), ## this is the knob for the length
dcc.Slider(
id = 'l',
min = 5,
max = 10,
marks = {i: 'Label ={}'.format(i) if i == 1 else str(i) for i in range(5,10)},
value = L,
),
html.Label('Config n'), ##knob for the n-gon
dcc.Slider(
id = 'n',
min = 0,
max = 10,
marks = {i: 'Label ={}'.format(i) if i == 1 else str(i) for i in range(1,10)},
value = n,
),
html.Label('Config N'), ##knob for the number of n-gons outside initial
dcc.Slider(
id = 'N',
min = 0,
max = 10,
marks = {i: 'Label ={}'.format(i) if i == 1 else str(i) for i in range(1,10)},
value = N,
),
html.Label('Config r'), ##knob for r only works on integers for now
dcc.Slider(
id = 'r',
min = 0,
max = 2,
marks = {i: 'Label ={}'.format(i) if i == 1 else str(i) for i in range(1,2)},
value = r,
),
html.Label('Config d'), ##knoc for the depth of the dip
dcc.Slider(
id = 'd',
min = 0,
max = 2,
marks = {i: 'Label ={}'.format(i) if i == 1 else str(i) for i in range(1,2)},
value = d,
)
],
style = {'columnCount': 1})
#app.callback(
dash.dependencies.Output('graph', 'figure'),
[dash.dependencies.Input('l', 'value'),
dash.dependencies.Input('n', 'value'),
dash.dependencies.Input('N', 'value'),
dash.dependencies.Input('r', 'value'),
dash.dependencies.Input('d', 'value')])
def output(L,n,N,r,d):
x = np.linspace(np.pi, L*n*N*r*d*np.pi, 1000)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x, sinx)
plotly_fig = tls.mpl_to_plotly(mpl_fig)
return{plotly_fig}
if __name__=='__main__':
app.run_server(debug = True)
What am I doing wrong?
The problem is that the variable plotly_fig is not even declared when you are trying to use it in the Graph's figure field. It is just declared locally in the callback.
It is not required to set the figure property of the Graph explicitly, It will be automatically mapped during the callback, so you can directly do it like this,
#your code here
app = dash.Dash()
#begin with the knobs
app.layout = html.Div([
dcc.Graph(
id = 'graph'), # ==> here you can remove the figure as it will be automatically set during the callback.
#your code here
],
style = {'columnCount': 1})
#app.callback(
dash.dependencies.Output('graph', 'figure'), #here figure represents the field
[dash.dependencies.Input('l', 'value'),
dash.dependencies.Input('n', 'value'),
dash.dependencies.Input('N', 'value'),
dash.dependencies.Input('r', 'value'),
dash.dependencies.Input('d', 'value')])
def output(L,n,N,r,d):
#your code here
plotly_fig = tls.mpl_to_plotly(mpl_fig)
return{plotly_fig}
if __name__=='__main__':
app.run_server(debug = True)
In the above snippet case, the value property of the Slider is the input of the app and the output of the app is the figure property of the Graph. Whenever the value of the Slider changes, Dash calls the callback function output with the new input values. The function filters the dataframe with this new value, constructs a figure object, and returns it to the Dash application.
Meanwhile, if you want a default value to be set even before the callback function is called you can declare plotly_fig as a global variable like this,
#your code here
plotly_fig = None # declare the default figure here
app = dash.Dash()
#begin with the knobs
app.layout = html.Div([
dcc.Graph(
id = 'graph', figure = plotly_fig),
#your code here
],
style = {'columnCount': 1})
#app.callback(
dash.dependencies.Output('graph', 'figure'),
[dash.dependencies.Input('l', 'value'),
dash.dependencies.Input('n', 'value'),
dash.dependencies.Input('N', 'value'),
dash.dependencies.Input('r', 'value'),
dash.dependencies.Input('d', 'value')])
def output(L,n,N,r,d):
#your code here
plotly_fig = tls.mpl_to_plotly(mpl_fig)
return{plotly_fig}
if __name__=='__main__':
app.run_server(debug = True)
For more information refer the official documentation page which has a similar example,
https://dash.plot.ly/getting-started-part-2