Add a web UI with Panel (basic)

Audience: Users who want to add a web UI written with Python and Panel.

Prereqs: Basic Python knowledge.


What is Panel?

Panel and the HoloViz ecosystem provide unique and powerful features such as big data visualization using DataShader, easy cross filtering using HoloViews, streaming and much more.

  • Panel is highly flexible and ties into the PyData and Jupyter ecosystems as you can develop in notebooks and use ipywidgets. You can also develop in .py files.

  • Panel is one of the most popular data app frameworks in Python with more than 400.000 downloads a month. It’s especially popular in the scientific community.

  • Panel is used, for example, by Rapids to power CuxFilter, a CuDF based big data visualization framework.

  • Panel can be deployed on your favorite server or cloud including Lightning.

Example Panel App

Example Panel App

Panel is particularly well suited for Lightning Apps that need to display live progress. This is because the Panel server can react to state changes and asynchronously push messages from the server to the client using web socket communication.

Example Panel Streaming App

Example Panel Streaming App

Install Panel with:

pip install panel

Run a basic Panel App

In the next few sections, we’ll build an App step-by-step.

First, create a file named app_panel.py with the App content:

# app_panel.py

import panel as pn

pn.panel("Hello **Panel ⚡** World").servable()

Then, create a file named app.py with the following App content:

# app.py

import lightning as L
from lightning.app.frontend import PanelFrontend


class LitPanel(L.LightningFlow):

    def configure_layout(self):
        return PanelFrontend("app_panel.py")


class LitApp(L.LightningFlow):
    def __init__(self):
        super().__init__()
        self.lit_panel = LitPanel()

    def run(self):
        self.lit_panel.run()

    def configure_layout(self):
        return {"name": "home", "content": self.lit_panel}


app = L.LightningApp(LitApp())

Finally, add panel to your requirements.txt file:

echo 'panel' >> requirements.txt

Note

This is a best practice to make Apps reproducible.


Run the App

Run the App locally:

lightning_app run app app.py

The App should look like this:

Basic Panel Lightning App

Basic Panel Lightning App

Now, run it on the cloud:

lightning_app run app app.py --cloud

Step-by-step walk-through

In this section, we explain each part of the code in detail.


0. Define a Panel app

First, find the Panel app you want to integrate. In this example, that app looks like:

import panel as pn

pn.panel("Hello **Panel ⚡** World").servable()

Refer to the Panel documentation and awesome-panel for more complex examples.


1. Add Panel to a Component

Link this app to the Lightning App by using the PanelFrontend class which needs to be returned from the configure_layout method of the Lightning Component you want to connect to Panel.

import lightning as L
from lightning.app.frontend import PanelFrontend


class LitPanel(L.LightningFlow):

    def configure_layout(self):
        return PanelFrontend("app_panel.py")


class LitApp(L.LightningFlow):
    def __init__(self):
        super().__init__()
        self.lit_panel = LitPanel()

    def run(self):
        self.lit_panel.run()

    def configure_layout(self):
        return {"name": "home", "content": self.lit_panel}


app = L.LightningApp(LitApp())

The argument of the PanelFrontend class, points to the script, notebook, or function that runs your Panel app.


2. Route the UI in the root component

The second step, is to tell the Root component in which tab to render this component’s UI. In this case, we render the LitPanel UI in the home tab of the app.

import lightning as L
from lightning.app.frontend import PanelFrontend


class LitPanel(L.LightningFlow):

    def configure_layout(self):
        return PanelFrontend("app_panel.py")


class LitApp(L.LightningFlow):
    def __init__(self):
        super().__init__()
        self.lit_panel = LitPanel()

    def run(self):
        self.lit_panel.run()

    def configure_layout(self):
        return {"name": "home", "content": self.lit_panel}

app = L.LightningApp(LitApp())

Tips & Tricks

0. Use autoreload while developing

To speed up your development workflow, you can run your Lightning App with Panel autoreload by setting the environment variable PANEL_AUTORELOAD to yes.

Try running the following:

PANEL_AUTORELOAD=yes lightning run app app.py
Basic Panel Lightning App with autoreload

Basic Panel Lightning App with autoreload

1. Theme your App

To theme your App you, can use the Lightning accent color #792EE5 with the FastListTemplate.

Try replacing the contents of app_panel.py with the following:

# app_panel.py

import panel as pn
import plotly.express as px

ACCENT = "#792EE5"

pn.extension("plotly", sizing_mode="stretch_width", template="fast")
pn.state.template.param.update(
    title="⚡ Hello Panel + Lightning ⚡", accent_base_color=ACCENT, header_background=ACCENT
)

pn.config.raw_css.append(
    """
.bk-root:first-of-type {
    height: calc( 100vh - 200px ) !important;
}
"""
)


def get_panel_theme():
    """Returns 'default' or 'dark'"""
    return pn.state.session_args.get("theme", [b"default"])[0].decode()


def get_plotly_template():
    if get_panel_theme() == "dark":
        return "plotly_dark"
    return "plotly_white"


def get_plot(length=5):
    xseries = [index for index in range(length + 1)]
    yseries = [x**2 for x in xseries]
    fig = px.line(
        x=xseries,
        y=yseries,
        template=get_plotly_template(),
        color_discrete_sequence=[ACCENT],
        range_x=(0, 10),
        markers=True,
    )
    fig.layout.autosize = True
    return fig


length = pn.widgets.IntSlider(value=5, start=1, end=10, name="Length")
dynamic_plot = pn.panel(
    pn.bind(get_plot, length=length), sizing_mode="stretch_both", config={"responsive": True}
)
pn.Column(length, dynamic_plot).servable()

Install some additional libraries and remember to add the dependencies to the requirements.txt file:

echo 'plotly' >> requirements.txt
echo 'pandas' >> requirements.txt

Finally run the App

lightning_app run app app.py
Basic Panel Plotly Lightning App with theming

Basic Panel Plotly Lightning App with theming


Next Steps