Hi Everybody,
I’m fairly new to dash and plotly. I’m working on a multi-page app dashboard. For one of the pages of my dashboard, I’m plotting data based on a radio item input. Here is the page:
trunk_angle.py
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import plotly.graph_objs as go
import numpy as np
from app import app
from components import utils
layout = html.Div([
html.Div([
html.Br(),
html.Label('Plotting Options'),
dcc.RadioItems(
id='trunk-angle-radio',
options=[
{'label':'Sagittal', 'value':'Sagittal'},
{'label':'Lateral', 'value':'Lateral'},
{'label':'Twist', 'value':'Twist'}
],
value='Sagittal'
)
]),
html.Div([
html.Div([
dcc.Graph(id='trunk-angle-plot')
],
style = {'width':'48%','display':'inline-block'}
),
html.Div([
dcc.Graph(id='trunk-angle-dist')
],
style = {'width':'48%','display':'inline-block','float':'right' }
)
]),
html.Div([
html.Label('Data Statistics'),
html.Div(
id='data-stats-div',
style={'padding':10})
])
])
@app.callback(
Output('trunk-angle-plot','figure'),
[Input('trunk-angle-radio','value')])
def update_angle_plot(radio_option):
(x, y) = utils.get_trunk_angles(radio_option)
fig = {
'data':[
go.Scatter(
x = x,
y = y,
mode = 'lines+markers'
)],
'layout': go.Layout(
title='Trunk Angle Time Series Plot',
xaxis={'title': 'Time (sec)'},
yaxis={'title': 'Degrees'})
}
return fig
@app.callback(
Output('trunk-angle-dist', 'figure'),
[Input('trunk-angle-radio', 'value')])
def update_dist_plot(radio_option):
(x,y) = utils.get_trunk_angles(radio_option)
counts, bins = np.histogram(y, bins=range(-90, 91, 30))
bins = bins + (bins[1] - bins[0]) / 2
#print(counts, bins)
fig={
'data': [
go.Bar(
x=bins,
y=counts
)],
'layout': go.Layout(
title = 'Trunk Angle Distributions',
xaxis = {
'title': 'Bin midpoint (degrees)',
'tickmode' : 'array',
'tickvals' : bins,
'ticktext' : [str(int(bin)) for bin in bins]},
yaxis = {'title': 'Percentage of time'})
}
return fig
@app.callback(
Output('data-stats-div', 'children'),
[Input('trunk-angle-radio', 'value')])
def update_stats(radio_option):
(x, y) = utils.get_trunk_angles(radio_option)
stats_div = [
html.Div('Minimum: {}'.format(np.min(y)),id='trunk-angle-dist-min'),
html.Div('Maximum: {}'.format(np.max(y)),id='trunk-angle-dist-max'),
html.Div('Mean: {:.2f}'.format(np.mean(y)),id='trunk-angle-dist-mean'),
html.Div('Standard Deviation: {:.2f}'.format(np.std(y)),id='trunk-angle-dist-std'),
html.Div('Range: {}'.format(np.max(y)-np.min(y)),id='trunk-angle-dist-range')
]
return stats_div
The utils.get_trunk_angles() function just provides some fake data for me to plot and is shown below:
def get_trunk_angles(radio_option):
dummy_x = np.linspace(0, 50, 101)
if radio_option == 'Sagittal':
dummy_y = np.random.randint(-90,90,101)
elif radio_option == 'Lateral':
dummy_y = np.random.randint(-90,90,101)
elif radio_option == 'Twist':
dummy_y = np.random.randint(-90,90,101)
return (dummy_x, dummy_y)
My problem is that when I first load this page, one of the graph objects plots the data as expected, but the other one does not and gives me a callback error. Once I change the radio button selection, both graphs will plot the data. Here is a screenshot of the callback error:
Here is the Traceback:
Traceback (most recent call last):
File “/Users/bwsturm/PycharmProjects/spinetrack-dashboard2/apps/trunk_angle.py”, line 73, in update_dist_plot
go.Bar(
File “/Users/bwsturm/anaconda3/envs/sm-dash/lib/python3.8/site-packages/plotly/graph_objs/init.py”, line 94246, in init
self[“x”] = x if x is not None else _v
File “/Users/bwsturm/anaconda3/envs/sm-dash/lib/python3.8/site-packages/plotly/basedatatypes.py”, line 3490, in setitem
self._set_prop(prop, value)
File “/Users/bwsturm/anaconda3/envs/sm-dash/lib/python3.8/site-packages/plotly/basedatatypes.py”, line 3772, in _set_prop
val = validator.validate_coerce(val)
File “/Users/bwsturm/anaconda3/envs/sm-dash/lib/python3.8/site-packages/_plotly_utils/basevalidators.py”, line 385, in validate_coerce
v = copy_to_readonly_numpy_array(v)
File “/Users/bwsturm/anaconda3/envs/sm-dash/lib/python3.8/site-packages/_plotly_utils/basevalidators.py”, line 93, in copy_to_readonly_numpy_array
if pd and isinstance(v, (pd.Series, pd.Index)):
AttributeError: partially initialized module ‘pandas’ has no attribute ‘Series’ (most likely due to a circular import)
Can anybody provide some clues to this callback error? I would greatly appreciate any help.
Thanks!
Ben