Eli Turasky
Eli Turasky

Reputation: 1061

Dash app has no errors, but does not plot

I have some long convoluted code that seems to be executing properly, but is not plotting. What is going on here?

The data that is being plotted is a nested dictionary, with each key in the dictionary corresponding to a dropdown option. Here is some of the core code:

from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State, ClientsideFunction
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
from pandas import Timestamp
import plotly.graph_objs as go
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import numpy as np
import pandas as pd
import numpy as np
from datetime import timedelta
import glob
import datetime as dt

enter image description here

Edit3: I fixed the callback issue and was able load in the data from the dcc.Store, which was just a date object. Now, I load in and format my data using that date object, which results in final_dict. However, the data still doesn't want to plot with my code afterwards.

I am confused why this isn't working.

app = JupyterDash(external_stylesheets=[dbc.themes.SLATE])
controls = dbc.Card(
    [dcc.Store(id='date_output'),
         dbc.FormGroup([
                dcc.DatePickerSingle(
                    id='my-date-picker-single',
                    min_date_allowed=dt.date(2018, 4, 17),
                    max_date_allowed=dt.date(2020, 10, 6),
                    initial_visible_month=dt.date(2020, 10, 6),
                    date=dt.date(2020, 10, 6)
            ),
        ],
    ),
        dbc.FormGroup(
                dcc.RadioItems(
                    id='hour_radio',
                    options=[{'label': '00z', 'value': '00z'},
                            {'label': '12z', 'value': '12z'}],
                    value='00z',
                    labelStyle={'display': 'inline-block'},
                    inputStyle={"margin-left": "15px","margin-right": "5px"}
                ),
            ),


       dbc.FormGroup(
            [dbc.Label("Model"),
                dcc.Dropdown(
                    id='model_dd',
                    options=[{'label': k, 'value': k} for k in model_list],
                    value=model_list[0],
                    clearable=False
                ),
            ]
        ),
        dbc.FormGroup(
            [dbc.Label("Crop"),
                dcc.Dropdown(
                    id='crop_dd',
                    options=[{'label': i.title(), 'value': i} for i in crop_list],
                    value=crop_list[0],
                    clearable=False
                ),
            ]
        ),           
        dbc.FormGroup(
            [dbc.Label("Weighting"),
                dcc.Dropdown(
                    id='weight_dd',
                    options=[{'label': i, 'value': i} for i in weight_list],
                    value=weight_list[0],
                    clearable=False
                ),
            ]
        ),
        dbc.FormGroup(
            [dbc.Label("Forecast Variable"),
                dcc.Dropdown(
                    id='columns_dd',
                    options=[{'label': i, 'value': i} for i in column_list],
                    value=column_list[0],
                    clearable=False
                ),
            ]
        ),
         dbc.FormGroup(
                dcc.RadioItems(
                    id='units_radio',
                    options=[{'label': 'Metric', 'value': 'Metric'},
                            {'label': 'Imperial', 'value': 'Imperial'}],
                    value='Metric',
                    labelStyle={'display': 'inline-block'},
                    inputStyle={"margin-left": "20px","margin-right": "5px"}
                ),
        ),

    ],
    body=True,
)


app.layout = dbc.Container(
    [
        html.Hr(),
        dbc.Row([
            dbc.Col([
                dbc.Row([
                    dbc.Col(controls)
                ],  align="start"), 
            ],xs = 2)
            ,
            dbc.Col([
                dbc.Row([
                    dbc.Col([html.Div(id = 'plot_title')],)
                ]),
                dbc.Row([
                    dbc.Col(dcc.Graph(id="crop-graph")),
                ]),
                dbc.Row([
                    dbc.Col([html.Div(id = 'date_picker')],)
                ]),
            ])
        ],), 
    ],
    fluid=True,
)



@app.callback(
    Output('date_output', 'data'),
    [Input('my-date-picker-single', 'date'),
     Input('hour_radio', 'value')])
    
    
def update_output(data, radio2):
    if radio2=='00z':
        data = pd.to_datetime(data)
    
    elif radio2=='12z':
        data = pd.to_datetime(data)
        data=data+dt.timedelta(hours=12)
    return data

 @app.callback(
    Output('crop-graph', 'figure'),
    [Input('model_dd', 'value'),
     Input('weight_dd', 'value'),
     Input('crop_dd', 'value'),
     Input('columns_dd', 'value'),
     Input('units_radio', 'value'),
     Input('date_output', 'data')])
    
