✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🐍Plotly, Coiled CEOs Discuss Partnering & ML Experts show us how Dash + Dask apps work Register for the Webinar.

Weird and unexpected behaviour when displaying hidden graphs with callbacks

Hi Community,

I want to have two hidden graphs displayed when I choose parameters in a dropdown and a CheckList (2 checkboxes). My problem is that I don’t succeed to display both of them.

when both checklist are checked, but the first checkbox is checked first:

  • only the first graph is displayed (instead of both)

when both checklist are checked, but the second checkbox is checked first:

  • sometimes only the second graph is displayed
  • sometimes both are displayed (as expected)
  • sometimes the same graph is displayed twice. (as in the following picture)

I followed this topic ( https://github.com/plotly/dash-table-experiments/issues/28 ) to learn how to “build” hidden dash_core_components, and it doesn’t look like I missed something.

The output of the callback goes in a div tag and seems right:

I also inspected the web-page and it seems like there are no particular errors:

html_inspection

Here is my body where the second graph (div_low tag) is missing lots of stuff (I don’t know much about html)

And finally Here is my code with two CSV containing data, to be able to have a reproducible example:

CSV 1: FB
Date,High,Low,Open,Close,Volume,Adj Close
2017-01-03,117.83999633789062,115.51000213623047,116.02999877929688,116.86000061035156,20663900,116.86000061035156
2017-01-04,119.66000366210938,117.29000091552734,117.55000305175781,118.69000244140625,19630900,118.69000244140625
2017-01-05,120.94999694824219,118.31999969482422,118.86000061035156,120.66999816894531,19492200,120.66999816894531
2017-01-06,123.87999725341797,120.02999877929688,120.9800033569336,123.41000366210938,28545300,123.41000366210938
2017-01-09,125.43000030517578,123.04000091552734,123.55000305175781,124.9000015258789,22880400,124.9000015258789
2017-01-10,125.5,124.27999877929688,124.81999969482422,124.3499984741211,17324600,124.3499984741211
2017-01-11,126.12000274658203,124.05999755859375,124.3499984741211,126.08999633789062,18356500,126.08999633789062
2017-01-12,126.7300033569336,124.80000305175781,125.61000061035156,126.62000274658203,18653900,126.62000274658203
2017-01-13,129.27000427246094,127.37000274658203,127.48999786376953,128.33999633789062,24884300,128.33999633789062
2017-01-17,128.33999633789062,127.4000015258789,128.0399932861328,127.87000274658203,15294500,127.87000274658203
2017-01-18,128.42999267578125,126.83999633789062,128.41000366210938,127.91999816894531,13145900,127.91999816894531
2017-01-19,128.35000610351562,127.44999694824219,128.22999572753906,127.55000305175781,12195500,127.55000305175781
2017-01-20,128.47999572753906,126.77999877929688,128.10000610351562,127.04000091552734,19097200,127.04000091552734

CSV 2: AAPL
Date,High,Low,Open,Close,Volume,Adj Close
2017-01-03,116.33000183105469,114.76000213623047,115.80000305175781,116.1500015258789,28781900.0,112.62096405029297
2017-01-04,116.51000213623047,115.75,115.8499984741211,116.0199966430664,21118100.0,112.49491119384766
2017-01-05,116.86000061035156,115.80999755859375,115.91999816894531,116.61000061035156,22193600.0,113.06698608398438
2017-01-06,118.16000366210938,116.47000122070312,116.77999877929688,117.91000366210938,31751900.0,114.32748413085938
2017-01-09,119.43000030517578,117.94000244140625,117.94999694824219,118.98999786376953,33561900.0,115.37466430664062
2017-01-10,119.37999725341797,118.30000305175781,118.7699966430664,119.11000061035156,24462100.0,115.49102020263672
2017-01-11,119.93000030517578,118.5999984741211,118.73999786376953,119.75,27588600.0,116.11158752441406
2017-01-12,119.30000305175781,118.20999908447266,118.9000015258789,119.25,27086200.0,115.62676239013672
2017-01-13,119.62000274658203,118.80999755859375,119.11000061035156,119.04000091552734,26111900.0,115.42314910888672
2017-01-17,120.23999786376953,118.22000122070312,118.33999633789062,120.0,34439800.0,116.35398864746094
2017-01-18,120.5,119.70999908447266,120.0,119.98999786376953,23713000.0,116.34428405761719
2017-01-19,120.08999633789062,119.37000274658203,119.4000015258789,119.77999877929688,25597300.0,116.14067077636719
2017-01-20,120.44999694824219,119.7300033569336,120.44999694824219,120.0,32597900.0,116.35398864746094

Code:

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objs as go

import pandas as pd

import logging
from logging.handlers import RotatingFileHandler

app = dash.Dash()

“”"
The View
“”"

app.layout = html.Div([

html.Div([ # Input

html.Div([ # https://dash.plot.ly/dash-core-components/checklist check if setProps is everywhere

html.Label(‘Range Label’),
dcc.RangeSlider( # https://dash.plot.ly/dash-core-components/rangeslider
id=‘time_slider’,
min=0, # min date
max=9, # max date
marks={i: ‘Label {}’.format(i) if i == 1 else str(i) for i in range(1, 6)}, # label names
value=[0, 9], # value we start at
),

html.Label(‘Radio Items’),
dcc.RadioItems(
id=‘freq_choice’,
options=[
{‘label’: ‘Daily’, ‘value’: 0},
{‘label’: ‘Weekly’, ‘value’: 1},
{‘label’: ‘Monthly’, ‘value’: 2}
],
value=0
),

]),

html.Div(

dcc.Dropdown(
id=‘dropdown’,
options=[
# {‘label’: ‘Google’, ‘value’: ‘GOOGL’},
{‘label’: ‘Apple’, ‘value’: ‘AAPL’},
{‘label’: ‘Facebook’, ‘value’: ‘FB’},
# {‘label’: ‘Advanced Micro Devices’, ‘value’: ‘AMD’},
# {‘label’: ‘Alibaba Group Holding’, ‘value’: ‘BABA’},
# {‘label’: ‘Facebook’, ‘value’: ‘FB’}
],
value=[],
multi=True
)

),

html.Div([

html.Div([
dcc.Checklist(
id=‘first_row_cb’,
options=[
{‘label’: ‘High’, ‘value’: ‘High’},
{‘label’: ‘Low’, ‘value’: ‘Low’},
# {‘label’: ‘High - Low’, ‘value’: ‘High - Low’}
],
values=[],
labelStyle={‘display’: ‘inline-block’}
)
])

])

], id=‘Input’),

html.Div(dcc.Graph(style={‘display’: ‘none’})), # In order to load dcc.Graph dependency

html.Div(html.Div(id=‘div_high’)),

html.Div(html.Div(id=‘div_low’))

])

“”"
The Controller
“”"

@app.callback(
Output(component_id=‘div_high’, component_property=‘children’), # div_high , children
[
# Input(component_id=‘time_slider’, component_property=‘value’), # values?
Input(component_id=‘dropdown’, component_property=‘value’), # values?
Input(component_id=‘first_row_cb’, component_property=‘values’) # values?
]
)
def populate_high_div(assets, checked):

if len(assets) > 0 and ‘High’ in checked:

high_figure = graph_builder([‘2017-01-03’, ‘2017-01-20’], assets, ‘High’)

app.logger.info("\n\nHIGH :\n{}\n".format(high_figure))

return high_figure

@app.callback(
Output(component_id=‘div_low’, component_property=‘children’), # div_low , children
[
# Input(component_id=‘time_slider’, component_property=‘value’), # values?
Input(component_id=‘dropdown’, component_property=‘value’), # values?
Input(component_id=‘first_row_cb’, component_property=‘values’) # values?
]
)
def populate_low_div(assets, checked):

if len(assets) > 0 and ‘Low’ in checked:

low_figure = graph_builder([‘2017-01-03’, ‘2017-01-20’], assets, ‘Low’)

app.logger.info("\n\nLOW :\n{}\n".format(low_figure))

return low_figure

“”"
Model
“”"

def graph_builder(time, assets, item):
graph = []
data = []
title = '{}: '.format(item)

for asset in assets:
data.append(get_data(asset_name=asset, item=item, start_date=time[0], end_date=time[1]))
title += '{} / '.format(asset)

figure = go.Figure(
data=data,
layout=go.Layout(
title=title[:-3],
showlegend=True
)
)

graph.append(dcc.Graph(
figure=figure,
style={‘display’: ‘block’},
id=‘graph_high’
))

return graph

def get_data(asset_name, item, start_date, end_date):

# load csv
csv_name = ‘{}_csv.csv’.format(asset_name)
df = pd.DataFrame(pd.read_csv(csv_name, index_col=‘Date’))

# dataframe --> filtered dictionary
df = df[start_date:end_date]
datas = df[item].T.to_dict()

# extract data
dates = [*datas] # https://stackoverflow.com/questions/16819222/how-to-return-dictionary-keys-as-a-list-in-python
points = list(datas.values())

return go.Scatter(x=dates, y=points, mode=‘lines+markers’)

if name == ‘main’:
logHandler = RotatingFileHandler(‘info.log’, maxBytes=1000, backupCount=1)
logHandler.setLevel(logging.INFO)
app.logger.setLevel(logging.INFO)
app.logger.addHandler(logHandler)

app.run_server()

Thanks in advance if you find any solutions. I don’t even know if it’s a bug or not …

Are the graph IDs unique?

They were not, now it works !!!

Thank you for you time, and again Thank you for Dash, it’s amazing for me :slight_smile:

1 Like