I would like to include a component in my Dash App, that automatically goes through all of the values of a slider. Basically a ‘play button’. As the consequence the callback with the slider value as input should fire and update the output element.
Does anyone know how to do it?
Here is some sample code from the official docs:
from dash import Dash, dcc, html, Input, Output
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
dcc.Slider(0, 20, 5,
value=10,
id='my-slider'
),
html.Div(id='slider-output-container')
])
#app.callback(
Output('slider-output-container', 'children'),
Input('my-slider', 'value'))
def update_output(value):
return 'You have selected "{}"'.format(value)
if __name__ == '__main__':
app.run_server(debug=True)
I am inexperienced in Dash, so I looked into it and found a case study answer on the plotly communication site. I have modified it to meet your requirements. As far as I understand it, you need two callbacks, one to start and stop the button click and one to return the value obtained from the animation and the new slider value. Note that it does not have a function to automatically stop when the maximum value is reached.
from dash import Dash, dcc, html, Input, Output, State
from jupyter_dash import JupyterDash # Add for my environment
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
#app = Dash(__name__, external_stylesheets=external_stylesheets)
app = JupyterDash(__name__, external_stylesheets=external_stylesheets) # Add for my environment
step_num = 5
app.layout = html.Div([
dcc.Interval(id="animate", disabled=True),
dcc.Slider(min=0,
max=50,
step=5,
value=0,
id='my-slider'
),
html.Button("Play/Stop", id="play"),
html.Div(id='slider-output-container')
])
#app.callback(
Output('slider-output-container', 'children'),
Output("my-slider", "value"),
Input('animate', 'n_intervals'),
State('my-slider', 'value'),
prevent_initial_call=True,
)
def update_output(n, selected_value):
selected_value = (n%11)*step_num
return 'You have selected "{}"'.format(selected_value), selected_value
#app.callback(
Output("animate", "disabled"),
Input("play", "n_clicks"),
State("animate", "disabled"),
)
def toggle(n, playing):
if n:
return not playing
return playing
if __name__ == '__main__':
app.run_server(debug=True, port=8051, mode='inline') #Add for my environment
Related
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
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)
i'm trying to learn dash i'm at the third tutorial but it raise this error whenever i run the file(python app.py)
dash.exceptions.IncorrectTypeException: The input argument input.value must be a list or tuple of dash.dependencies.Inputs.
this is the code i'm running :
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
html.H6("Change the value in the text box to see callbacks in action!"),
html.Div(["Input: ",
dcc.Input(id='input', value='initial value', type='text')]),
html.Br(),
html.Div(id='output'),
])
#app.callback(
Output(component_id='output', component_property='children'),
Input(component_id='input', component_property='value')
)
def update_output_div(input_value):
return 'Output: {}'.format(input_value)
if __name__ == '__main__':
app.run_server(debug=True)
please what is wrong with the code?! even i tried to copy and paste the code still raise the same error
thank you ..
versions
python = 3.6
dash=1.7.0
dash-core-components=1.6.0
dash-html-components=1.0.2
You need to wrap your inputs in a list, like this:
#app.callback(
Output(component_id='output', component_property='children'),
[Input(component_id='input', component_property='value')]
)
def update_output_div(input_value):
return 'Output: {}'.format(input_value)
I try to learn Python Dash to visualize some data. I worked on the Plotly Example with multiple Buttons:
import dash
from dash.dependencies import Input, Output
import dash_html_components as html
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
html.Button('Button 1', id='btn-nclicks-1', n_clicks=0),
html.Button('Button 2', id='btn-nclicks-2', n_clicks=0),
html.Button('Button 3', id='btn-nclicks-3', n_clicks=0),
html.Div(id='container-button-timestamp')
])
#app.callback(Output('container-button-timestamp', 'children'),
Input('btn-nclicks-1', 'n_clicks'),
Input('btn-nclicks-2', 'n_clicks'),
Input('btn-nclicks-3', 'n_clicks'))
def displayClick(btn1, btn2, btn3):
changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0]
if 'btn-nclicks-1' in changed_id:
msg = 'Button 1 was most recently clicked'
elif 'btn-nclicks-2' in changed_id:
msg = 'Button 2 was most recently clicked'
elif 'btn-nclicks-3' in changed_id:
msg = 'Button 3 was most recently clicked'
else:
msg = 'None of the buttons have been clicked yet'
return html.Div(msg)
if __name__ == '__main__':
app.run_server(debug=True)
The code displays which button was clicked recently. I want to ask if it is possible to put this in a loop, so that I can loop over i numbers of buttons, because it is pretty much work if I want to use 50 buttons or so.
Instead of
html.Button('Button 1', id='btn-nclicks-1', n_clicks=0),
html.Button('Button 2', id='btn-nclicks-2', n_clicks=0),
html.Button('Button 3', id='btn-nclicks-3', n_clicks=0),
something like:
for i in range(number_buttons):
html.Button('Button i', id='btn-nclicks-i', n_clicks=0)
#app.callback(
Input('btn-nclicks-i', 'n_clicks')
)
I'd appreciate some links to tutorials or examples with Dash Callbacks.
The trickiest part about this is adding all of the buttons created in your loop as Input to your callback, but you can do that using pattern matching callbacks (see dash docs). Here is a small example, using the code you provided as basis but using 10 buttons via a loop:
from dash.dependencies import Input, Output, ALL
import dash_html_components as html
app = dash.Dash(__name__)
btnlst = [html.Button(
'Button {}'.format(i),
id={
'type' : 'mybuttons',
'index' : i,
}
)
for i in range(10)]
app.layout = html.Div(btnlst + [
html.Div(id='btn-out-container'),
])
#app.callback(Output('btn-out-container', 'children'),
Input({'type':'mybuttons', 'index':ALL}, 'n_clicks'))
def display_click(nclicks):
changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0]
if changed_id == '.':
msg = 'None of the buttons have been clicked yet'
else:
# do additional parsing of changed_id here as necessary
msg = 'Changed property: {}'.format(changed_id)
return html.Div(msg)
if __name__ == '__main__':
app.run_server(debug=True)
Important things to note:
I created the list of buttons btnlst beforehand and added it to the first argument of the other html.Div component. That technique is universal and does not only work with pattern matching callbacks.
Note the form of the id property of each button, which is needed to use them in a pattern matching callback. The type of the id can be any string, but if you are going to use multiple groups like this, it's advisable to not mix their names.
The changed_id used in display_clicks has a pretty custom format, as you can see when looking at the output. You'll propably need to do some extra parsing on it, especially if you have any other Input besides just the list of buttons.
I would like to get inputs x and y from a user's input to a text box.
if x + 2*y 3*x*y > 100:
print('Blurb 1')
else:
print('Blurb 2')
This seems to be convoluted in dash with callbacks, etc, even though it could be self-contained and quite simple. Is there a simple way to do this within a web app? Other resources I found seem to assume a much more complex goal, so I am curious as to how much the code can be pared.
I don't think you can accomplish your task without defining a callback, but the code to get the work done is very short and simple. A possible solution could be the following:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash()
app.layout = html.Div([
html.H1("Simple input example"),
dcc.Input(
id='input-x',
placeholder='Insert x value',
type='number',
value='',
),
dcc.Input(
id='input-y',
placeholder='Insert y value',
type='number',
value='',
),
html.Br(),
html.Br(),
html.Div(id='result')
])
#app.callback(
Output('result', 'children'),
[Input('input-x', 'value'),
Input('input-y', 'value')]
)
def update_result(x, y):
return "The sum is: {}".format(x + y)
if __name__ == '__main__':
app.run_server(host='0.0.0.0', debug=True, port=50800)
This is what you get:
The value of the sum is updated every time one of the two input boxes changes its values.