{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import panel as pn\n", "\n", "import plotly.express as px\n", "import plotly.io as pio\n", "import plotly.graph_objects as go\n", "\n", "pn.extension(\"plotly\", sizing_mode=\"stretch_width\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Styling Plotly for Panel\n", "\n", "In this example we will show how to style Plotly plots with Panel for both the `default` and the `dark` theme.\n", "\n", "![PlotlyStyle.gif](https://assets.holoviews.org/panel/thumbnails/gallery/styles/plotly-styles.gif)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Get or set the theme\n", "\n", "When we use the Fast templates the `theme` can be found in the `session_args`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def get_theme():\n", " return pn.state.session_args.get(\"theme\", [b'default'])[0].decode()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "theme=get_theme()\n", "theme" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Select a nice accent color\n", "\n", "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." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "nice_accent_colors = [\n", " (\"#00A170\", \"white\"), # Mint\n", " (\"#DAA520\", \"white\"), # Golden Rod\n", " (\"#F08080\", \"white\"), # Light Coral\n", " (\"#4099da\", \"white\"), # Summery Sky\n", " (\"#2F4F4F\", \"white\"), # Dark Slate Grey\n", " (\"#A01346\", \"white\"), # Fast\n", "]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def get_nice_accent_color():\n", " \"\"\"Returns the 'next' nice accent color\"\"\"\n", " if not \"color_index\" in pn.state.cache:\n", " pn.state.cache[\"color_index\"]=0\n", " elif pn.state.cache[\"color_index\"]==len(nice_accent_colors)-1:\n", " pn.state.cache[\"color_index\"]=0\n", " else:\n", " pn.state.cache[\"color_index\"]+=1\n", " return nice_accent_colors[pn.state.cache[\"color_index\"]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "accent_color, color = get_nice_accent_color()\n", "pn.pane.Markdown(f\"# Color: {accent_color}\", background=accent_color, height=70, margin=0, style={\"color\": color, \"padding\": \"10px\"})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plotly\n", "\n", "Plotly provides a list of built in templates in `plotly.io.templates`. See the [Plotly Templates Guide](https://plotly.com/python/templates/).\n", "\n", "Let's define a [`Select`](https://panel.holoviz.org/reference/widgets/Select.html) widget to explore the templates. We will set the default value to `plotly` or `plotly_dark` depending on the theme." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plotly_template = pn.widgets.Select(options=sorted(pio.templates))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if theme==\"dark\":\n", " plotly_template.value=\"plotly_dark\"\n", "else:\n", " plotly_template.value=\"plotly\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plotly Express\n", "\n", "Plotly Express provides a `template` argument. Let's try to use it." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "data = pd.DataFrame(\n", " [\n", " (\"Monday\", 7),\n", " (\"Tuesday\", 4),\n", " (\"Wednesday\", 9),\n", " (\"Thursday\", 4),\n", " (\"Friday\", 4),\n", " (\"Saturday\", 4),\n", " (\"Sunay\", 4),\n", " ],\n", " columns=[\"Day\", \"Orders\"],\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def get_express_plot(template=plotly_template.value, accent_color=accent_color):\n", " fig = px.line(\n", " data,\n", " x=\"Day\",\n", " y=\"Orders\",\n", " template=template,\n", " color_discrete_sequence=(accent_color,),\n", " title=f\"Orders: '{template}' theme\"\n", " )\n", " fig.update_traces(mode=\"lines+markers\", marker=dict(size=10), line=dict(width=4))\n", " fig.layout.autosize = True\n", " return fig" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's [bind](https://panel.holoviz.org/user_guide/APIs.html#reactive-functions) `get_express_plot` to the `plotly_template` widget and lay out the two in a `Column`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "get_express_plot=pn.bind(get_express_plot, template=plotly_template)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "express_plot=pn.pane.panel(get_express_plot, config={\"responsive\": True}, sizing_mode=\"stretch_both\", name=\"EXPRESS\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pn.Column(plotly_template, express_plot, sizing_mode=\"stretch_both\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plotly Graph Objects Figure\n", "\n", "You can set the theme of a Plotly Graph Objects Figure via the `update_layout` method." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "z_data = pd.read_csv(\"https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def get_go_plot(template=plotly_template.value, accent_color=accent_color):\n", " figure = go.Figure(\n", " data=go.Surface(z=z_data.values),\n", " layout=go.Layout(\n", " title=\"Mt Bruno Elevation\",\n", " ))\n", " figure.layout.autosize = True\n", " figure.update_layout(template=template, title=\"Mt Bruno Elevation: '%s' theme\" % template)\n", " return figure" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Letss [bind](https://panel.holoviz.org/user_guide/APIs.html#reactive-functions) `get_go_plot` to the `plotly_template` widget and lay everything using `Tabs`and `Column`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "get_go_plot=pn.bind(get_go_plot, template=plotly_template)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "go_plot=pn.pane.panel(get_go_plot, config={\"responsive\": True}, sizing_mode=\"stretch_both\", name=\"GRAPH OBJECTS\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pn.Column(plotly_template, go_plot, min_height=600)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Wrap it up in a nice template\n", "\n", "Here we use the [`FastGridTemplate`](https://panel.holoviz.org/reference/templates/FastListTemplate.html#templates-gallery-fastgridtemplate)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "template = pn.template.FastGridTemplate(\n", " site=\"Panel\",\n", " title=\"Styling Plotly\",\n", " sidebar=[plotly_template],\n", " accent_base_color=accent_color,\n", " header_background=accent_color,\n", " header_color=color,\n", " row_height=70, \n", " save_layout=True, prevent_collision=True,\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "template.main[0:1,:]=plotly_template\n", "template.main[1:10,0:6]=express_plot\n", "template.main[1:10,6:12]=go_plot" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "template.servable();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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*." ] } ], "metadata": { "language_info": { "name": "python", "pygments_lexer": "ipython3" } }, "nbformat": 4, "nbformat_minor": 5 }