how to delete value of one dropdown when the other dropdown value is selected and vice versa? - plotly-dash

I have two dropdown menu using dcc.Dropdown(). If I select one a value from a dropdown menu, I'd like to de-select anything on the other dropdown menu and Vice Versa.
here is what I did to define two callbacks, with each callback to set the value of the other dropdown value to empty when one dropdown value is selected. I got an error of circular dependency error. Thanks for your help.
for example, I have two dropdown, dts-filename-dropdown and dts-longterm-filename-dropdown.
#app.callback(
[
Output("dts-filename-dropdown", "value")
],
[
Input("dts-longterm-filename-dropdown", "value")
],
)
def close_tfo_dts_filename(dts_longterm_filename):
if dts_longterm_filename is not None:
dts_filename=[]
return dts_filename
else:
raise dash.exceptions.PreventUpdate
#app.callback(
[
Output("dts-longterm-filename-dropdown", "value")
],
[
Input("dts-filename-dropdown", "value")
],
)
def close_longterm_dts_filename(dts_longterm_filename):
if dts_filename is not None:
dts_longterm_filename=[]
return dts_longterm_filename
else:
raise dash.exceptions.PreventUpdate

You can use circular callbacks where the inputs and outputs are identical. Here is an example for your case:
#app.callback(
[
Output("dts-longterm-filename-dropdown", "value"),
Output("dts-filename-dropdown", "value")
],
[
Input("dts-longterm-filename-dropdown", "value"),
Input("dts-filename-dropdown", "value"),
],
)
def close_longterm_dts_filename(dts_longterm_filename, dts_filename):
ctx = dash.callback_context
if not ctx.triggered:
raise PreventUpdate
else:
button_id = ctx.triggered[0]['prop_id'].split('.')[0]
if button_id == "dts-filename-dropdown":
return [], dts_filename
else:
return dts_longterm_filename, []

Related

dcc.Store is expecting a list or a tuple

