Hello
I am writing a dash app using dash_bio
. dash_bio
does not still support the latest dash version, these are the versions used:
dash==0.40.0
dash-bio==0.1.2
dash-core-components==0.45.0
dash-html-components==0.15.0
dash-renderer==0.21.0
dash-table==3.6.0
Nevertheless, I don’t think that the error is linked to the version, see at the end.
In this app, I upload and process a fil and then do several things. I extracted a “small” part that reproduces my issue. I put the code at the end. There are four callbacks
- The first callback manages the upload component, store the results in a Store component and set the options of two dropdowns: one for selecting data to plot (
dropdown-data
) and the other for selecting the column I want to display in the table (data-column-selector
). - A second callback, get the data from the store and return a table with columns according to the dropdown (
data-column-selector
). - A third callback make a fake plot just for debugging (
MAP DATA
) - The last callback draw a colorscale I need in the true app.
The problem is that the first time the select_table_columns
callback is fired, the value of the dropdown data-column-selector
is None
. I don’t understand why dash executes the first callback (the one which will upload data) at the end and not at the beginning as the other callbacks depend on the outputs of the upload callback. Here after is the console output when the app is running, you can see the order of the callback and then a lot of exceptions corresponding to KeyError
because the value is None
and thus does not correspond to any column of the DataFrame.
Running on http://127.0.0.1:8050/
Debugger PIN: 122-420-937
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
Running on http://127.0.0.1:8050/
Debugger PIN: 958-957-993
PLOT COLORBAR
MAP DATA
SELECTED COLUMNS None
UPLOAD DATA
SELECTED COLUMNS None
SELECTED COLUMNS ['A', 'B']
Traceback (most recent call last):
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/pandas/core/indexes/base.py", line 2657, in get_loc
return self._engine.get_loc(key)
File "pandas/_libs/index.pyx", line 108, in pandas._libs.index.IndexEngine.get_loc
File "pandas/_libs/index.pyx", line 132, in pandas._libs.index.IndexEngine.get_loc
File "pandas/_libs/hashtable_class_helper.pxi", line 1601, in pandas._libs.hashtable.PyObjectHashTable.get_item
File "pandas/_libs/hashtable_class_helper.pxi", line 1608, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: None
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/app.py", line 2463, in __call__
return self.wsgi_app(environ, start_response)
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/app.py", line 2449, in wsgi_app
response = self.handle_exception(e)
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/app.py", line 1866, in handle_exception
reraise(exc_type, exc_value, tb)
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/app.py", line 2446, in wsgi_app
response = self.full_dispatch_request()
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/app.py", line 1951, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/app.py", line 1820, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/app.py", line 1949, in full_dispatch_request
rv = self.dispatch_request()
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/app.py", line 1935, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/dash/dash.py", line 1073, in dispatch
response.set_data(self.callback_map[output]['callback'](*args))
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/dash/dash.py", line 969, in add_context
output_value = func(*args, **kwargs)
File "/Users/gvallver/git/mosaica/dash/test/app.py", line 170, in select_table_columns
tab_df = df[values]
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/pandas/core/frame.py", line 2927, in __getitem__
indexer = self.columns.get_loc(key)
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/pandas/core/indexes/base.py", line 2659, in get_loc
return self._engine.get_loc(self._maybe_cast_indexer(key))
File "pandas/_libs/index.pyx", line 108, in pandas._libs.index.IndexEngine.get_loc
File "pandas/_libs/index.pyx", line 132, in pandas._libs.index.IndexEngine.get_loc
File "pandas/_libs/hashtable_class_helper.pxi", line 1601, in pandas._libs.hashtable.PyObjectHashTable.get_item
File "pandas/_libs/hashtable_class_helper.pxi", line 1608, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: None
Traceback (most recent call last):
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/pandas/core/indexes/base.py", line 2657, in get_loc
return self._engine.get_loc(key)
File "pandas/_libs/index.pyx", line 108, in pandas._libs.index.IndexEngine.get_loc
File "pandas/_libs/index.pyx", line 132, in pandas._libs.index.IndexEngine.get_loc
File "pandas/_libs/hashtable_class_helper.pxi", line 1601, in pandas._libs.hashtable.PyObjectHashTable.get_item
File "pandas/_libs/hashtable_class_helper.pxi", line 1608, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: None
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/app.py", line 2463, in __call__
return self.wsgi_app(environ, start_response)
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/app.py", line 2449, in wsgi_app
response = self.handle_exception(e)
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/app.py", line 1866, in handle_exception
reraise(exc_type, exc_value, tb)
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/app.py", line 2446, in wsgi_app
response = self.full_dispatch_request()
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/app.py", line 1951, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/app.py", line 1820, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/app.py", line 1949, in full_dispatch_request
rv = self.dispatch_request()
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/flask/app.py", line 1935, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/dash/dash.py", line 1073, in dispatch
response.set_data(self.callback_map[output]['callback'](*args))
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/dash/dash.py", line 969, in add_context
output_value = func(*args, **kwargs)
File "/Users/gvallver/git/mosaica/dash/test/app.py", line 170, in select_table_columns
tab_df = df[values]
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/pandas/core/frame.py", line 2927, in __getitem__
indexer = self.columns.get_loc(key)
File "/anaconda3/envs/dash-mosaica/lib/python3.7/site-packages/pandas/core/indexes/base.py", line 2659, in get_loc
return self._engine.get_loc(self._maybe_cast_indexer(key))
File "pandas/_libs/index.pyx", line 108, in pandas._libs.index.IndexEngine.get_loc
File "pandas/_libs/index.pyx", line 132, in pandas._libs.index.IndexEngine.get_loc
File "pandas/_libs/hashtable_class_helper.pxi", line 1601, in pandas._libs.hashtable.PyObjectHashTable.get_item
File "pandas/_libs/hashtable_class_helper.pxi", line 1608, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: None
This is now the code of the app. I do not know if I have to change the callbacks or if there is something about the Store component that I do not clearly understand.
#!/usr/bin/env python3
# -*- coding=utf-8 -*-
import dash
import dash_table
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output, State
import plotly.graph_objs as go
import pandas as pd
import numpy as np
# plotly colorscales
# must be lowercase for matplotlib
COLORSCALES = ["Blues",
"Greens",
"Greys",
"Hot",
"Jet",
"Rainbow",
"RdBu",
"Reds",
"Viridis",
"YlGnBu",
"YlOrRd"]
# ---- Set up App ----
app = dash.Dash(__name__)
# Layout
# ------------------------------------------------------------------------------
footer = ""
header = ""
# --- Body: main part of the app ---
body = html.Div(className="container", children=[
# --- store components for the data
dcc.Store(id="data-storage", storage_type="memory"),
# --- upload
html.H4("Upload xyz file"),
dcc.Upload(
id='file-upload',
children=html.Div(
className="upload-area",
children=[
' Drag and Drop or ', html.A('Select File')]
),
),
html.Div(id="submit_done", className="mt-5"),
html.Div(children=[
# --- dash bio Molecule 3D Viewer
html.Div(id="dash-bio-container", children=[
html.H4("Structure Viewer"),
# --- controls
html.Div(className="control-label", children="Select data"),
dcc.Dropdown(
className="control",
id='dropdown-data',
placeholder="Select data"
),
html.Div(className="control-label", children="Select colormap"),
dcc.Dropdown(
className="control",
id='dropdown-colormap',
options=[{"label": cm, "value": cm}
for cm in COLORSCALES],
value="Viridis"
),
html.Div(id="dash-bio-viewer", children=[
dcc.Graph(id="graph")
]),
dcc.Graph(id='colorbar', config=dict(displayModeBar=False))
]),
# --- Data table
html.Div(id="data-table-container", children=[
html.H4("Table"),
dcc.Dropdown(
id="data-column-selector",
multi=True,
),
html.P("Click on atoms to highlight the corresponding lines."),
html.Div(children=[
dash_table.DataTable(
id="data-table",
editable=False,
style_cell={'maxWidth': '60px',
'width': '60px',
'minWidth': '60px',
'whiteSpace': 'normal'},
style_header={'backgroundColor': 'rgba(60, 93, 130, .25)',
'fontWeight': 'bold',
"border": "1px solid gray",
"fontFamily": "sans-serif"},
style_data_conditional = [{'if': {'row_index': 'odd'},
'backgroundColor': 'rgba(60, 93, 130, .05)'}],
style_data={'border': '1px solid gray'},
style_table={"overflowX": "scroll",
"maxHeight": "800px",
"overflowY": "scroll"},
# need higher version of dash_table, incompatible with dash-bio
# fixed_rows={'headers': True, 'data': 0}
)
]),
])
])
])
app.layout = html.Div([header, body, footer])
# callbacks
# ------------------------------------------------------------------------------
@app.callback(
[Output("data-storage", "data"),
Output("dropdown-data", "options"),
Output("data-column-selector", "options"),
Output("data-column-selector", "value")],
[Input("file-upload", "contents")]
)
def upload_data(content):
"""
Uploads the data from an xyz file and store them in the store component.
Then set up the dropdowns, the table and the molecule viewer.
"""
print("\n\nUPLOAD DATA")
# read file
# bla bla with content
# comute data
df = pd.DataFrame({k: np.random.random(20) for k in "ABCDEF"})
# all data for the store component
all_data = df.to_dict("records")
# dropdown for table columns
tab_options = [{"label": name, "value": name} for name in df]
values = ["A", "B"]
# options for dropdown for mapped values
options = [{"label": name, "value": name} for name in df
if name not in ["C", "F"]]
return all_data, options, tab_options, values
@app.callback(
[Output("data-table", "data"),
Output("data-table", "columns")],
[Input("data-storage", "modified_timestamp"),
Input("data-column-selector", "value")],
[State("data-storage", "data")]
)
def select_table_columns(ts, values, data):
"""
Select columns for the table
"""
df = pd.DataFrame(data)
print("\n\nSELECTED COLUMNS", values)
tab_df = df[values]
columns = [{"name": i, "id": i} for i in tab_df]
data = tab_df.to_dict("records")
return data, columns
@app.callback(
Output('graph', 'figure'),
[Input('dropdown-data', 'value'),
Input('dropdown-colormap', "value")],
[State("data-storage", "data")]
)
def map_data_on_atoms(selected_data, cm_name, data):
"""
Map the selected data on the structure using a colorscale to draw the atoms.
"""
print("\n\nMAP DATA")
df = pd.DataFrame(data)
if selected_data:
trace = [
go.Scatter(
y=df[selected_data],
mode="lines+markers",
line=dict(dash="dash"),
marker=dict(
size=20,
color=df[selected_data],
colorscale=cm_name),
hoverinfo="skip",
),
]
else:
trace = []
figure = go.Figure(
data=trace,
layout=go.Layout(
width=500, height=500,
)
)
return figure
@app.callback(
Output("colorbar", "figure"),
[Input('dropdown-data', 'value'),
Input('dropdown-colormap', 'value')],
[State("data-storage", "data")]
)
def plot_colorbar(selected_data, cm_name, data):
"""
Display a colorbar according to the selected data mapped on to the structure.
"""
print("\n\nPLOT COLORBAR")
if selected_data:
npts = 100
values = pd.DataFrame(data)[selected_data].values
values = np.linspace(np.nanmin(values), np.nanmax(values), npts)
trace = [
go.Contour(
z=[values, values],
x0=values.min(),
dx=(values.max() - values.min()) / npts,
colorscale=cm_name,
autocontour=False,
showscale=False,
contours=go.contour.Contours(coloring="heatmap"),
line=go.contour.Line(width=0),
hoverinfo="skip",
),
]
figure = go.Figure(
data=trace,
layout=go.Layout(
width=550, height=100,
xaxis=dict(showgrid=False, title=selected_data),
yaxis=dict(ticks="", showticklabels=False),
margin=dict(l=0, t=0, b=40, r=0, pad=0)
)
)
else:
figure = go.Figure(
data=[],
layout=go.Layout(
width=550, height=100,
xaxis=dict(ticks="", showticklabels=False, showgrid=False,
title=selected_data, zeroline=False),
yaxis=dict(ticks="", showticklabels=False, showgrid=False,
title=selected_data, zeroline=False),
margin=dict(l=5, t=0, b=40, r=5, pad=0)
)
)
return figure
if __name__ == '__main__':
app.run_server(debug=True)
I also try to run the above app in another environment with the following version of dash:
dash==1.0.1
dash-core-components==1.0.0
dash-html-components==1.0.0
dash-renderer==1.0.0
dash-table==4.0.1
I got the same error.