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
Related
I'm trying to set my Dash app to automatically pull the latest data from a .csv file used in the data frame with dcc.Interval. The error code isn't providing a detailed explanation and also doesn't always appear. I've tried this with both a button and a set 6 sec interval, but the result seems to be the same. The Dash app runs fine at first and refreshes fine a few times, then error starts occurring:
Callback error updating graph.figure
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
app = dash.Dash(__name__)
server = app.server
df = pd.read_csv('example.csv', encoding="WINDOWS-1252")
app.layout = html.Div([
dcc.Graph(id='graph'),
dcc.Interval(
id='interval-component',
interval=1*6000,
n_intervals=0
)
])
#app.callback(
Output('graph','figure'),
[Input('interval-component', 'n_intervals')]
)
def update_df(n):
updated_df = pd.read_csv('example.csv', encoding="WINDOWS-1252")
fig = px.scatter(updated_df, x='Date', y='Deviation', height=800)
fig.update_layout(
yaxis_tickformat = '.0%',
)
fig.update_xaxes(
rangeslider_visible=True,
rangeselector=dict(
)
)
return fig
if __name__ == '__main__':
app.run_server(debug=True)
I think your issue must have something to do with your file specifically, because the following code based exactly off as you provide (with the exception of generation of random matching-df timeseries data), works perfectly updating with an interval of every 6 seconds:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
import numpy as np
np.random.seed(2019)
def get_random_deviation_ts_df(N=100):
rng = pd.date_range("2019-01-01", freq="D", periods=N)
df = pd.DataFrame(np.random.rand(N, 1), columns=["Deviation"], index=rng)
df["Date"] = df.index
return df
app = dash.Dash(__name__)
server = app.server
# df = pd.read_csv('example.csv', encoding="WINDOWS-1252")
app.layout = html.Div(
[
dcc.Graph(id="graph"),
dcc.Interval(
id="interval-component", interval=1 * 6000, n_intervals=0
),
]
)
#app.callback(
Output("graph", "figure"), [Input("interval-component", "n_intervals")]
)
def update_df(n):
updated_df = (
get_random_deviation_ts_df()
) # pd.read_csv('example.csv', encoding="WINDOWS-1252")
fig = px.scatter(updated_df, x="Date", y="Deviation", height=800)
fig.update_layout(yaxis_tickformat=".0%",)
fig.update_xaxes(rangeslider_visible=True, rangeselector=dict())
return fig
if __name__ == "__main__":
app.run_server(debug=True)
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?
I recently wrote a dash program
it is refreshing number of records and refreshes or redraws the fig
the problem is when I do filter over 1 or multiple legends it won't show any of the points
but when you hover over invisible points it shows the data of the point
my code:
from threading import Event
import dash
from dash import dcc, Input, Output
from dash import html
from dash.dcc.Interval import Interval
import plotly.express as px
import pandas as pd
import sqlalchemy
app = dash.Dash(__name__)
# assume you have a "long-form" data frame
# see https://plotly.com/python/px-arguments/ for more options
connection = sqlalchemy.create_engine('mysql+pymysql://*:*#localhost:*')
df = pd.read_sql_table('rawdata_clean', connection)
fig = px.scatter(df, x="Size", y="Price", color="Neighbourhood_Per")
index = df.index
app.layout = html.Div(children=[
html.H1(id='Numberofrecords', children= len(index)),
dcc.Interval(id='up-Numberofrecords', interval=3000, n_intervals=0),
html.Div(children='''
Dash: A web application framework for Python.
'''),
dcc.Graph(
id='grph',
animate=True
),
dcc.Interval(id='up-graph', interval=3000, n_intervals=0)
])
#app.callback(Output('grph', 'figure'),
Input('up-graph', 'n_intervals'))
def update_graph (n):
df = pd.read_sql_table('rawdata_clean', connection)
fig = px.scatter(df, x="Size", y="Price", color="Neighbourhood_Per")
return fig
#app.callback(Output('Numberofrecords', 'children'),
Input('up-Numberofrecords', 'n_intervals'))
def up_Numberofrecords (n):
df = pd.read_sql_table('rawdata_clean', connection)
index = df.index
print('up_Numberofrecords')
return len(index)
if __name__ == '__main__':
app.run_server(debug=True, port=9876)
is there any problems with this code?
i'm new to dash and plotly :D
the problem was :
animate=True
IDK what this code does but by deleting it, it get to work
Is it possible to have a text field at the bottom of a graph in dash that displays the text for the point they are on (showing hover data as plain text). So the text box will be able to make changes when users hover over a certain point. I have defined a dcc.Graph component and the app layout but am not sure how to define the callback function for the hoverdata.
I have used the below code to define dcc.Graph and app.layout
fig = go.Figure(data=plot_data, layout=plot_layout)
app.layout = html.Div([
dcc.Graph(figure=fig),
html.Div([
dcc.Markdown(id='mpg-metrics')
],style={'width':'20%','display':'inline-block'})
])
Any help with the callback will be great. thanks in advance
Yes, that's very possible! Since you haven't provided a complete description of your setup, I've put together a minimal example that draws on elements from dash.plotly.com/interactive-graphing and https://community.plotly.com/: Use Hover Trace As Input for Callback that among other things describes the use of hover data in callbacks. The code snippet below will produce the following app for JupyterDash. If you'd like to run a standard dash app, just rewrite it following these steps.
The solution I've put together should do exactly what you're aiming for. Every time you hover over a point on one of the lines in the figure in the dcc.Graph component, a set of details about the trace is displayed in the html.Pre component under it, such as x and y values. Try it out and let me know how it works out for you!
App 1:
If you'd like to retrieve only certain elements of the output, you can subset the output like this:
json.dumps({'Date:':hoverData['points'][0]['x'],
'Value:':hoverData['points'][0]['y']}, indent = 2)
App 2:
Complete code for JupyterDash, App1
import json
from textwrap import dedent as d
import pandas as pd
import plotly.graph_objects as go
import numpy as np
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
from dash.dependencies import Input, Output
from jupyter_dash import JupyterDash
# app info
app = JupyterDash(__name__)
styles = {
'pre': {
'border': 'thin lightgrey solid',
'overflowX': 'scroll'
}
}
# data and basic figure
x = np.arange(20)+10
fig = go.Figure(data=go.Scatter(x=x, y=x**2, mode = 'lines+markers'))
fig.add_traces(go.Scatter(x=x, y=x**2.2, mode = 'lines+markers'))
app.layout = html.Div([
dcc.Graph(
id='basic-interactions',
figure=fig,
),
html.Div(className='row', children=[
html.Div([
dcc.Markdown(d("""
Click on points in the graph.
""")),
html.Pre(id='hover-data', style=styles['pre']),
], className='three columns'),
])
])
#app.callback(
Output('hover-data', 'children'),
[Input('basic-interactions', 'hoverData')])
def display_hover_data(hoverData):
return json.dumps(hoverData, indent=2)
app.run_server(mode='external', port = 8070, dev_tools_ui=True,
dev_tools_hot_reload =True, threaded=True)
Complete code for JupyterDash, App2
import json
from textwrap import dedent as d
import pandas as pd
import plotly.graph_objects as go
import numpy as np
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
from dash.dependencies import Input, Output
from jupyter_dash import JupyterDash
# app info
app = JupyterDash(__name__)
styles = {
'pre': {
'border': 'thin lightgrey solid',
'overflowX': 'scroll'
}
}
# data and basic figure
y = np.arange(100)+10
x = pd.date_range(start='1/1/2021', periods=len(y))
fig = go.Figure(data=go.Scatter(x=x, y=y**2, mode = 'lines+markers'))
fig.add_traces(go.Scatter(x=x, y=y**2.2, mode = 'lines+markers'))
app.layout = html.Div([
dcc.Graph(
id='basic-interactions',
figure=fig,
),
html.Div(className='row', children=[
html.Div([
dcc.Markdown(d("""
Click on points in the graph.
""")),
html.Pre(id='hover-data', style=styles['pre']),
], className='three columns'),
])
])
#app.callback(
Output('hover-data', 'children'),
[Input('basic-interactions', 'hoverData')])
def display_hover_data(hoverData):
try:
return json.dumps({'Date:':hoverData['points'][0]['x'],
'Value:':hoverData['points'][0]['y']}, indent = 2)
except:
return None
app.run_server(mode='external', port = 8070, dev_tools_ui=True,
dev_tools_hot_reload =True, threaded=True)
When I run the code i get the graph but the graph is not getting updated i am calling the data from my sql laptop sql management studio.
Kindly let me know what needs to be done the X axis contains date and time and Y axis contains data in numeric form which is getting updated automatically
Code:
import pandas as pd
import pyodbc
import numpy as np
server ='LAPTOP-OO3V36UA\SQLEXPRESS'
db='addy'
conn=pyodbc.connect('DRIVER={SQL Server}; SERVER=' +server + ';DATABASE=' + db +
';Trusted_connection=yes')
sql="""
SELECT * FROM Summry
"""
df=pd.read_sql(sql ,conn)
import dash
from dash.dependencies import Output, Input
import dash_core_components as dcc
import dash_html_components as html
from random import random
import plotly
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Graph(id='live-update-graph-scatter', animate=True),
dcc.Interval(
id='interval-component',
interval=1*1000
)
])
#app.callback(Output('live-update-graph-scatter', 'figure'),
[Input('interval-component', 'interval')])
def update_graph_scatter():
df=pd.read_sql(sql ,conn)
trace1=go.Scatter(
y=df['ACL'],
x = df['DateandnTime'],
mode='lines',
name='ACL'
)
layout = go.Layout(
title='Daily Monitoring'
)
return {'data': trace1, 'layout': layout}
if __name__ == '__main__':
app.run_server()
You've set your callback's input to
Input('interval-component', 'interval')
But you want
Input('interval-component', 'n_intervals')
The interval property sets how frequently n_intervals gets updated. The change in n_intervals is what can be used to trigger the callback.
Here's the documentation: https://dash.plotly.com/dash-core-components/interval