I am getting the following error when trying to store a dictionary in dcc.Store. Doesn't it take a dict to store data?
dash._grouping.SchemaTypeValidationError: Schema: [<Output `user_status_check.data`>]
Path: ()
Expected type: (<class 'tuple'>, <class 'list'>)
Received value of type <class 'dict'>:
{'user_status': [{'status': 'update', 'user_id': None, 'screen_name': 'mfa_russia'}]}
here's the layout
layout = html.Div([
tw_user_navbar,
popup_row,
dcc.Store(id='user_data_values'),
dcc.Store(id='user_status_check', storage_type='session', clear_data =True),
and the callback, not sure how helpful it would be in answering the question
#app.callback(
[
Output('user_status_check', 'data')
],
[
Input('screen_name', 'value'),
Input('user_id', 'value'),
]
)
def check_user_status(input_screen_name, input_user_id):
if input_screen_name or input_user_id:
# check if the user exists in the db
from tw_mod.load.pg_db_functions import db_user_check
user_in_db = db_user_check(screen_name=input_screen_name, user_id=input_user_id)
# if so check if the user information is up-to-date
if user_in_db:
from tw_mod.tw_procssing import check_account_status
account_status = check_account_status(user_id=input_user_id, screen_name=input_screen_name)
if account_status:
return {'user_status':[{'status':'no_update','user_id':input_user_id, 'screen_name':input_screen_name}]}
else:
return {'user_status':[{'status':'update','user_id':input_user_id,
else:
from dash.exceptions import PreventUpdate
raise PreventUpdate

Plotly Dashboard: How to make a simple dropdown to display figures?

My figures are saved in a dictionary and they are accessible, but I am lost on what to put on options and value.
app = JupyterDash(__name__)
app.layout = html.Div([
dcc.Dropdown(
id='launch-data',
options=[
{"label":"All","value":"launch_tot_fig"}],
value=launch_tot_fig
),
html.Div(id="dd-output-container")]
)
#app.callback(Output('dd-output-container', 'children'),Input('launch-data', 'value'))
def update_output(value):
return 'You have selected "{}"'.format(value)
if __name__ == '__main__':
app.run_server(debug = True)
I also have the figure launch_tot_fig that is a pie chart for the launch sites. So that is to show when the input is "All".
The Dictionary is launchmass with the SPACEX launchsites as keys
If you want to show a graph you need to add a graph component to your layout and then use a callback to update it given the dropdown value. You should have something like this :
app.layout = html.Div([
dcc.Dropdown(
id='launch-data',
options=[
{"label": "All", "value": "launch_tot_fig"}, {"label": "Other", "value": "Other"}],
value="Other"
),
html.Div(id="dd-output-container"),
dcc.Graph(id='my-fig')
]
)
And the callback should look like this :
#app.callback(Output('my-fig', 'figure'),
Input('launch-data', 'value'))
def update_output(value):
fig = px.bar()
if value == 'launch_tot_fig':
fig = dictionnary_with_graphs['launch_tot_fig']
return fig

output of a callback as input of another callback, second callback run twice

The dashboard include a dropdown, a table and a graph.
By selecting a item from dropdown, some rows of the table is shown and figure plot the data in the table.
I have two callback,
at the first one:
input : dropdown
output: table
second one:
input: table
output: figure
So the output of first callback is input of the second one.
The following code output look like this:
import dash
import dash_table
import pandas as pd
from copy import deepcopy
import plotly.graph_objects as go
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
data = pd.DataFrame({"a": ["a1", "a2"],
"b": [1, 2]})
app = dash.Dash(
__name__,
external_stylesheets=[dbc.themes.BOOTSTRAP],
prevent_initial_callbacks=True,
)
app.layout = dbc.Container(
[
dbc.Row(dbc.Col([dcc.Dropdown(
id='dropdown1',
options=[
{'label': '1', 'value': 1},
{'label': '2', 'value': 2}
],
value=1)])),
dbc.Row(
dbc.Col([
dash_table.DataTable(
id="datatable",
columns=[dict(id=i,
name=j,
)
for i, j in zip(
["a", "b"],
["a", "b"],
)],
data=data.loc[data['a'] ==
"a1"].to_dict("records"),
sort_mode="single",
)
])),
dbc.Row([dbc.Col([html.Div(
children=dcc.Graph(id="graph"), className="card")
])]),
], fluid=True,
)
########################################################
#app.callback(
Output("datatable", "data"),
[Input("dropdown1", "value")],
prevent_initial_call=True
)
def update_current_table(value):
idx = int(value)
print(idx)
if idx == 1:
df = (data.loc[data["a"] == "a1"])
return df.to_dict("records")
else:
df = deepcopy(data.loc[data["a"] == "a2"])
return df.to_dict("records")
########################################################
# app.callback(
Output('graph', 'figure'),
[Input("datatable", "derived_virtual_data"),
Input("dropdown1", "value")
],
prevent_initial_call=True
)
def update_figure(table, value):
df = pd.DataFrame(table)
print(df)
fig = go.Figure()
return fig
if __name__ == "__main__":
app.run_server(debug=True, port=8000)
The problem here is callback run twice:
a b
0 a1 1
a b
0 a2 2
and for the first time print the previous values of the table
This cause error in the main code that I am working on.
How to prevent dash from runnig callback twice?
I found some other questions complaining about running the callback twic, but I could not found a proper solution for that.
The problem is that you have two inputs for the callback that's running twice:
# app.callback(
Output('graph', 'figure'),
[Input("datatable", "derived_virtual_data"),
Input("dropdown1", "value")
],
prevent_initial_call=True
)
def update_figure(table, value):
The dropdown changes, and triggers this callback, but it also triggers the table to update. The updated table causes the derived_virtual_datato trigger this callback again. You can fix this by making the dropdown value a State instead, like this:
# app.callback(
Output('graph', 'figure'),
[Input("datatable", "derived_virtual_data")],
[State("dropdown1", "value"),]
prevent_initial_call=True
)
def update_figure(table, value):
Edit:
On another read through, you don't even use the value from the dropdown in the second input. Just removing it entirely will also work:
# app.callback(
Output('graph', 'figure'),
[Input("datatable", "derived_virtual_data")],
prevent_initial_call=True
)
def update_figure(table):

Dash drop down menu graph

