import pandas as pd
import panel as pn
import plotly.express as px
import plotly.io as pio
import plotly.graph_objects as go
pn.extension("plotly", sizing_mode="stretch_width")
In this example we will show how to style Plotly plots with Panel for both the default
and the dark
theme.
When we use the Fast templates the theme
can be found in the session_args
.
def get_theme():
return pn.state.session_args.get("theme", [b'default'])[0].decode()
theme=get_theme()
theme
Below we create some functionality to cycle through a list of nice accent colors. You would probably just set the accent_color
and color
for your specific use case.
nice_accent_colors = [
("#00A170", "white"), # Mint
("#DAA520", "white"), # Golden Rod
("#F08080", "white"), # Light Coral
("#4099da", "white"), # Summery Sky
("#2F4F4F", "white"), # Dark Slate Grey
("#A01346", "white"), # Fast
]
def get_nice_accent_color():
"""Returns the 'next' nice accent color"""
if not "color_index" in pn.state.cache:
pn.state.cache["color_index"]=0
elif pn.state.cache["color_index"]==len(nice_accent_colors)-1:
pn.state.cache["color_index"]=0
else:
pn.state.cache["color_index"]+=1
return nice_accent_colors[pn.state.cache["color_index"]]
accent_color, color = get_nice_accent_color()
pn.pane.Markdown(f"# Color: {accent_color}", background=accent_color, height=70, margin=0, style={"color": color, "padding": "10px"})
Plotly provides a list of built in templates in plotly.io.templates
. See the Plotly Templates Guide.
Let's define a Select
widget to explore the templates. We will set the default value to plotly
or plotly_dark
depending on the theme.
plotly_template = pn.widgets.Select(options=sorted(pio.templates))
if theme=="dark":
plotly_template.value="plotly_dark"
else:
plotly_template.value="plotly"
Plotly Express provides a template
argument. Let's try to use it.
data = pd.DataFrame(
[
("Monday", 7),
("Tuesday", 4),
("Wednesday", 9),
("Thursday", 4),
("Friday", 4),
("Saturday", 4),
("Sunay", 4),
],
columns=["Day", "Orders"],
)
def get_express_plot(template=plotly_template.value, accent_color=accent_color):
fig = px.line(
data,
x="Day",
y="Orders",
template=template,
color_discrete_sequence=(accent_color,),
title=f"Orders: '{template}' theme"
)
fig.update_traces(mode="lines+markers", marker=dict(size=10), line=dict(width=4))
fig.layout.autosize = True
return fig
Let's bind get_express_plot
to the plotly_template
widget and lay out the two in a Column
.
get_express_plot=pn.bind(get_express_plot, template=plotly_template)
express_plot=pn.pane.panel(get_express_plot, config={"responsive": True}, sizing_mode="stretch_both", name="EXPRESS")
pn.Column(plotly_template, express_plot, sizing_mode="stretch_both")
You can set the theme of a Plotly Graph Objects Figure via the update_layout
method.
z_data = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv")
def get_go_plot(template=plotly_template.value, accent_color=accent_color):
figure = go.Figure(
data=go.Surface(z=z_data.values),
layout=go.Layout(
title="Mt Bruno Elevation",
))
figure.layout.autosize = True
figure.update_layout(template=template, title="Mt Bruno Elevation: '%s' theme" % template)
return figure
Letss bind get_go_plot
to the plotly_template
widget and lay everything using Tabs
and Column
.
get_go_plot=pn.bind(get_go_plot, template=plotly_template)
go_plot=pn.pane.panel(get_go_plot, config={"responsive": True}, sizing_mode="stretch_both", name="GRAPH OBJECTS")
pn.Column(plotly_template, go_plot, min_height=600)
Here we use the FastGridTemplate
template = pn.template.FastGridTemplate(
site="Panel",
title="Styling Plotly",
sidebar=[plotly_template],
accent_base_color=accent_color,
header_background=accent_color,
header_color=color,
row_height=70,
save_layout=True, prevent_collision=True,
)
template.main[0:1,:]=plotly_template
template.main[1:10,0:6]=express_plot
template.main[1:10,6:12]=go_plot
template.servable();
You can serve the app via panel serve PlotlyStyle.ipynb
and find it at http://localhost:5006/PlotlyStyle
. You should add the --autoreload
flag while developing for hot reloading.