Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to save a Dash layout to an HTML file

I am trying to save a Dash layout in an HTML file, but I couldn’t find a way to achieve this. Strange enough it is quite easy to save a single Plotly figure, but not a Dash layout. Does anyone have a solution?

I saw this question has already an answer here https://stackoverflow.com/a/51013594/3057377, but I don’t understand it. Especially the note about the interactivity loss. One can see that interactivity is kept when saving a single plot, so it should be the same for an entire layout.

Here are the things I already tried:

import dash_core_components as dcc
import dash_html_components as html
import dash
import plotly as py
import plotly.graph_objs as go

# Create two figures.
fig1 = go.Figure(data=go.Scatter(x=[0, 1, 2], y=[0, 10, 0]))
fig2 = go.Figure(data=go.Scatter(x=[0, 1, 2], y=[0, -10, 0]))

# Write fig1 to HTML. The three methods below work.
py.io.write_html(fig1, file="fig1_a.html", auto_open=True)
fig1.write_html(file="fig1_b.html", auto_open=True)
py.offline.plot(fig1, filename='fig1_c.html', auto_open=True)

# Write fig2 to HTML. The three methods below work.
py.io.write_html(fig2, file="fig2_a.html", auto_open=True)
fig2.write_html(file="fig2_b.html", auto_open=True)
py.offline.plot(fig2, filename='fig2_c.html', auto_open=True)


# Now create a layout that will be displayed in an HTML page.
app = dash.Dash(__name__)
app.layout = html.Div([dcc.Graph(id="fig1", figure=fig1),
                       dcc.Graph(id="fig2", figure=fig2)])

# Trying to save the layout to HTML doesn’t work with the same three methods as above.
print("############  1")
try:
    py.io.write_html(app.layout, file="app_layout_a.html", auto_open=True)
except Exception as e:
    print(e)

print("############  2")
try:
    app.layout.write_html(file="app_layout_c.html", auto_open=True)
except Exception as e:
    print(e)

print("############  3")
try:
    py.offline.plot(app.layout, filename='app_layout_b.html')
except Exception as e:
    print(e)

# But the layout displays correctly when served by Dash.
app.run_server(debug=True)

like image 583
nico Avatar asked Feb 09 '20 16:02

nico


Video Answer


2 Answers

You can save the HTML code that contains the graph's information into a variable. In order to plot the graph, you can use html.Iframe from dash_html_components. If the graph is generated inside a Dash callback you can return that variable or the Iframe as the output of the callback.

I also share how I save plotly figures to HTML. The plot remains interactive and the HTML file is considerably lighter than other alternatives (like fig.write_html() ).

with open('plot.html', 'w') as f:
    f.write(fig.to_html(full_html=False, include_plotlyjs='cdn'))

Here is a minimum working example in a Dash application. In this case, the figure is in a callback because each time you click in the bottom "Rotate" the figure is updated and rotates the tick labels. This app is a modification from the Plotly Docs:

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px

df = px.data.tips()

app = dash.Dash(__name__)

app.layout = html.Div([
    html.Button("Rotate", id='button', n_clicks=0), 
    html.Div(id="output", children=[])
])

@app.callback(
    Output('output', 'children'), # The output will be displayed in  html.Div(id="output)
    [Input("button", "n_clicks")])
def rotate_figure(n_clicks):
    fig = px.histogram(df, x="sex", height=500)
    fig.update_xaxes(tickangle=n_clicks*45)

    # The plotly figure is saved as HTML in a variable
    html_data = fig.to_html(full_html=False, include_plotlyjs='cdn')
    
    # The variable is then displayed as a plot using Iframe from dash_html_components
    html_plot = html.Iframe(srcDoc = html_data, 
                            style = {"height": "1000px", 
                                     "width": "1000px",
                                     "display":"flex",
                                     "align-items": "center", 
                                     "justify-content":  "center"}
                            )
    
    # Now you can return the Iframe as a children of a Div
    return html_plot

app.run_server(debug=True)



like image 170
Álvaro H.G Avatar answered Sep 17 '22 14:09

Álvaro H.G


Simply use the following command:

fig.write_html("path/to/file.html")
like image 40
Hatem Elattar Avatar answered Sep 19 '22 14:09

Hatem Elattar