python plolty dash - read .pkl files and display them in plotly dash - python

i changed the following code from using ".png" to ".pkl". but this doesn't work
import plotly.express as px
import joblib
#generate example pkl
fig = px.scatter(x=range(10), y=range(10))
joblib.dump(fig, "img_dash/figure.pkl")
#%%
import dash
import dash_core_components as dcc
import dash_html_components as html
import flask
import glob
import os
image_directory = 'img_dash/'
list_of_images = [os.path.basename(x) for x in glob.glob('{}*.pkl'.format(image_directory))]
static_image_route = '/static/'
app = dash.Dash()
app.layout = html.Div([
dcc.Dropdown(
id='image-dropdown',
options=[{'label': i, 'value': i} for i in list_of_images],
value=list_of_images[0]
),
html.Img(id='image')
])
#app.callback(
dash.dependencies.Output('image', 'src'),
[dash.dependencies.Input('image-dropdown', 'value')])
def update_image_src(value):
return static_image_route + value
#app.server.route('{}<image_path>.pkl'.format(static_image_route))
def serve_image(image_path):
image_name = '{}.pkl'.format(image_path)
if image_name not in list_of_images:
raise Exception('"{}" is excluded from the allowed static files'.format(image_path))
return flask.send_from_directory(image_directory, image_name)
if __name__ == '__main__':
app.run_server(debug=False)
i expect to show the .pkl files in the dashboard with hover-function. may other formats also possible! i was not able to check this.

I recommend you to use a Graph component here instead of an Img component since you want to display these figures dynamically.
Since each pkl file already stores a Figure you can just dynamically load these files using joblib in your callback based on the dropdown value.
Example based on your code:
# Example figures for demo purposes
fig1 = px.scatter(x=range(10), y=range(10))
fig2 = px.scatter(x=range(15), y=range(15))
fig3 = px.scatter(x=range(20), y=range(20))
joblib.dump(fig1, "img_dash/figure1.pkl")
joblib.dump(fig2, "img_dash/figure2.pkl")
joblib.dump(fig3, "img_dash/figure3.pkl")
# ...
image_directory = "img_dash/"
list_of_images = [
os.path.basename(x) for x in glob.glob("{}*.pkl".format(image_directory))
]
app = dash.Dash()
app.layout = html.Div(
[
dcc.Dropdown(
id="image-dropdown",
options=[{"label": i, "value": i} for i in list_of_images],
value=list_of_images[0],
),
dcc.Graph(id="graph"),
]
)
#app.callback(
dash.dependencies.Output("graph", "figure"),
[dash.dependencies.Input("image-dropdown", "value")],
)
def update_graph(file):
return joblib.load(os.path.join(image_directory, file))
if __name__ == "__main__":
app.run_server(debug=False)

Related

Export plotly dash to html from callback

I'm trying to export the dynamic dash plot to html. here is my code, when I click download as html after the plot appear, I was only able to download an empty plot, it came back nothing.
What went wrong? thank you
from dash import Dash, dcc, html,Input, Output, callback,dash_table
import plotly.express as px
from base64 import b64encode
import io
app = Dash(__name__)
buffer = io.StringIO()
df=tem1 # tem1 is my own dataset
html_bytes = buffer.getvalue().encode()
encoded = b64encode(html_bytes).decode()
app.layout = html.Div([
html.H4('Test Graph'),
dcc.Graph(id="graph"),
dcc.Checklist(
id="checklist",
options=['A','B','C'],
value=['A','B','C'],
inline=True),
html.A(
html.Button("Download as HTML"),
id="download",
href="data:text/html;base64," + encoded,
download="plotly_graph.html"
)
])
#app.callback(
Output("graph", "figure"),
Input("checklist", "value"))
def update_line_chart(Programs):
mask = df.Program.isin(Programs)
fig = px.line(df[mask],
x="Month", y="Mood", color='Group',text='Module')
return fig
#app.callback(
Output('download','n_clicks'),
[Input('graph','figure')])
def download_html(n):
return n.write_html(buffer)
app.run_server(debug=False,port=8051)
I referred to this post, but it couldn't solve my problem.
Your referred code is my question and I think you should fix it as below:
Add dcc.Download
Save fig to html first
Use dcc.send_file to download html file
I don't have your df so please refer below code:
from dash import Dash, dcc, html,Input, Output, callback,dash_table
import plotly.express as px
from base64 import b64encode
import io
app = Dash(__name__)
df = px.data.gapminder()
app.layout = html.Div([
html.H4('Test Graph'),
dcc.Graph(id="graph",figure=fig),
dcc.Checklist(
id="checklist",
options=['A','B','C'],
value=['A','B','C'],
inline=True),
html.A(
html.Button("Download as HTML"),
id="download"
),
dcc.Download(id='download_1')
])
#app.callback(
Output("graph", "figure"),
Input("checklist", "value"))
def update_line_chart(Programs):
fig = px.scatter(df.query("year==2007"), x="gdpPercap", y="lifeExp",
size="pop", color="continent",
hover_name="country", log_x=True, size_max=60)
fig.write_html("plotly_graph.html")
return fig
#app.callback(
Output('download_1','data'),
Input('download','n_clicks'),prevent_initial_call=True)
def download_html(n):
return dcc.send_file("plotly_graph.html")
app.run_server(debug=False,port=8051)
Hope this help

