{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import panel as pn\n", "pn.extension('plotly')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The ``Plotly`` pane renders Plotly plots inside a panel. It optimizes the plot rendering by using binary serialization for any array data found on the Plotly object, providing efficient updates. Note that to use the Plotly pane in a Jupyter notebook, the Panel extension has to be loaded with 'plotly' as an argument to ensure that Plotly.js is initialized.\n", "\n", "#### Parameters:\n", "\n", "For layout and styling related parameters see the [customization user guide](../../user_guide/Customization.ipynb).\n", "\n", "* **``object``** (object): The Plotly figure being displayed\n", "* **``click_data``** (dict): Click callback data\n", "* **``clickannotation_data``** (dict): Clickannotation callback data\n", "* **``config``** (dict): Config data\n", "* **``hover_data``** (dict): Hover callback data\n", "* **``link_figure``** (bool): Attach callbacks to the Plotly figure to update output when it is modified in place.\n", "* **``relayout_data``** (dict): Relayout callback data\n", "* **``restyle_data``** (dict): Restyle callback data\n", "* **``selected_data``** (dict): Selected callback data\n", "* **``viewport``** (dict): Current viewport state\n", "* **``viewport_update_policy``** (str, default = 'mouseup'): Policy by which the viewport parameter is updated during user interactions\n", " * ``mouseup``: updates are synchronized when mouse button is released after panning\n", " * ``continuoius``: updates are synchronized continually while panning\n", " * ``throttle``: updates are synchronized while panning, at intervals determined by the viewport_update_throttle parameter\n", "* **``viewport_update_throttle``** (int, default = 200, bounds = (0, None)): Time interval in milliseconds at which viewport updates are synchronized when viewport_update_policy is \"throttle\".\n", "\n", "___" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As with most other types ``Panel`` will automatically convert a Plotly figure to a ``Plotly`` pane if it is passed to the ``pn.panel`` function or a panel layout, but a ``Plotly`` pane can be constructed directly using the ``pn.pane.Plotly`` constructor:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import plotly.graph_objs as go\n", "\n", "xx = np.linspace(-3.5, 3.5, 100)\n", "yy = np.linspace(-3.5, 3.5, 100)\n", "x, y = np.meshgrid(xx, yy)\n", "z = np.exp(-(x-1)**2-y**2)-(x**3+y**4-x/5)*np.exp(-(x**2+y**2))\n", "\n", "surface = go.Surface(z=z)\n", "layout = go.Layout(\n", " title='Plotly 3D Plot',\n", " autosize=False,\n", " width=500,\n", " height=500,\n", " margin=dict(t=50, b=50, r=50, l=50)\n", ")\n", "fig = dict(data=[surface], layout=layout)\n", "\n", "plotly_pane = pn.pane.Plotly(fig)\n", "plotly_pane" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once created the plot can be updated by modifying the Plotly traces and then triggering an update by setting or triggering an event on the pane ``object``. Note that this only works if the ``Figure`` is defined as a dictionary, since Plotly will make copies of the traces, which means that modifying them in place has no effect. Modifying an array will send just the array using a binary protocol, leading to fast and efficient updates." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "surface.z = np.sin(z+1)\n", "plotly_pane.object = fig" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, modifying the plot ``layout`` will only modify the layout, leaving the traces unaffected." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig['layout']['width'] = 800\n", "\n", "plotly_pane.object = fig" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The Plotly pane supports layouts and subplots of arbitrary complexity, allowing even deeply nested Plotly figures to be displayed:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from plotly import subplots\n", "\n", "heatmap = go.Heatmap(\n", " z=[[1, 20, 30],\n", " [20, 1, 60],\n", " [30, 60, 1]],\n", " showscale=False)\n", "\n", "y0 = np.random.randn(50)\n", "y1 = np.random.randn(50)+1\n", "\n", "box_1 = go.Box(y=y0)\n", "box_2 = go.Box(y=y1)\n", "data = [heatmap, box_1, box_2]\n", "\n", "fig = subplots.make_subplots(\n", " rows=2, cols=2, specs=[[{}, {}], [{'colspan': 2}, None]],\n", " subplot_titles=('First Subplot','Second Subplot', 'Third Subplot')\n", ")\n", "\n", "fig.append_trace(box_1, 1, 1)\n", "fig.append_trace(box_2, 1, 2)\n", "fig.append_trace(heatmap, 2, 1)\n", "\n", "fig['layout'].update(height=600, width=600, title='i <3 subplots')\n", "fig = fig.to_dict()\n", "\n", "subplot_panel = pn.pane.Plotly(fig)\n", "subplot_panel" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Just like in the single-subplot case we can modify just certain aspects of a plot and then trigger an update. E.g. here we replace the overall title text:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig['layout']['title']['text'] = 'i <3 updating subplots'\n", "subplot_panel.object = fig" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lastly, Plotly plots can be made responsive using the `autosize` option on a Plotly layout:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import plotly.express as px\n", "\n", "data = pd.DataFrame([\n", " ('Monday', 7), ('Tuesday', 4), ('Wednesday', 9), ('Thursday', 4),\n", " ('Friday', 4), ('Saturday', 4), ('Sunay', 4)], columns=['Day', 'Orders']\n", ")\n", "\n", "fig = px.line(data, x=\"Day\", y=\"Orders\")\n", "fig.update_traces(mode=\"lines+markers\", marker=dict(size=10), line=dict(width=4))\n", "fig.layout.autosize = True\n", "\n", "responsive = pn.pane.Plotly(fig, config={'responsive': True})\n", "\n", "pn.Column('# A responsive plot', responsive, sizing_mode='stretch_width')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Controls\n", "\n", "The `Plotly` pane exposes a number of options which can be changed from both Python and Javascript try out the effect of these parameters interactively:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pn.Row(responsive.controls(jslink=True), responsive)" ] } ], "metadata": { "language_info": { "name": "python", "pygments_lexer": "ipython3" } }, "nbformat": 4, "nbformat_minor": 4 }