Print output based on user input in dash (or shiny) - python

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.

Related

Is there a way to combine a loading data callback and a recurrent updating data callback with dash-python?

I am working on a dashboard with dash-plotly and I have created two different callbacks to handle data storage. The first callback loads initial data based on a dropdown
#app.callback(Output('battery-data','data'),
[Input('battery-dropdown', 'value')],
[State('battery-data','data')]
)
def load_data(battery_name):
example_data = utils_new.load_dump_from_mongo(collection,battery_name)
example_pd = pd.DataFrame(example_data)
print(example_pd.head())
example_pd = example_pd.drop('_id',axis=1)
return(example_pd.to_json(date_format='iso', orient='split'))
While the second gets as input the initial data and then updates it recurrently
#app.callback(Output('battery-data', 'data'),
[Input('interval-component', 'n_intervals'),
Input('battery-data','data'),
Input('battery-dropdown', 'value']
) [State('battery-data', 'data')])
def update_data(n, battery_json, battery_name, time_range):
example_old_data = pd.read_json(battery_json, orient='split')
example_old_data['Time'] = pd.to_datetime(example_old_data['Time']).apply(lambda x: x.replace(tzinfo=None))
last_record_time = parser.parse(str(example_old_data['Time'].tail(1).item()))
# load last 10 seconds of data as a list of records
update_data = utils_new.update_data_from_mongo(collection,battery_name,last_record_time)
update_pd = pd.DataFrame(update_data)
print('SIZE OF THE UPDATE', len(update_pd))
update_pd.drop("_id", axis=1, inplace=True)
# add update data
len_update = len(update_pd)
example_new_data = example_old_data.append(update_pd,ignore_index=True)
example_new_data.drop(example_new_data.head(len_update).index,inplace=True)
example_new_data = example_new_data.reset_index(drop=True)
# filter for battery id
example_new_data_battery = example_new_data[example_new_data['Battery_ID'] == battery_name]
return(example_new_data.to_json(date_format='iso', orient='split'))
app.layout = dbc.Container([
dbc.Row([
html.H1(children='Battery monitoring'),
html.Div(children='''
This dashboard shows battery state
'''),
html.Br(style={'marginBottom': '10px'})
]),
dbc.Row([
dbc.Col([
dbc.Row([batteries_drop()]),
],width=6),
dbc.Col([
dbc.Row(id='card-anomaly'),
], width=6)]),
dcc.Store(id='battery-data')
dcc.Interval(id='interval-component',
interval=10*1000,
n_intervals=0)
])
However, in this way, it doesn't work because I use the same ID for two different callbacks. Do you know if there is a way to make it work? Or if you know a strategy to address this? Initially, I would like to load only the data from a single battery to avoid crashing the dashboard and then I need to get the data updated every 10 secs.
Thanks for any suggestion or help!
You can fix this issue by using the great dash-extensions library.
This library has some modules that modify the Dash and allow us to extend it to do more than the standard Plotly does. By using a module called MultiplexerTransform combined with DashProxy you will be able to use the same ID in different callback outputs;
Below is a code snippet which does exactly what you did, you just need to adjust it to your context.
from dash.exceptions import PreventUpdate
from dash_extensions.enrich import Output, DashProxy, Input, MultiplexerTransform, html
app = DashProxy(transforms=[MultiplexerTransform()])
app.layout = html.Div([
html.Button("Left", id="left"),
html.Button("Right", id="right"),
html.Div(id="log")
])
#app.callback(Output("log", "children"), Input("left", "n_clicks"))
def left(n_clicks):
if not n_clicks:
raise PreventUpdate()
return "left"
#app.callback(Output("log", "children"), Input("right", "n_clicks"))
def right(n_clicks):
if not n_clicks:
raise PreventUpdate()
return "right"
if __name__ == "__main__":
app.run_server()
To read more about this module and library you can read: dash-extensions
Regards,
Leonardo

Python Plotly Dash: Automatically iterate through slider, 'PLAY BUTTON'

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

The input argument `input.value` must be a list or tuple of `dash.dependencies.Input`s. dash

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)

