{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "4a53dc53", "metadata": {}, "outputs": [], "source": [ "import seaborn as sns\n", "import panel as pn\n", "import matplotlib.font_manager\n", "\n", "from matplotlib.figure import Figure\n", "\n", "pn.extension(sizing_mode=\"stretch_width\", template=\"fast\")" ] }, { "cell_type": "markdown", "id": "111cd4bf", "metadata": {}, "source": [ "## Styling Seaborn for Panel\n", "\n", "In this example we will show how to style Seaborn charts with Panel for both the `default` and the `dark` theme.\n", "\n", "![SeabornStyle.gif](https://assets.holoviews.org/panel/thumbnails/gallery/styles/seaborn-styles.gif)" ] }, { "cell_type": "markdown", "id": "90401993", "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, "id": "b1229000", "metadata": {}, "outputs": [], "source": [ "def get_theme():\n", " return pn.state.session_args.get(\"theme\", [b'default'])[0].decode()\n", "\n", "theme = get_theme()\n", "theme" ] }, { "cell_type": "markdown", "id": "95f41cda", "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, "id": "f14848e8", "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, "id": "93da9812", "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, "id": "a7239a9e", "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", "id": "37ed9768", "metadata": {}, "source": [ "## Seaborn: `set_theme`\n", "\n", "You can set the `style`, `palette` and `font` using `sns.set_theme`. See https://seaborn.pydata.org/generated/seaborn.set_theme.html." ] }, { "cell_type": "code", "execution_count": null, "id": "7a34b38e-06fd-4509-aeb0-451d6e03e76d", "metadata": {}, "outputs": [], "source": [ "def plot(style=\"white\", palette=\"deep\", font=\"sans-serif\", theme=\"default\", rc={}):\n", " sns.set_theme(style=style, palette=palette, font=font, rc=rc)\n", " \n", " fig = Figure(figsize=(12, 6))\n", " ax = fig.add_subplot(111)\n", "\n", " sns.barplot(x=[\"A\", \"B\", \"C\"], y=[1, 3, 2], ax=ax)\n", " return fig" ] }, { "cell_type": "markdown", "id": "e532b213-ae59-44e1-8d1f-289585796ef9", "metadata": {}, "source": [ "Lets's add the Seaborn logo to the app" ] }, { "cell_type": "code", "execution_count": null, "id": "e1f6d68a-49c5-4dbc-bde5-89b8b21f3962", "metadata": {}, "outputs": [], "source": [ "pn.Row(\n", " pn.layout.HSpacer(),\n", " pn.pane.SVG(\n", " \"https://seaborn.pydata.org/_images/logo-tall-lightbg.svg\",\n", " sizing_mode=\"fixed\",\n", " width=210,\n", " ),\n", " pn.layout.HSpacer(),\n", ").servable(target=\"sidebar\")" ] }, { "cell_type": "markdown", "id": "6c43cf6c-37fa-4bb8-9cd4-dbab335fe9a8", "metadata": {}, "source": [ "We can use [`Select`](https://panel.holoviz.org/reference/widgets/Select.html) widgets to explore the `style`, `palette` and `font` arguments" ] }, { "cell_type": "code", "execution_count": null, "id": "a11d2e50-b4a8-4609-85be-e58e06bf0053", "metadata": {}, "outputs": [], "source": [ "STYLES = [\n", " \"dark\",\n", " \"ticks\",\n", " \"white\",\n", " \"whitegrid\",\n", "]\n", "PALETTES = [\n", " \"bright\",\n", " \"colorblind\",\n", " \"dark\",\n", " \"deep\",\n", " \"hls\",\n", " \"husl\",\n", " \"muted\",\n", " \"pastel\",\n", " f\"dark:{accent_color}\",\n", " f\"light:{accent_color}\",\n", "]\n", "if theme == \"dark\":\n", " PALETTE = f\"light:{accent_color}\"\n", "else:\n", " PALETTE = f\"dark:{accent_color}\"\n", "\n", "FONTS = sorted(set([f.name for f in matplotlib.font_manager.fontManager.ttflist]))\n", "\n", "if theme==\"dark\":\n", " RC = {\n", " \"axes.labelcolor\": \"white\",\n", " \"axes.facecolor\": \"black\",\n", " \"figure.facecolor\": \"black\",\n", " \"xtick.color\": \"white\",\n", " \"ytick.color\": \"white\",\n", " }\n", "else:\n", " RC = {}" ] }, { "cell_type": "code", "execution_count": null, "id": "19fa98dc", "metadata": {}, "outputs": [], "source": [ "style = pn.widgets.Select(name=\"Style\", value=\"white\", options=STYLES).servable(target=\"sidebar\")\n", "palette = pn.widgets.Select(name=\"Palette\", value=PALETTE, options=PALETTES).servable(\n", " target=\"sidebar\"\n", ")\n", "font = pn.widgets.Select(name=\"Font\", value=\"Verdana\", options=FONTS).servable(target=\"sidebar\")\n", "pn.Column(style, palette, font)" ] }, { "cell_type": "markdown", "id": "6ca4cb1b", "metadata": {}, "source": [ "Lets define a plot" ] }, { "cell_type": "markdown", "id": "514fcbf4-b1a5-47a0-b11b-d5be0c8a341f", "metadata": {}, "source": [ "We can *bind* the `plot`function to the widgets using `pn.bind`" ] }, { "cell_type": "code", "execution_count": null, "id": "46b39adf", "metadata": {}, "outputs": [], "source": [ "interactive_plot = pn.bind(plot, style=style, palette=palette, font=font, theme=theme, rc=RC)\n", "pn.panel(interactive_plot, sizing_mode=\"scale_width\").servable()" ] }, { "cell_type": "markdown", "id": "637fb93f", "metadata": {}, "source": [ "## Style the app template" ] }, { "cell_type": "code", "execution_count": null, "id": "5c5e0a45", "metadata": {}, "outputs": [], "source": [ "pn.state.template.param.update(\n", " site=\"Panel\", title=\"Styling Seaborn\", header_background=accent_color, accent_base_color=accent_color, favicon=\"https://raw.githubusercontent.com/mwaskom/seaborn/master/doc/_static/favicon.ico\",\n", ")" ] }, { "cell_type": "markdown", "id": "7d3d6d34-3f95-4b63-9646-ab572eff4435", "metadata": {}, "source": [ "## Serve the app" ] }, { "cell_type": "markdown", "id": "8cfb51b8", "metadata": {}, "source": [ "You can serve the app via `panel serve SeabornStyle.ipynb` and find it at http://localhost:5006/SeabornStyle. You should add the `--autoreload` flag while developing for *hot reloading*." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.7" } }, "nbformat": 4, "nbformat_minor": 5 }