petercorke / petercorke/robotics-toolbox-python

PyPlot backend: global rcParams mutation + accumulated deprecation bugs -- needs a scoped-style rework

Open
#646 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

tech-debt
Dominant language
C++
Stars
3.5k
Forks
624
Avg merge
2d 4h
Merged PRs (30d)
53

Description

The core problem

roboticstoolbox/backends/PyPlot/PyPlot.py and PyPlot2.py apply their visual style by mutating global matplotlib state at import/instantiation time:

matplotlib.rcParams["pdf.fonttype"] = 42
matplotlib.rcParams["ps.fonttype"] = 42
plt.style.use("ggplot")
matplotlib.rcParams["font.size"] = 7
matplotlib.rcParams["lines.linewidth"] = 0.5
matplotlib.rcParams["xtick.major.size"] = 1.5
matplotlib.rcParams["ytick.major.size"] = 1.5
matplotlib.rcParams["axes.labelpad"] = 1

Confirmed via direct reproduction (2026-08): merely import roboticstoolbox no longer triggers this (the module is lazily imported now, only loaded via load_backend()), so #480's literal reported repro is fixed. But actually using the pyplot backend once (robot.plot(q, backend="pyplot")) still mutates 24 global rcParams for the rest of the Python process -- grid visibility, facecolor, font size, line width, color cycle, etc. -- which then silently changes the appearance of any other, unrelated matplotlib figure created afterward in the same session. This is exactly the symptom in #480's screenshots.

The proper fix is to scope the style to RTB's own figures only, e.g. wrapping the PyPlot session's rendering calls in matplotlib.rc_context({...}) / plt.style.context("ggplot") instead of mutating matplotlib.rcParams directly, and setting per-axes equivalents (ax.set_prop_cycle(), ax.tick_params(), etc.) where matplotlib supports them instead of the global rcParam.

Why this is worth a dedicated pass, not another one-off patch

Several independent, unrelated bugs have turned up in this same backend in quick succession, each patched individually:

  • #405 / PR #645 -- robot.plot(..., movie=...) crashed outright (missing import + a matplotlib Agg canvas method removed since tostring_rgb()).
  • #418 / PR #642 -- options= merge crashed on scalar-valued plot options (jointaxislength, eelength).
  • #405, #480, #481, #509 (title/body) -- a cluster of matplotlib API deprecations (w_xaxis->xaxis, Slider() kwargs, colorbar ax=) that all trace back to PyPlot never being updated alongside matplotlib's own API changes.

Each fix so far has been small and targeted, which is fine reactively, but the pattern suggests the PyPlot backend hasn't had a real audit against current matplotlib in some time. Worth a deliberate pass: scoped style application (this issue), a currency check against the matplotlib version(s) actually in pyproject.toml's support range, and maybe a smoke test that renders through every public PyPlot/PyPlot2 code path against the pinned matplotlib version in CI.

Ref: #480 (original report), #405/#645, #418/#642.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with roboticstoolbox/backends/PyPlot/PyPlot.py and PyPlot2.py, then inspect how load_backend() creates and renders PyPlot sessions. Compare the current global rcParams and plt.style.use calls with the scoped-style and per-axes approaches described in the issue, and check the supported matplotlib range in pyproject.toml. Done means RTB figures retain their intended style without changing unrelated matplotlib figures, with the relevant public PyPlot/PyPlot2 paths checked against the supported version.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data-visualization
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.