A parametric curve plot visualizes x(t) and y(t) as functions of a parameter t, tracing smooth curves in 2D space. Unlike standard function plots where y = f(x), parametric curves can loop, self-intersect, and form closed shapes such as Lissajous figures, spirals, and cardioids. This makes them essential for representing trajectories, oscillations, and classical mathematical curves that cannot be expressed as single-valued functions.

""" anyplot.ai
line-parametric: Parametric Curve Plot
Library: plotnine 0.15.7 | Python 3.13.14
Quality: 93/100 | Updated: 2026-06-20
"""
import os
import numpy as np
import pandas as pd
from plotnine import (
aes,
coord_equal,
element_blank,
element_line,
element_rect,
element_text,
facet_wrap,
geom_path,
geom_point,
ggplot,
guide_colorbar,
guide_legend,
guides,
labs,
scale_color_gradientn,
scale_fill_manual,
scale_shape_manual,
theme,
theme_void,
)
# Theme tokens
THEME = os.getenv("ANYPLOT_THEME", "light")
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
# Imprint sequential colormap — brand green → blue (single-polarity, direction of t)
IMPRINT_SEQ = ["#009E73", "#4467A3"]
# Marker fills from Imprint palette: green = start (matches gradient low), red = end (contrast)
MARKER_START = "#009E73" # brand green
MARKER_END = "#AE3030" # matte red — semantic contrast against blue path end
# Data — normalize t to [0, 1] per curve so both panels use the full color gradient
n_points = 1000
t_lissajous = np.linspace(0, 2 * np.pi, n_points)
x_lissajous = np.sin(3 * t_lissajous)
y_lissajous = np.sin(2 * t_lissajous)
t_norm_liss = np.linspace(0, 1, n_points)
t_spiral = np.linspace(0, 4 * np.pi, n_points)
x_spiral = t_spiral * np.cos(t_spiral) / (4 * np.pi)
y_spiral = t_spiral * np.sin(t_spiral) / (4 * np.pi)
t_norm_spiral = np.linspace(0, 1, n_points)
df = pd.concat(
[
pd.DataFrame(
{"x": x_lissajous, "y": y_lissajous, "t_norm": t_norm_liss, "curve": "Lissajous · x = sin(3t), y = sin(2t)"}
),
pd.DataFrame(
{"x": x_spiral, "y": y_spiral, "t_norm": t_norm_spiral, "curve": "Spiral · x = t·cos(t), y = t·sin(t)"}
),
],
ignore_index=True,
)
# Start and end markers for direction cues
markers = pd.concat(
[
pd.DataFrame(
{
"x": [x_lissajous[0], x_spiral[0]],
"y": [y_lissajous[0], y_spiral[0]],
"curve": ["Lissajous · x = sin(3t), y = sin(2t)", "Spiral · x = t·cos(t), y = t·sin(t)"],
"endpoint": ["Start (t = 0)", "Start (t = 0)"],
}
),
pd.DataFrame(
{
"x": [x_lissajous[-1], x_spiral[-1]],
"y": [y_lissajous[-1], y_spiral[-1]],
"curve": ["Lissajous · x = sin(3t), y = sin(2t)", "Spiral · x = t·cos(t), y = t·sin(t)"],
"endpoint": ["End (t = tmax)", "End (t = tmax)"],
}
),
],
ignore_index=True,
)
# Plot
plot = (
ggplot(df, aes(x="x", y="y", color="t_norm"))
+ geom_path(aes(group="curve"), size=1.0, alpha=0.94)
+ geom_point(
aes(shape="endpoint", fill="endpoint"), data=markers, color=INK, size=3.5, stroke=0.8, show_legend=True
)
+ scale_shape_manual(name="Direction", values={"Start (t = 0)": "o", "End (t = tmax)": "D"})
+ scale_fill_manual(name="Direction", values={"Start (t = 0)": MARKER_START, "End (t = tmax)": MARKER_END})
+ facet_wrap("curve", scales="free")
+ scale_color_gradientn(
name="Parameter t",
colors=IMPRINT_SEQ,
breaks=[0.0, 0.25, 0.5, 0.75, 1.0],
labels=["0", "¼", "½", "¾", "tmax"],
guide=guide_colorbar(nbin=200),
)
+ coord_equal()
+ labs(
title="line-parametric · python · plotnine · anyplot.ai",
x="Horizontal Position x(t)",
y="Vertical Position y(t)",
)
+ guides(shape=guide_legend(order=2), fill=guide_legend(order=2))
+ theme_void()
+ theme(
figure_size=(8, 4.5),
plot_title=element_text(size=12, weight="bold", color=INK, margin={"b": 8}),
axis_title_x=element_text(size=10, color=INK, margin={"t": 6}),
axis_title_y=element_text(size=10, color=INK, margin={"r": 6}),
axis_text=element_text(size=8, color=INK_SOFT),
axis_ticks=element_blank(),
legend_title=element_text(size=8, weight="bold", color=INK),
legend_text=element_text(size=8, color=INK_SOFT),
legend_key=element_rect(fill=ELEVATED_BG, color=ELEVATED_BG),
legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT, size=0.3),
legend_box_margin=4,
strip_text=element_text(size=9, weight="bold", color=INK, margin={"b": 6}),
strip_background=element_rect(fill=ELEVATED_BG, color="none"),
panel_spacing_x=0.1,
panel_grid_major=element_line(color=INK, size=0.2, alpha=0.15),
panel_grid_minor=element_blank(),
panel_background=element_rect(fill=PAGE_BG, color="none"),
plot_background=element_rect(fill=PAGE_BG, color="none"),
plot_margin=0.01,
)
)
# Save
plot.save(f"plot-{THEME}.png", dpi=400, width=8, height=4.5, units="in", verbose=False)
Part of Parametric Curve Plot on anyplot.ai.