[Solved] Dash layout not working as expected + General Debugging Tips

I am trying to do a cluster of data selection in my Dash app to display plots that are dependent on the data. However using the base dash CSS based on skeleton, it doesn’t appear to follow the format that I specified.

code for app.layout():

app.layout = html.Div([
    html.Div([
        html.H1('Power Forward Research',
                className='six columns'),
        html.Img(
            src='static\\Uniper_Logo_RGB_Black.jpg',
            className='two column',
            style={'float': 'right',
                   'position': 'relative',
                   'height' : '120',
                   'width' : '150'
                   })
        ],className='row'),
    html.Div([
        html.Div([
            html.P('Select Quote Date:'),
            dcc.Dropdown(
                id='quote_date',
                options=date_options,
                multi = False,
                value = [last_day]
            ),
            html.P('Select Contracts:'),
            dcc.Dropdown(
                id='contract',
                options=contract_options,
                multi=False,
                value=[contract_options[0]]
            )
        ],className='six column'),
        html.Div([
            html.P('Select Gas:'),
            dcc.Dropdown(
                id='gas',
                options=gas_contracts,
                multi=False,
                value=[gas_contracts[0]]
            )
        ],className='six column')
    ],className='row'),
    html.Div([
        dcc.Graph(id='forward_curve')
    ],className='row',style={'height': 300})
],className='ten columns offset-by-one')

Indstead of returning what I think it is asking for I get a renderd layout that looks like this:

A side issue that I have when using dropdowns is that the content doesn’t appear in the dropdown when values['label"] == values["value"]. I am wondering if this is an issue that others have encountered or is an issue that arises when working with data types that are converted from other non-string formats.

Here is my code for creating the dropdown menues, only the

# Create controls
contract_options = [{'label': str(contract[0]),
                     'value': str(contract[1])}
                     for contract in zip(contract_data.name, contract_data.ice_id)]

date_options = [{'lable': str(quote_dt),
                 'value': str(quote_dt)}
                for quote_dt in gas_forwards.quote_dt]


gas_contracts = [{'lable': str(ctr),
                 'value': str(ctr)}
                 for ctr in gas_forwards.columns[2:].values]

Other than this being an amazing implementation of the long needed python shiny, I was wondering what the reccomended best practices are for debugging issues similar to the ones I am having. I think the hardest part for people who are accustomed to programming in an interactive environment, which was my largest stumbling block when learning shiny app development, is the lack of reasources and documentation on best practices for debugging.

Hmm I can’t tell you what your high level problems may be, but if your options/contracts dicts need to be of a certain format, check your spelling for the key 'label'!!

I noticed this and fixed it but it the high-level issue persisted. I changed the container tag that was in the outer div of the app. This seemed to fix the layout.

It also looks like there might be a typo in your className: “six column” instead of “six columns”.


I was wondering what the reccomended best practices are for debugging issues similar to the ones I am having.

Great question. I’ll expand this out into a larger chapter in the documentation but for now, here are some tips and tricks:

Backend Debugging

1 - Explicitly viewing errors: If an error occurs in any of your functions that are wrapped in app.callback, it’ll get printed in your terminal (this won’t work in Jupyter notebooks). If you use debug=True when running the app (app.run_server(debug=True)) then if you modify your code, your app will automatically restart (even if there was an error).
Note that the app’s frontend may not notify you that an error occured (this will change in the future). Here’s an example of what tracebacks look like.


Here’s the code that I am using to demonstrate this error:

    import dash
    import dash_html_components as html
    import dash_core_components as dcc

    app = dash.Dash()

    app.layout = html.Div([
        dcc.Input(id='my-input'),
        html.Div(id='my-output')
    ])


    @app.callback(dash.dependencies.Output('my-output', 'children'), [dash.dependencies.Input('my-input', 'value')])
    def update_output(input_value):
        raise Exception('error!')

    if __name__ == '__main__':
        app.run_server(debug=True)

2 - IPDB: There is an excellent debugger for (i)python called ipdb (pip install ipdb). You can insert a debugger statement in your callback functions with import ipdb; ipdb.set_trace() and that will launch an interactive session in your code for you. Here’s what it looks like in my terminal:

Here’s a good tutorial on IPDB: https://www.safaribooksonline.com/blog/2014/11/18/intro-python-debugger/

Frontend Debugging

1 - DevTools - If no error was raised in the backend code then there might’ve been an error in the front-end. These are harder to detect and a few things can cause errors:

  • There could be a genuine bug in Dash. In this case, try to isolate your example into something extremely simple and create an issue at https://github.com/plotly/dash/issues
  • The data that you are returning from your callback isn’t in the right form. In this case, print out the data that you’re returning in your callback and visually inspect it.

One way to check for errors in the front-end is to open up your browser’s “Dev Tools” environment. Chrome is recommended here. Uncaught errors are printed out in red. Here is what chrome devtools looks like with a few errors:

2 - Debugging Styling
Your app may not look exactly how you want it to look and the feedback cycle from modifying Dash code to seeing the updated app in your browser can take a few seconds which can feel like a long time if you’re making hundreds of edits. I recommend two prototyping environments:
1- Chrome Devtools: With DevTools you can modify the Dash app’s HTML CSS classes or the HTML component’s style directly without refreshing your browser. You can manually copy over those styles or classes into your Dash app code when your satisfied with it. Here’s a good tutorial on editing styles: https://developers.google.com/web/tools/chrome-devtools/inspect-styles/
2- CodePen: I have a Dash styleguide on CodePen here: https://codepen.io/chriddyp/pen/bWLwgP. You can fork this styleguide and prototype a rough outline of your app in HTML and then manually port those changes over to your Dash code. You’re free to modify the CSS as well!

Chart Debugging

1 - plotly.graph_objs - Plotly graphs (dash_core_components.Graph) are described declaratively through the figure property. This property is composed of a set of dictionaries with special keys like x, y, marker, name, etc that completely describe what the graph looks like.
There are two ways to describe a graph.
1 - You can use just regular dict and list objects like: figure={'data': [{'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar'}]
2 - You can use plotly.graph_objs, which subclass dict and list but provide validation around the keys. With graph_objs, that example would look like plotly.graph_objs.Bar(x=[1, 2, 3], y=[4, 1 2]).

The nice thing about plotly.graph_objs is that it does validation. If you specify a key that isn’t valid, then it’ll raise an error. Using dict or a list will not raise errors. Here is a simple example:

>>> go.Bar(xx=[1, 2, 3])
---------------------------------------------------------------------------
PlotlyDictKeyError                        Traceback (most recent call last)
<ipython-input-5-f7e181fdb056> in <module>()
----> 1 go.Bar(xx=[1, 2, 3])

/Users/chriddyp/Repos/dash-stuff/dash-sandbox/vv/lib/python2.7/site-packages/plotly/graph_objs/graph_objs.pyc in __init__(self, *args, **kwargs)
    375         d = {key: val for key, val in dict(*args, **kwargs).items()}
    376         for key, val in d.items():
--> 377             self.__setitem__(key, val, _raise=_raise)
    378
    379     def __dir__(self):

/Users/chriddyp/Repos/dash-stuff/dash-sandbox/vv/lib/python2.7/site-packages/plotly/graph_objs/graph_objs.pyc in __setitem__(self, key, value, _raise)
    426                 if _raise:
    427                     path = self._get_path() + (key, )
--> 428                     raise exceptions.PlotlyDictKeyError(self, path)
    429                 return
    430

PlotlyDictKeyError: 'xx' is not allowed in 'bar'

Path To Error: ['xx']

Valid attributes for 'bar' at path [] under parents []:

    ['bardir', 'base', 'basesrc', 'dx', 'dy', 'error_x', 'error_y',
    'hoverinfo', 'hovertext', 'hovertextsrc', 'insidetextfont',
    'legendgroup', 'marker', 'name', 'offset', 'offsetsrc', 'opacity',
    'orientation', 'outsidetextfont', 'r', 'rsrc', 'showlegend', 'stream',
    't', 'text', 'textfont', 'textposition', 'textpositionsrc', 'textsrc',
    'tsrc', 'type', 'uid', 'visible', 'width', 'widthsrc', 'x', 'x0',
    'xaxis', 'xcalendar', 'xsrc', 'y', 'y0', 'yaxis', 'ycalendar', 'ysrc']

Run `<bar-object>.help('attribute')` on any of the above.
'<bar-object>' is the object at []

2 - Online Chart Editor: We have built an online chart editor GUI for creating Plotly graphs: https://plot.ly/create. This chart editor using the same underlying libraries that dash_core_components.Graph and features a “JSON Editor” that displays the JSON representation of the chart that you’re editing. If your graph isn’t quite looking the way you want it to, then I highly recommend creating and editing the chart on https://plot.ly/create and then exporting the code into your Dash app.


Finally, Plotly does training and has a team that is available for one-on-one support if you’re company has the resources (support contracts here: https://support.plot.ly/libraries/python, contact the sales team here: https://plot.ly/products/consulting-and-oem/)

6 Likes

Thank you, that was super informative. I think that for people who are creating dashboards coming from a scientific stack, these tips are invaluable because it is hard to find where all this stuff lives.

1 Like

Definitely. These are great suggestions. I’ll wrap this up into a “debugging” chapter in the user guide soon :slight_smile:

I really like the online chart editor. On GitHub

The Link doesn’t work anymore.
I’m not sure which tutorial it’s referring to, but I found this helpful:

&

http://www.christianlong.com/blog/ipdb-the-ipython-debugger.html