Dash Graph not updating even when callback function runs

I've been trying to make a live graph with dash. This is my first time trying out dash but I've come across a problem. I write the callback functions to update the graph according to the update intervals. But even though the function is called(which I verify by adding print statements), the graph itself doesn't update.
import os
import dash
from dash import dcc, html
import pandas as pd
import os
from dotenv import load_dotenv
from sqlalchemy import create_engine
import plotly.graph_objs as go
from dash.dependencies import Input, Output
load_dotenv()
purl = os.environ.get('url')
dbname = 'database'
engine = create_engine(purl + dbname)
table_name = 'SANDBTC'
df = pd.read_sql(table_name.lower(), engine)
print(df)
app_name = 'dash-plots'
def _create_fig():
df = pd.read_sql(table_name.lower(), engine)
print(df)
return go.Figure(
data=go.Scatter(
x=df['Time'],
y=df['result']))
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.title = 'Graphs'
app.layout = html.Div(children=[html.H1(id='live-text', style={'textAlign': 'center'}),
dcc.Graph(
id='dash-graph',
animate=True,
figure=_create_fig()
),
dcc.Interval(
id='interval-component',
interval=1000,
n_intervals=0
)
], className="container")
#app.callback(Output('live-text', 'children'),
[Input('interval-component', 'n_intervals')])
def update_text(n):
return html.Span(f'No of times updated: {n}')
#app.callback(Output('dash-graph', 'figure'),
[Input('interval-component', 'n_intervals')])
def update_graph(n):
return _create_fig()
if __name__ == '__main__':
app.run_server(debug=True)
The update text function is working fine but for some reason the update graph function doesnt work. Can anyone point out what error im doing.Thank you for your help.
I removed animate=true and it works

update DataFrame in Dash after text input

I want to update my DataFrame that feeds my graphs in realtime. In all the tutorials I have found, the DataFrame is created before creating the app layout. I want to take the input from the input component with the username_input ID and use that in the get_dataFrame function to create my initial DataFrame which will create the figure which will be used in the graph component.
app = Dash(__name__)
df = get_dataFrame(username_input)
fig = px.line(df, x='end', y="user",color="class")
app.layout = html.Div(children=[
dcc.Input(
id="username_input",
placeholder="username",
type='text'
),
dcc.Graph(
id='example-graph',
figure=fig
),
])
I don't fully understand how to structure the code so that this is possible. In essence I want a user input first and then after the user input all the dash data updates to reflect the new input. Any ideas?
Move your dataframe and figure creation into your callback, then return a new figure after the user's input comes in. Working example:
from dash import Dash, dcc, html, Input, Output, no_update
import pandas as pd
import plotly.express as px
import numpy as np
app = Dash(__name__)
def get_dataFrame(username_input):
data = np.random.rand(10) * len(username_input)
return pd.DataFrame({"end": [*range(10)], "user": data, "class": ["red"] * 10})
fig = px.line()
app.layout = html.Div(
children=[
dcc.Input(id="username_input", placeholder="username", type="text"),
dcc.Graph(id="example-graph", figure=fig),
]
)
#app.callback(
Output("example-graph", "figure"), Input("username_input", "value"),
)
def func(username_input: str):
if username_input:
df = get_dataFrame(username_input)
fig = px.line(df, x="end", y="user", color="class")
return fig
return no_update
if __name__ == "__main__":
app.run(debug=True)

How to use a boolean switch to update a graph in Dash?

