4

I am trying not the show the defult dcc.graph when the app runs. I just want to show my graph when app runs

enter image description here

Here is my code,

App layout

dbc.Row([
    dbc.Col([
        dcc.Graph(id='datatable-upload-graph', responsive=True, style={
            'display': 'block'
        })
    ], xs=10, sm=8, md=5, lg=6, xl=5)
])

Callbacks and methods

@app.callback(
Output('datatable-upload-graph', 'figure'),
Input('container-datatable', 'data')
)
def display_gantt(container_datatable):
    df = pd.DataFrame(container_datatable)

    df['Start Date'] = pd.to_datetime(df['Start Date'], errors='coerce')
    df['End Date'] = pd.to_datetime(df['End Date'], errors='coerce')

    fig = px.timeline(df, x_start="Start Date", x_end="End Date", y="Project Name", color="Status")
    fig.update_yaxes(autorange="reversed")

    if container_datatable is None:
        return []
    else:
        return fig

app.config['suppress_callback_exceptions'] = True
if __name__ == '__main__':
    app.run_server(debug=True, use_reloader=False)
Delal
  • 87
  • 1
  • 10
  • Does the graph automatically load up after a little bit of time or is there a user-interaction that needs to take place in order to load the values into the graph? – AS11 Mar 15 '21 at 12:50
  • Yes @as11 there is a button to upload to dateset , after uploading the dateset it takes a little bit of time to show the the graph – Delal Mar 15 '21 at 13:41
  • So do you want the data to show up immediately or not have the blank graph there and have it generated after the button is clicked? – AS11 Mar 15 '21 at 14:05
  • I just don't want to have a blank graph and generates after the button is clicked @as11 – Delal Mar 15 '21 at 14:37
  • 2
    https://stackoverflow.com/questions/63811550/plotly-how-to-display-graph-after-clicking-a-button - This should be able to help – AS11 Mar 15 '21 at 14:40
  • Thanks it worked @as11 – Delal Mar 15 '21 at 17:14
  • 1
    @Delal While the linked resource does indeed prevent the problem, it does not *solve* the problem. Nor does it explain what's really going on here. Hopefully, the suggestion I've just posted will do exactly that. Please let me know how it works out for you. – vestland Mar 21 '21 at 23:48

1 Answers1

9

The essence:

Just make sure to not leave the figure attribute of dcc.Graph unspecified, but rather, for example, like this:

dcc.Graph(id='datatable-upload-graph', figure = blank_figure())

Where blank_figure() is a figure that is not only empty like in the default version, but stripped of all visible features.


The details:

In your app layout you've set up your dcc.Graph as:

dcc.Graph(id='datatable-upload-graph', responsive=True, style={
    'display': 'block'
})

What you're missing here is a specification for the figure attribute. Your app will work perfectly fine without it, but you will end up with that empty figure until you've managed to populate the figure object through one of your callbacks. And for longer loading times the empty figure will become visible.

But you can remedy this by specifying a completely blank figure like:

dcc.Graph(id='datatable-upload-graph', figure = blank_figure())

where blank_figure() is this:

def blank_fig():
    fig = go.Figure(go.Scatter(x=[], y = []))
    fig.update_layout(template = None)
    fig.update_xaxes(showgrid = False, showticklabels = False, zeroline=False)
    fig.update_yaxes(showgrid = False, showticklabels = False, zeroline=False)
    
    return fig

The code snippet below will let you test this with a random data sample. The app itself is pretty neat as well (in all modesty). Nothing too fancy, but it will let you check out some templates available for your figures through fig.update_layout(template = <template>)

Without including figure = blank_figure() in dcc.Graph, the app will look like this for a brief moment:

enter image description here

And with figure = blank_figure() the app will look like this:

enter image description here

And when the simulations have come to an end the app will look like this:

enter image description here

And now you can easily take a look at how the figure will look like using the different templates, like 'plotly_dark':

enter image description here

Just switch between commenting out these two lines to see the effects in the complete snippet below.

dcc.Graph(id="graph", figure = blank_fig())
# dcc.Graph(id="graph")

Complete code:

import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go

import dash
import dash_core_components as dcc
import dash_html_components as html
from jupyter_dash import JupyterDash
from dash.dependencies import Input, Output


templates = ['plotly', 'seaborn', 'simple_white', 'ggplot2',
             'plotly_white', 'plotly_dark', 'presentation', 'xgridoff',
             'ygridoff', 'gridon', 'none']

def blank_fig():
    fig = go.Figure(go.Scatter(x=[], y = []))
    fig.update_layout(template = None)
    fig.update_xaxes(showgrid = False, showticklabels = False, zeroline=False)
    fig.update_yaxes(showgrid = False, showticklabels = False, zeroline=False)
    
    return fig

# startfig = blank_fig()

# Dash
app = JupyterDash(__name__)
app.layout = html.Div([
                        dcc.RadioItems(
                            id='template_radio',
                            options=[{'label': k, 'value': k} for k in templates],
                            value=templates[0]
                        ),

                        html.Hr(),
                        html.Div(id='display_templates'),
                        dcc.Graph(id="graph", figure = blank_fig())
#                         dcc.Graph(id="graph")

])

# Make a figure with selected template
@app.callback(Output('graph', 'figure'),
             [Input('template_radio', 'value')])
def make_graph(template):
    np.random.seed(1)
    start = 2021
    ncols = 50
    nrows = 100
    cols = [str(i) for i in np.arange(start, start+ncols)]
    df = pd.DataFrame(np.random.randint(-2,3, (nrows,ncols)), columns = cols).cumsum()
    df.iloc[0] = 0

    # figure
    fig = px.line(df, x=df.index, y=cols)
    fig.update_layout(template = template)

    return fig

app.run_server(mode='inline', port = 8070, dev_tools_ui=True,
          dev_tools_hot_reload =True, threaded=True)
vestland
  • 55,229
  • 37
  • 187
  • 305
  • 1
    Thank you so much for the solution. As soon as I clicked the button, it was showing the default graph, but now it works just the way I want it – Delal Mar 25 '21 at 11:53
  • 1
    @Delal You're welcome! Glad it worked for you! – vestland Mar 25 '21 at 11:55