def make_graph(model, weight, available_crops, vals, radio, data):
#do data formatting here, and end up with final_dict
    if radio=='Metric':
        if weight == 'Production':
            
            df_delta_prod_temp = pd.concat([final_dict[model][weight][available_crops]['time'], final_dict[model][weight][available_crops]['24h Delta Temp']], axis=1).set_index('time').resample('24h').mean().reset_index()
            df_delta_prod_precip = pd.concat([final_dict[model][weight][available_crops]['time'], final_dict[model][weight][available_crops]['24h Delta Precip']], axis=1).set_index('time').resample('24h').mean().reset_index()
            
            if vals=='Temperature':
                fig.add_trace(go.Scatter(x=final_dict[model][weight][available_crops]['time'], y=final_dict[model][weight][available_crops][vals]-273,
                                        mode = 'lines', line=dict(color='red', width=4),
                                        hovertemplate='Date: %{x|%d %b %H%M} UTC<br>Temp: %{y:.2f} C<extra></extra>'), secondary_y=True)
                fig.add_trace(go.Bar(x=df_delta_prod_temp['time']['time'],
                                 y=df_delta_prod_temp['24h Delta Temp'],
                                 marker_color = "white", opacity=1,hovertemplate='Date: %{x|%d %b}<br>Delta: %{y:.2f} C<extra></extra>'),
                          secondary_y=False)
                fig.update_yaxes(title_text="<b>Temp (C)<b>", color='red', secondary_y=True)
                fig.update_yaxes(title_text="<b>24hr Forecast Change (C)</b>", secondary_y=False)
     print(fig)
     return fig

   
app.run_server(mode='external', port = 4100, debug=True)

final_dict is in the form of final_dict[model_key][weight_keys][crop_key][value_key][dataframe] I am getting this error: ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all(). This is being triggered on the line if vals=='Temperature'. I am using the if statement here so that I can properly format the plot (as you can see in the lines following the plot command), as plotting for the 3 variables (Temperature, Total Precip, and Total Snow) will all be different. How can I fix this? Here is a print out of a the dataframe at the end of the nested dict:

24h Delta Temp  Temperature  Total Snow  24h Delta Precip  Total Precip  \
0         0.498935   290.315356         NaN               NaN           NaN   
1         0.237127   285.985779    0.000000          0.000866      0.006311   
2         0.328559   283.643185    0.000000          0.003557      0.013087   
3         0.749757   295.701362    0.000000          0.006307      0.015658   
4         0.888228   293.332520    0.000000         -0.000009      0.005487   
..             ...          ...         ...               ...           ...   
56       -2.917237   285.034693    0.009300          0.161451      0.523343   
57             NaN   281.955112    0.010279               NaN      0.729168   
58             NaN   280.365132    0.013355               NaN      0.605418   
59             NaN   287.087138    0.012851               NaN      0.522774   
60             NaN   284.684470    0.006231               NaN      0.459217   

                  time  
0  2020-10-06 00:00:00  
1  2020-10-06 06:00:00  
2  2020-10-06 12:00:00  
3  2020-10-06 18:00:00  
4  2020-10-07 00:00:00  
..                 ...  
56 2020-10-20 00:00:00  
57 2020-10-20 06:00:00  
58 2020-10-20 12:00:00  
59 2020-10-20 18:00:00  
60 2020-10-21 00:00:00 

Upvotes: 1

Views: 1142

Answers (1)

coralvanda
coralvanda

Reputation: 6616

You never define final_dict

Edit: updated answer and code example to respond to further discussion

@app.callback(
    Output('date_output', 'data'),
    [Input('my-date-picker-single', 'date'),
     Input('hour_radio', 'value')])
def update_output(date_value, radio2):
    final_dict = {
        'tempurature': {0: 1, 1: 5, 2: 3, 3: 5, 4: 1, 5: 2, 6: 5, 7: 6},
        # and so on
    }
    return final_dict

This function needs to define that variable, otherwise it's just going to return None. Be careful of your indentation as well, because the way this is set up would prevent the second if statement from ever executing, and would ALWAYS return at the first return statement.

Also, you don't need the parens, you can just do return final_dict.

Your second callback, which outputs to the figure, is taking in the data from the dcc.Store correctly, but you don't ever use it. That Input corresponds to the data arg you defined in the callback function's signature. You should replace uses of final_dict in that function with data.

Upvotes: 2

Related Questions