Build a Monitoring Dashboard#

In this tutorial, we will construct a display-only dashboard that refreshes the entire page periodically.

These types of dashboards are suitable for displaying on a large screen running continuously, such as in a call center, control room, or trading area.

Monitoring Dashboard

Dependencies
panel scipy
Code
import numpy as np
import panel as pn
from scipy.interpolate import interp1d

pn.extension()

ACCENT = "teal"

WIND_SPEED_STD_DEV = 2.0
WIND_SPEED_MEAN = 8.0

WIND_SPEEDS = np.array([0, 3, 6, 9, 12, 15, 18, 21])  # Wind speed (m/s)
POWER_OUTPUTS = np.array([0, 39, 260, 780, 1300, 1300, 0, 0])  # Power output (MW)

# Extract Data

def get_wind_speed():
    # Replace with your wind speed source
    return round(np.random.normal(WIND_SPEED_MEAN, WIND_SPEED_STD_DEV), 1)

wind_speed = get_wind_speed()

# Transform Data

def get_power_output(wind_speed):
    # Replace with your power output calculation
    power_interpolation = interp1d(
        WIND_SPEEDS, POWER_OUTPUTS, kind="linear", fill_value="extrapolate"
    )
    return np.round(power_interpolation(wind_speed), 1)

power_output = get_power_output(wind_speed)

# View Data

wind_speed_view = pn.indicators.Number(
    name="Wind Speed",
    value=wind_speed,
    format="{value} m/s",
    colors=[(10, ACCENT), (100, "red")],
)
power_output_view = pn.indicators.Number(
    name="Power Output",
    value=power_output,
    format="{value} MW",
    colors=[
        (power_output, ACCENT),
        (max(POWER_OUTPUTS), "red"),
    ],
)
indicators = pn.FlexBox(wind_speed_view, power_output_view)

# Layout and style with template

pn.template.FastListTemplate(
    title="WTG Monitoring Dashboard",
    main=[indicators],
    accent=ACCENT,
    main_layout=None,
    theme="dark",
    theme_toggle=False,
    meta_refresh="2",  # Automatically refresh every 2 seconds
).servable();  # The ; is only needed if used in a notebook

Install the dependencies#

Please ensure that Panel and SciPy are installed.

pip install panel scipy
conda install -y -c conda-forge panel scipy

Explanation#

Let’s dissect the code that brings our dashboard to life:

import numpy as np
import panel as pn
from scipy.interpolate import interp1d

We import the necessary libraries: NumPy for numerical computations, Panel for building interactive web apps, and SciPy for interpolation.

pn.extension()

We load the JavaScript dependencies required by our app.

ACCENT = "teal"

WIND_SPEED_STD_DEV = 2.0
WIND_SPEED_MEAN = 8.0

WIND_SPEEDS = np.array([0, 3, 6, 9, 12, 15, 18, 21])  # Wind speed (m/s)
POWER_OUTPUTS = np.array([0, 39, 260, 780, 1300, 1300, 0, 0])  # Power output (MW)

We set some constants related to wind speed and power output data.

def get_wind_speed():
    return round(np.random.normal(WIND_SPEED_MEAN, WIND_SPEED_STD_DEV), 1)

wind_speed = get_wind_speed()

A function get_wind_speed() generates a random wind speed value based on a normal distribution.

def get_power_output(wind_speed):
    power_interpolation = interp1d(
        WIND_SPEEDS, POWER_OUTPUTS, kind="linear", fill_value="extrapolate"
    )
    return np.round(power_interpolation(wind_speed), 1)

power_output = get_power_output(wind_speed)

Another function get_power_output(wind_speed) calculates the corresponding power output based on the provided wind speed using linear interpolation.

wind_speed_view = pn.indicators.Number(
    name="Wind Speed",
    value=wind_speed,
    format="{value} m/s",
    colors=[(10, ACCENT), (100, "red")],
)
power_output_view = pn.indicators.Number(
    name="Power Output",
    value=power_output,
    format="{value} MW",
    colors=[
        (power_output, ACCENT),
        (max(POWER_OUTPUTS), "red"),
    ],
)
indicators = pn.FlexBox(wind_speed_view, power_output_view)
indicators

We create Number indicators to display the wind speed and power output. The FlexBox layout will arrange the indicators horizontally or vertically depending on the screen size.

pn.template.FastListTemplate(
    title="WTG Monitoring Dashboard",
    main=[indicators],
    accent=ACCENT,
    main_layout=None,
    theme="dark",
    theme_toggle=False,
    meta_refresh="2",  # Automatically refresh every 2 seconds
).servable()
pn.template.FastListTemplate(
    title="WTG Monitoring Dashboard",
    main=[indicators],
    accent=ACCENT,
    main_layout=None,
    theme="dark",
    theme_toggle=False,
    meta_refresh="2",  # Automatically refresh every 2 seconds
).servable();  # The ; is only needed if used in a notebook

Finally, we construct the dashboard using the FastListTemplate. We set the accent color, theme, and enable automatic refreshing every 2 seconds.

Note

In the example, we use a meta_refresh rate of 2 for illustration purposes. For real use cases, we recommend meta_refresh rates of 15 or above. For lower refresh rates we would be using a Periodic Callback or generators in combination with a meta_refresh rate of 900 or above.

Serve the App#

Now serve the app with:

panel serve app.py --dev
panel serve app.ipynb --dev

Open http://localhost:5006/app

It should resemble

Monitoring Dashboard

Recap#

In this tutorial, we have built a basic monitoring dashboard that refreshes the entire page periodically. We have used pn.panel, the Number indicator and the FastListTemplate.

We used the meta_refresh argument of the FastListTemplate to automatically refresh the dashboard periodically.