How to update chained dropdown value in Dash dcc?

In dash, how do I update the values of one dropdown into another checklist or slider?
In the below code, I am selecting one value from a dropdown which should update checklist values based on the selected value from the dropdown. Here I am partially successful in taking value from the dropdown but it's accumulating with older selected values in the checklist.
Please find below part of the code.
import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import dash_table
import pandas as pd
from dash.exceptions import PreventUpdate
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/solar.csv')
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.config['suppress_callback_exceptions'] = True
app.layout = html.Div([
dash_table.DataTable(
id='datatable-upload-container',
columns=[{"name": i, "id": i} for i in df.columns],
data=df.to_dict('records'),
),
html.Div(dcc.Dropdown(
id='data_selector1',
options=[
{'label': '', 'value': ''}
],
value=[]
)
),
html.Br(),
html.Div([
html.Div(id='numerical-slider'),
# this is a hack: include a hidden dcc component so that
# dash registers and serve's this component's JS and CSS
# libraries
dcc.Input(style={'display': 'none'})
])
])
#app.callback(Output('data_selector1', 'options'),
[Input('datatable-upload-container', 'data')])
def update_dropdown(rows):
print('updating menus')
numerical_col = [i for i in df.columns if df[i].dtypes != "object"]
col_labels=[{'label' :k, 'value' :k} for k in numerical_col]
return col_labels
#app.callback(Output('numerical-slider','children'),
[Input('data_selector1', 'value'),
Input('datatable-upload-container', 'data')])
def explanatory_cat_slider(value, rows):
if value:
categories, intervals = pd.cut(df[value], 3, retbins=True)
return html.Div(html.Label([value,
dcc.RangeSlider(id='numerical-slider',
min=min(intervals),
max=max(intervals),
step=None,
marks={str(val): str(round(val,2)) for val in intervals},
value = [intervals[0],intervals[-1]]
)
],style={'width': '50%', 'display': 'inline-block', 'textAlign': 'left'})
)
else:
return []
if __name__ == '__main__':
app.run_server(debug=False)
updated code...
I am getting an issue with explanatory_cat_slider, it's not getting updated with new selected values.
In the first image I can select one value of dropdown which automatically shows slider of that value
In the second image sliders getting accumulated on upon other. How do I rectify this issue?
In the last image, how it becomes slider overlapped
The code you posted is incomplete, because you have the Input ID data_selector and the ID datatable-upload-container in your callback, but they do not exist in your layout. I can see that the callback will have a problem with its Output as well, because it's trying to update the children of categorical-checklist with an element that contains an ID of the same. This would result in non-unique IDs in your layout, which will break.
I may be able to help more with the complete code but, essentially, you have the right idea to check if value: and run your code inside that block. Make sure you do not let the callback silently end, because that will return None and cause trouble for you. You should include a return [] or return '' at the end, or inside an else: block to protect against that, and keep the children component valid, even if only with an empty value.
You should also include the dcc.Checklist in your initial layout. Give it options=[] to start with and have your callback update its options prop. That should work but, if there are still problems, update your posted code and I'll take another look.

How to get accurate timing interval by using plotly dash?

I would like to create a stopwatch using python plotly dash and the following is my code. Here I use the element dcc.Interval to update timing information every one second, but unfortunately, I found that it is not accurate when I used my iPhone built-in stopwatch to test its accuracy. Any suggestion on how how to correct my code? Thanks :)
# import modules
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
# define functions
def sec_transform(i):
m, s = divmod(i, 60)
msg = '%02i:%02i' % (m, s)
return msg
# dashboard layout
app = dash.Dash()
app.layout = html.Div([
# display time elapsed
html.H1(id='live-update-text'),
# for live updating
dcc.Interval(
id='interval-component',
interval=1000, # 1000 milliseconds
n_intervals=0
)
])
# call back function
#app.callback(Output('live-update-text', 'children'),
[Input('interval-component', 'n_intervals')])
def update_layout(n):
msg = sec_transform(n)
return msg
if __name__ == '__main__':
app.run_server()

Categories

Resources