I’m using an app right now with tabs. I have an input above the tabs and a couple inputs in each tabs layout. At least that’s the plan. In each tab layout is a different graph. I don’t know if this is relevant but it maybe.
I’m doing this as I’m making an app where you select a test and based on the test you can switch between tabs to see data from different files associated with that test. I.e.
dcc.input(id=‘test-select’)
tabs selecter code here,
tabs divider which updates on callback from tab selection.
|_> layout of tab1:
dcc.input(id=‘tab1-test-data-filter’)
dcc.Graph(id=‘tab1-graph’)
I’ve used psuedocode as there are more filters to help select the test and more filters for the data I didn’t want to include all of that as it’s a couple hundred lines of code (nothing mind bending just lot’s of formatting).
Right now I fire a callback to tab1-graph when test-select is changed. that’s working. Whenever I add 'tab1-test-data-filter as an Input to that callback, the callback is successfully fired but the graph doesn’t update. I’m confident that the ID for the second input is correct (obviously as the callback works) but for some reason the graph won’t update. I’m using the latest dash libraries (1.01 and whatever the other one is). Thank you so much for any help I’ve spent a long time working on this and am running into what seems like a bug. Here’s the full code for “Cycle_data” which is the code for the tab1 layout and content.
import stuff to do stuff
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go
import os
import urllib.parse
import numpy as np
from pathlib import Path
from batModel2 import batteryTest as bt
# define directory for SOH and cycle data
BASE_DIR = Path(__file__).parents[1]
direc = os.path.join(BASE_DIR, 'CycleData')
SOH_direc=os.path.join(BASE_DIR,"SohData")
info_direc=os.path.join(BASE_DIR,"ExperimentSummary")
bat = bt(0,0,5,1)
column_options = bat.cycleHeaders
SOH_column_options = bat.SOH_Cycle_Headers
info_column_options = bat.ExpSum_Headers
layout = [
# add labels for dropdowns
html.Div([
html.Div('X-axis type Selection:',
style={'margin-top': '10px'},
className='four columns'),
html.Div('Please select your desired y-axis type for cycle data:',
style={'margin-top': '10px'},
className='four columns'),
html.Div('Please select your desired y-axis type for SOH data:',
style={'margin-top': '10px'},
className='four columns'),
# add droppdowns to select data types
html.Div([
html.Div(
dcc.Dropdown(
id='cycle-xaxis',
options=[{'label': 'Cycle Number', 'value': 'Cycle Number'},
{'label': 'Cycle End Time ( s )', 'value': 'Cycle End Time ( s )'},
{'label': 'Throughput ( Wh )', 'value': 'Throughput ( Wh )'},
],
value='Cycle Number',
),
className='four columns'
),
html.Div(
dcc.Dropdown(
id='yaxis-column',
options=[{'label': i, 'value': i} for i in column_options],
value='Discharge Capacity ( Ah )',
multi = True,
),
className='four columns'
),
html.Div(
dcc.Dropdown(
id='SOH_yaxis-column',
options=[{'label': i, 'value': i} for i in SOH_column_options],
value='Discharge Energy ( Wh )',
multi=True,
),
className='four columns'
),
],
className='row',
)
],
style={'margin-Bottom': '10',
'background-color': '#F0F0F0'}
),
# add SOH Radioitem
html.Div([
dcc.RadioItems(id='SOH_Check',
options=[{'label': 'Hide SOH', 'value': True},
{'label': 'Show SOH', 'value': False}],
value=False,
labelStyle={'display': 'inline-block'},
style={'margin-left': '40'}),
dcc.RadioItems(id='Normalize',
options=[{'label': 'Normalize', 'value': True},
{'label': 'Absolute', 'value': False}],
value=False,
labelStyle={'display': 'inline-block'},
style={'margin-left': '40'}),
]),
# add graphs
html.Div([
html.Div([
html.P('Cell Cycle Data', style={'text-align': 'center', 'font-size': '20', 'margin-top': '10px', 'font-weight': 'bold'}),
dcc.Graph(id='cycle-graph', style={'padding-right': '10px', 'padding-left': '10px'}),
],
className='six columns',
style={'border-color': '#C1C1C1',
'border-style': 'solid',
'border-width': '3px',
'background-color': 'white',
'border-radius': '7px',
'padding': '10px',
}
),
html.Div([
html.P('Cell SOH Data',
style={'text-align': 'center',
'font-size': '20',
'margin-top': '10px',
'font-weight': 'bold',
}),
dcc.Graph(id='soh_graph',
style={'padding-right': '10px',
'padding-left': '10px', }
),
],
className='six columns',
style={'border-color': '#C1C1C1',
'border-style': 'solid',
'border-width': '3px',
'margin-left': '10px',
'background-color': 'white',
'border-radius': '7px',
'padding': '10px',}
),
],
className='row',
style={'margin-Bottom': '30',
'verticalAlign': 'middle',
'align-self': 'center',
'margin-left': '40',
}),
# add info boxes
html.Div([
html.Div('Cell Information:',
style={'font-size': '20', 'font-weight': 'bold'
}),
html.Div(children=html.Div(id='info box'), className='row'),
],
style={'border-width': '3px',
'border-color': '#C1C1C1',
'border-style': 'solid',
'margin-top': '10',
'padding': '10px'}),
# Add download link:
html.Div([ 'Download Data:',
html.Div([
html.A('Download Cycle Data',
id='download-link',
download="Cycledata.csv",
href="",
target="_blank"
)], id='cycle-downloaddiv'),
html.Div([
html.A(
'Download SOH Data',
id='download-link-soh',
download="SOHdata.csv",
href="",
target="_blank"
)], id='sohddiv')
])
]
layout = html.Div(layout, style={'padding': '20px 10px 15px 10px',
'marginLeft': 'auto', 'marginRight': 'auto', "width": "95%", 'margin-top':'50px',
'boxShadow': '0px 0px 5px 5px rgba(204,204,204,0.4)'})
def register_cycle_callback1(app):
@app.callback(dash.dependencies.Output('cycle-graph', 'figure'),
[dash.dependencies.Input('Test_Selectorr', 'value'),
dash.dependencies.Input("SOH_Check", 'value')])
def update_graph(cell_numbers):
traces=[]
SOH_Check = False
Normalize = False
xaxis_column_name = 'Cycle End Time ( s )'
yaxis_column_name = "Discharge Capacity ( Ah )"
if cell_numbers == None or yaxis_column_name == [] or cell_numbers == []:
return
if type(cell_numbers) == str:
cell_numbers = [cell_numbers]
if type(yaxis_column_name) == str:
yaxis_column_name = [yaxis_column_name]
dataframes = []
for i in range(len(cell_numbers)):
path = os.path.join(direc, cell_numbers[i])
if not os.path.isfile(path):
break
df = pd.read_csv(path)
nme = cell_numbers[i].split('.')
nme = nme[0].split(os.sep)
nme = ' '.join(nme[-1].split('_')[1:-1])
n = 0
for j in range(len(yaxis_column_name)):
if Normalize is True:
normalizer = df.loc[2, yaxis_column_name[j]]
else:
normalizer = 1
if SOH_Check is True:
df = df.loc[(df['Step Max'] < df['Step Max'].mean()) & (df['Step Min'] > 0), :]
if n == 0 and len(yaxis_column_name) >= 1:
if xaxis_column_name == 'Cycle End Time ( s )':
df[xaxis_column_name] = df[xaxis_column_name]
df[xaxis_column_name] = pd.to_datetime(df[xaxis_column_name], unit='s')
traces.append(go.Scatter(
x=df.loc[:,xaxis_column_name],
y=df.loc[:,yaxis_column_name[j]]/normalizer,
mode='lines',
name = nme + ' ' + yaxis_column_name[j],
yaxis='y%s' % str(j+1)
))
return {'data':traces}