Tutorial 08 – Plotly Backend

The Plotly backend renders your maxplotlib canvas as an interactive plotly.graph_objects.Figure. Unlike the default matplotlib output, Plotly figures:

  • Are interactive in Jupyter: zoom, pan, hover for values, toggle traces.

  • Can be exported as standalone HTML files that work in any browser—no Python or server required.

  • Support multi-subplot layouts.

When to use Plotly vs matplotlib

Use case

Backend

Quick static plot / publication PDF

matplotlib (default)

Interactive exploration in Jupyter

plotly

Share a self-contained interactive report

plotlyfig.write_html(...)

LaTeX document figure

tikzfigure

[1]:
%load_ext autoreload
%autoreload 2
%matplotlib inline

from maxplotlib import Canvas
import numpy as np

Plotly in Jupyter

In notebooks, you can either:

  • call canvas.show(backend="plotly") (displays and returns a Plotly figure), or

  • call fig = canvas.plot(backend="plotly") and put fig as the last line of a cell.

[2]:
x = np.linspace(0, 2 * np.pi, 200)

canvas = Canvas(width="10cm", ratio=0.45)
canvas.add_line(x, np.sin(x), color="steelblue", label="sin(x)")
canvas.set_title("Displayed inline")
canvas.set_legend(True)

fig = canvas.show(backend="plotly")
fig

Data type cannot be displayed: application/vnd.plotly.v1+json

Data type cannot be displayed: application/vnd.plotly.v1+json

1 · Basic line plot

Switch to the Plotly backend by passing backend='plotly' to canvas.plot(). The returned object is a genuine plotly.graph_objects.Figure, so every Plotly method is available on it.

[3]:
x = np.linspace(0, 2 * np.pi, 200)

canvas = Canvas(width="10cm", ratio=0.55)
canvas.add_line(x, np.sin(x), color="steelblue", label="sin(x)")
canvas.set_xlabel("x")
canvas.set_ylabel("y")
canvas.set_title("Basic line plot")

fig = canvas.show(backend="plotly")
fig

Data type cannot be displayed: application/vnd.plotly.v1+json

Data type cannot be displayed: application/vnd.plotly.v1+json

2 · Multiple lines

Each ax.plot() call becomes a separate Plotly trace. Enable the legend with ax.set_legend(True) so trace labels appear.

[4]:
x = np.linspace(0, 2 * np.pi, 200)

canvas = Canvas(width="10cm", ratio=0.55)
canvas.add_line(x, np.sin(x), color="steelblue", label="sin(x)", linewidth=2)
canvas.add_line(x, np.cos(x), color="tomato", label="cos(x)", linewidth=2)
canvas.add_line(
    x,
    np.sin(2 * x),
    color="seagreen",
    label="sin(2x)",
    linewidth=2,
    linestyle="dashed",
)

canvas.set_xlabel("x")
canvas.set_ylabel("y")
canvas.set_title("Multiple lines")
canvas.set_legend(True)

fig = canvas.show(backend="plotly")
fig

Data type cannot be displayed: application/vnd.plotly.v1+json

Data type cannot be displayed: application/vnd.plotly.v1+json

3 · Scatter plot

ax.scatter() maps to a Plotly scatter trace with markers only.

[5]:
rng = np.random.default_rng(42)
n = 120
x_data = rng.uniform(0, 10, n)
y_data = 0.5 * x_data + rng.normal(0, 1, n)

canvas = Canvas(width="10cm", ratio=0.6)
canvas.scatter(
    x_data, y_data, color="steelblue", marker="o", s=20, label="observations"
)
canvas.add_line(
    [0, 10],
    [0, 5],
    color="tomato",
    linestyle="dashed",
    linewidth=2,
    label="y = 0.5x",
)

canvas.set_xlabel("x")
canvas.set_ylabel("y")
canvas.set_title("Scatter plot with trend line")
canvas.set_legend(True)

fig = canvas.show(backend="plotly")
fig

Data type cannot be displayed: application/vnd.plotly.v1+json

Data type cannot be displayed: application/vnd.plotly.v1+json

4 · Bar chart

ax.bar() maps to a Plotly bar trace.

[6]:
categories = ["Alpha", "Beta", "Gamma", "Delta", "Epsilon"]
values = [4.2, 7.1, 3.8, 5.9, 6.4]
x_pos = np.arange(len(categories))

canvas = Canvas(width="10cm", ratio=0.6)
canvas.bar(x_pos, values, color="steelblue", label="metric")
canvas.set_xticks(x_pos, categories)

canvas.set_xlabel("Category")
canvas.set_ylabel("Value")
canvas.set_title("Bar chart")
canvas.set_legend(True)

fig = canvas.show(backend="plotly")
fig

Data type cannot be displayed: application/vnd.plotly.v1+json

Data type cannot be displayed: application/vnd.plotly.v1+json

5 · Mixing lines and bars

You can place multiple trace types on the same axes — Plotly handles the overlay automatically.

