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 |
|
Interactive exploration in Jupyter |
|
Share a self-contained interactive report |
|
LaTeX document figure |
|
[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), orcall
fig = canvas.plot(backend="plotly")and putfigas 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 |
|---|---|---|
|
✅ |
|
|
✅ |
|
|
✅ |
|
|
❌ |
Not supported by this backend |
|
❌ |
Not supported by this backend |
|
❌ |
Not supported by this backend |
Multi-subplot canvas |
✅ |
|
|
✅ |
Maps to figure title |
|
✅ |
|
|
✅ |
|
|
✅ |
Interactive in Jupyter |
|
✅ |
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