I'm attempting to implement a live-update graph that is only displayed if the user selected it from the drop down menu. I've made a callback with input from "intervals" and from the dropdown menu "oxygen". I thought if "value" is "0" then no chart has been selected and I could return "null"(???), and if 'value' = '1', then the graph would update. Is this possible? or is my approach incorrect?
dcc.Graph(id='live-graph2', animate=False),
dcc.Interval(
id='graph-update',
interval=10000,
n_intervals=0
)),
dbc.Col(html.Div([
dcc.Dropdown(
id='oxygen',
options=[{'label': s, 'value': s}
for s in main_graph.keys()],
value=[],
multi=True),
#app.callback(
dash.dependencies.Output('live-graph2', 'figure'),
[dash.dependencies.Input('oxygen', 'value'),
dash.dependencies.Input('graph-update', 'n_intervals')],
)
def update_graph_scatter_2(n,value):
if value == 0:
....
else:
data = {}
I would approach the problem differently.
If you don't want to display the graph at all when no dropdown option is selected then the Graph component doesn't need to be in the layout by default.
Instead you could create a container component that your Graph component is appended to dynamically based on the option values of your Dropdown component.
Below is a simplified example using sample data, adjust per your requirements:
import dash
import dash_html_components as html
import dash_core_components as dcc
import plotly.express as px
import dash_bootstrap_components as dbc
df = px.data.iris()
app = dash.Dash(__name__)
app.layout = html.Div(
[
dcc.Interval(id="graph-update", interval=10000, n_intervals=0),
html.Div(id="graph-container"),
dbc.Col(
html.Div(
[
dcc.Dropdown(
id="oxygen",
options=[{"label": s, "value": s} for s in [1, 2, 3]],
value=[],
multi=True,
)
]
)
),
]
)
#app.callback(
dash.dependencies.Output("graph-container", "children"),
[
dash.dependencies.Input("oxygen", "value"),
dash.dependencies.Input("graph-update", "n_intervals"),
],
)
def update_graph_scatter_2(value, n):
if value:
# Change the line below to dynamically create the figure based on value
fig = px.scatter(df, x="sepal_width", y="sepal_length")
return dcc.Graph(id="live-graph2", figure=fig)
return html.Div()

Dash plotly Datatable column filtering or cropping

I have implemented a live-update datatable to correspond with a live-update graph. Functionally, both work very well. I do have a problem with filtering the datatable to include certain columns and exclude others. For ex. If the graph is zoomed in for certain x-value (09:00-10:00), is there any way I can also crop the corresponding datatable to represent columns from that same value? Perhaps add a button with a callback that deletes specific column ids? Is there a way to delete specific 'column' 'id' inputs through python with out using the GUI? As of now, I can only manually delete individual columns which is very tedious given the amount of columns. Thank you. I hope this question is not too open-ended.
table_contents = ['Propofol/Remi # 6.5 ug/ml', 'Fentanyl (ug)', 'Propofol (mg)', 'Remi (ug)',
'Ketorolac (mg)']
html.Div([dash_table.DataTable(
id='editing-columns',
columns=[{
'name': 'Parameter',
'id': 'column1',
'deletable': True,
'renamable': True
}],
data=[
{'column1': j}
for j in table_contents
],
editable=True,
)]),
# The callback stores the previous length of the csv file in dcc.store and appends new columns if new csv data uploaded
#app.callback(Output('editing-columns', 'columns'),
[Input('graph-update', 'n_intervals')],
[State('editing-columns', 'columns')],
[State('mystore', 'data')])
def update_columns(n, btn, existing_columns, data):
with open('temp.csv', 'r') as rf:
reader = csv.reader(rf)
for a in reader:
existing_columns.append({
'id': a[3], 'name': a[3],
'renamable': True, 'deletable': True
})
return existing_columns, html.Div('Program running')
else:
check_length = []
de_serialized = json.loads(data)
with open('temp.csv', 'r') as rf:
reader = csv.reader(rf)
for a in reader:
check_length.append(a[3])
if len(check_length) == 0:
return existing_columns, html.Div('Program running')
elif len(check_length) > len(de_serialized):
existing_columns.append({
'id': check_length[-1], 'name': check_length[-1],
'renamable': True, 'deletable': True
})
return existing_columns, html.Div('Program running')
else:
return existing_columns, html.Div('Program running')
#The graph is a bar and scatter graph that is updated with x,y values derived from the same csv as the datatable.
#app.callback(
dash.dependencies.Output('live-graph', 'figure'),
[dash.dependencies.Input('graph-update-BP', 'n_intervals')],
)
def update_graph_scatter_1(btn, n):
trace = []
trace2 = []
blood_pressure = []
hr = []
with open('temp.csv', 'r') as rf:
reader_2 = csv.reader(rf)
for a in reader_2:
blood_pressure.append(eval(a[4]))
time.append(a[3])
for i in range(0, len(blood_pressure)):
trace.append(go.Box(y=blood_pressure[i],
x=triple_time[i],
line=dict(color='#6a92ff'),
hoverinfo='all'))
for a in range(0, len(hr)):
trace2.append(go.Scatter(y=coated_hr[a],
x=coated_time[a],
name='HR',
Whenever you pan or zoom, a relayoutData interaction is triggered, from there you can get the axis ranges.
The dcc.Graph component has four attributes that can change through
user-interaction: hoverData, clickData, selectedData, relayoutData.
These properties update when you hover over points, click on points,
or select regions of points in a graph.
https://dash.plotly.com/interactive-graphing
import json
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from dash.exceptions import PreventUpdate
import plotly.express as px
import pandas as pd
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
df = pd.DataFrame({
"x": [1,2,1,2],
"y": [1,2,3,4],
"customdata": [1,2,3,4],
"fruit": ["apple", "apple", "orange", "orange"]
})
fig = px.scatter(df, x="x", y="y", color="fruit", custom_data=["customdata"])
fig.update_traces(marker_size=20)
app.layout = html.Div([
dcc.Graph(
id='basic-interactions',
figure=fig
),
html.Div(className='row', children=[
html.Div([
dcc.Markdown("""
**Zoom and Relayout Data**
Click and drag on the graph to zoom or click on the zoom
buttons in the graph's menu bar.
Clicking on legend items will also fire
this event.
"""),
html.Pre(id='relayout-data'),
])
])
])
#app.callback(
Output('relayout-data', 'children'),
Input('basic-interactions', 'relayoutData'))
def display_relayout_data(relayoutData):
if relayoutData is None:
raise PreventUpdate
elif "xaxis.range[0]" not in relayoutData.keys():
raise PreventUpdate
else:
#get the relevant axis ranges, you can use to drop columns from the datatable
print(relayoutData,type(relayoutData))
return json.dumps(relayoutData, indent=2)
if __name__ == '__main__':
app.run_server(debug=True)