[7]:
months = np.arange(1, 13)
rainfall = np.array([55, 48, 62, 70, 85, 40, 30, 35, 60, 90, 75, 65])
cumulative = np.cumsum(rainfall)

canvas = Canvas(width="10cm", ratio=0.6)
canvas.bar(
    months, rainfall, color="steelblue", alpha=0.7, label="monthly rainfall (mm)"
)
canvas.add_line(
    months,
    cumulative / 10,
    color="tomato",
    linewidth=2.5,
    marker="o",
    label="cumulative / 10",
)

canvas.set_xlabel("Month")
canvas.set_ylabel("Rainfall (mm)")
canvas.set_title("Monthly rainfall + cumulative trend")
canvas.set_legend(True)

fig = canvas.show(backend="plotly")
fig

Data type cannot be displayed: application/vnd.plotly.v1+json

Data type cannot be displayed: application/vnd.plotly.v1+json

6 · Multiple subplots

Multi-subplot canvases are fully supported. Each panel gets its own axis labels and title; canvas.suptitle(...) sets the figure-level title.

[8]:
x = np.linspace(0, 2 * np.pi, 200)
rng = np.random.default_rng(0)

canvas = Canvas(ncols=1)  # , width="14cm", ratio=0.35)

# Left panel — line plot
canvas.add_line(x, np.sin(x), color="steelblue", label="sin(x)", linewidth=2, col=0)
canvas.add_line(x, np.cos(x), color="tomato", label="cos(x)", linewidth=2, col=0)
canvas.set_xlabel("x", col=0)
canvas.set_ylabel("y", col=0)
canvas.set_title("Trigonometric functions", col=0)
canvas.set_legend(True, col=0)

# Right panel — scatter
x_s = rng.uniform(0, 6, 80)
y_s = np.sin(x_s) + rng.normal(0, 0.15, 80)
canvas.scatter(x_s, y_s, color="seagreen", marker="o", s=18, label="noisy sin", col=1)
canvas.add_line(
    x,
    np.sin(x),
    color="black",
    linestyle="dashed",
    linewidth=1.5,
    label="true sin",
    col=1,
)
canvas.set_xlabel("x", col=1)
canvas.set_ylabel("y", col=1)
canvas.set_title("Noisy observations", col=1)
canvas.set_legend(True, col=1)

canvas.suptitle("Multi-panel Plotly figure")

fig = canvas.show(backend="plotly")

Data type cannot be displayed: application/vnd.plotly.v1+json

7 · Log scale

ax.set_yscale('log') is passed through to Plotly’s axis type.

[9]:
x = np.linspace(0.1, 5, 200)

canvas = Canvas(width="10cm", ratio=0.55)
canvas.add_line(x, np.exp(x), color="steelblue", label="exp(x)", linewidth=2)
canvas.add_line(x, np.exp(1.5 * x), color="tomato", label="exp(1.5x)", linewidth=2)
canvas.add_line(x, x**2, color="seagreen", label="x²", linewidth=2)

canvas.set_xlabel("x")
canvas.set_ylabel("y  (log scale)")
canvas.set_title("Log-scale y axis")
canvas.set_yscale("log")
canvas.set_legend(True)

fig = canvas.show(backend="plotly")

Data type cannot be displayed: application/vnd.plotly.v1+json

8 · Saving to HTML

fig.write_html() saves a fully self-contained HTML file. The file works in any browser without Python, Plotly, or a running server — ideal for sharing interactive figures with colleagues.

[10]:
x = np.linspace(0, 2 * np.pi, 200)

canvas = Canvas(width="10cm", ratio=0.55)
canvas.add_line(x, np.sin(x), color="steelblue", label="sin(x)", linewidth=2)
canvas.add_line(x, np.cos(x), color="tomato", label="cos(x)", linewidth=2)
canvas.set_xlabel("x")
canvas.set_ylabel("y")
canvas.set_title("Saved interactive figure")
canvas.set_legend(True)

# Writes a standalone HTML file — open it in any browser
canvas.savefig("output.html", backend="plotly")
print("Saved to output.html")
Saved to output.html

Summary

Plotly backend feature table

Feature

Supported

Notes

ax.plot() — line trace

color, linestyle, linewidth, marker all passed through

ax.scatter() — markers

color, marker, s, alpha

ax.bar() — bar chart

color, alpha

ax.fill_between()

Not supported by this backend

ax.errorbar()

Not supported by this backend

ax.axhline/axvline

Not supported by this backend

Multi-subplot canvas

Canvas.subplots(ncols=...) etc.

canvas.suptitle()

Maps to figure title

ax.set_yscale('log')

ax.set_legend(True)

fig.show()

Interactive in Jupyter

fig.write_html(path)

Standalone interactive HTML

Typical workflow

from maxplotlib import Canvas
import numpy as np

canvas, ax = Canvas.subplots()
ax.plot(x, y, label='data')
ax.set_legend(True)

fig = canvas.plot(backend='plotly')   # → plotly.graph_objects.Figure
fig.show()                            # interactive in Jupyter
fig.write_html('report.html')         # share with anyone