I'm new in Dash. I'm trying to use a daq.BooleanSwitch() like an input to callback a graph. I can display a message but I have troubles with the graph.
Does anyone have any advice that can help me?
import dash
from dash.dependencies import Input, Output
import dash_daq as daq
import dash_html_components as html
app = dash.Dash(__name__)
app.layout = html.Div([
html.H1("Here we go"),
daq.BooleanSwitch(id='my_pb', on=False,color="red"),
html.Div(id='power-button-result-1'),
dcc.Graph(id="plot")
])
#app.callback(
Output('power-button-result-1', 'children'),
Input('my_pb', 'on')
)
def update_output(on):
x = '{}'.format(on)
if x == "True":
return "Hi Iḿ using DASH"
#app.callback(
Output('plot', 'figure'),
Input('my_pb', 'on')
)
def figura(on):
x = '{}'.format(on)
if x == "True":
# fig1 = Code to do a nice plot
return fig1
if __name__ == "__main__":
app.run_server(port = 1895)
My DASH output look like this:
I took a look at your code, and a couple changes were necessary:
import dash
import dash_daq as daq
from dash import dcc
from dash import html
from dash.dependencies import Input
from dash.dependencies import Output
app = dash.Dash(__name__)
app.layout = html.Div(
[
html.H1("Here we go"),
daq.BooleanSwitch(id="my_pb", on=False, color="red"),
html.Div(id="power-button-result-1"),
]
)
#app.callback(
Output("power-button-result-1", "children"),
Input("my_pb", "on"),
)
def update_output(on):
x = "{}".format(on)
if x == "True":
return [dcc.Graph(id="plot")]
if __name__ == "__main__":
app.run_server(debug=True)
You were super close - I think you only need one callback. Here, you can see the boolean switch now toggles the display (or not) of the dcc.Graph object. Is this what you were looking for?
↓ (toggle the switch)
If you want the graph to already be displayed, and then updated upon toggling, here's a slightly modified expanded version of same code above to do that:
import dash
import dash_daq as daq
from dash import dcc
from dash import html
from dash import no_update
from dash.dependencies import Input
from dash.dependencies import Output
import plotly.express as px
import pandas as pd
app = dash.Dash(__name__)
app.layout = html.Div(
[
html.H1("Here we go"),
daq.BooleanSwitch(id="my_pb", on=False, color="red"),
html.Div(
[dcc.Graph(id="plot")], id="power-button-result-1"
),
]
)
#app.callback(
Output("power-button-result-1", "children"),
Input("my_pb", "on"),
)
def update_output(on):
df = px.data.iris()
if on:
fig = px.scatter(df, x="sepal_width", y="sepal_length")
dcc.Graph(figure=fig)
return [dcc.Graph(figure=fig)]
else:
fig = px.scatter()
return [dcc.Graph(figure=fig)]
if __name__ == "__main__":
app.run_server(debug=True)
There - that's much better, hopefully helpful?

using dash in python to upload files and plot a bar chart

I try to make an interactive dashboard using dash from plotly. I am a beginner in it therefore I used an example to do it.
The code should upload different data files from a certain folder and plot a histogram based on a certain column. The name of each file looks like "30092017ARB.csv" (date + ARB.csv). The code loops over all file names in the data-folder and print the name of files in a drop-down bottom. After selecting the name of file it should be uploaded and plot a histogram. I wrote the following code:
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
#
from os import listdir
from os.path import isfile, join
import numpy as np
#
mypath='/Users/Python/BeN_/data/'
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]
app = dash.Dash()
app.layout = html.Div([
html.H2("Ausfallsreport"),
html.Div(
[
dcc.Dropdown(
id="dataFH",
options=[{
'label': i,
'value': i
} for i in onlyfiles],
value=" "),
],
style={'width': '25%',
'display': 'inline-block'}),
dcc.Graph(id='Mygraph'),
])
#app.callback(
dash.dependencies.Output('Mygraph', 'figure'),
[dash.dependencies.Input('dataFH', 'value')])
def update_graph(dataFH):
df = pd.read_csv(mypath+dataFH, delimiter=';',encoding='cp1252')
# aggregate
dfagg = df.groupby('Bestand', as_index=False).agg({'MW': 'sum'})
# make strings for x-axis
x=["BE-"+s for s in[str(s) for s in [int(x) for x in dfagg.iloc[:,0].tolist()]]]
y=dfagg.ix[:,1].tolist()
trace = go.Bar(x=x, y=y, name='Declined')
return {
'data': [trace],
'layout':
go.Layout(
title='Customer Order Status for {}'.format(dataFH),
barmode='bar',
yaxis=dict(tickformat=".2%"))
}
if __name__ == '__main__':
app.run_server(debug=True)
I get the following under http://127.0.0.1:8050/ .
The problem is that I do not get any Bar chart. Could someone help me to figure out why.
In case you haven't figured it out yet, the issue is that when a user initially connects, it triggers your callback. And you're setting the initial value of dropdown to
dataFH=" "
which causes
df = pd.read_csv(mypath+dataFH ...
to throw an error because that file doesn't exist.
Different ways to fix this, but one way is to check if mypath+dataFH is a file within your callback and return an empty list for the trace if it's not a file:
def update_graph(dataFH):
if isfile(mypath+dataFH):
df = pd.read_csv(mypath+dataFH, delimiter=';',encoding='cp1252')
# aggregate
dfagg = df.groupby('Bestand', as_index=False).agg({'MW': 'sum'})
# make strings for x-axis
x=["BE-"+s for s in[str(s) for s in [int(x) for x in dfagg.iloc[:,0].tolist()]]]
y=dfagg.ix[:,1].tolist()
trace = go.Bar(x=x, y=y, name='Declined')
else:
trace=[]
return {
'data': [trace],
'layout':
go.Layout(
title='Customer Order Status for {}'.format(dataFH),
barmode='bar',
yaxis=dict(tickformat=".2%"))
}

Categories

Resources