Skip to content

Bivar colorbar - #32606

Draft
trygvrad wants to merge 2 commits into
matplotlib:mainfrom
trygvrad:bivar-colorbar
Draft

trygvrad wants to merge 2 commits into
matplotlib:mainfrom
trygvrad:bivar-colorbar

Conversation

@trygvrad

@trygvrad trygvrad commented Nov 15, 2026 •

Copy link
Copy Markdown
Contributor

This PR has a long history. It is part of Bivariate and Multivariate Colormapping and contains changes that were previously part of #31214 which is being separated into multiple parts with the use of AI. This is part 2 of 4 and Depends on #32605. Only the last commit ("Add bivariate colorbars") is new in this PR.

PR summary

  • Adds Figure.colorbar_bivar / SubFigure.colorbar_bivar and pyplot.colorbar_bivar.
  • New module matplotlib.colorbar_multivariate with BivarColorbar, make_bivar_axes, make_bivar_axes_gridspec.
  • colorbar.py is not changed (see discussion in Multivar colorbar #31214). The colorbar Axes is created by the existing colorbar.make_axes / make_axes_gridspec (with aspect=1 and no orientation), so placement, gridspec and constrained layout behave as for a normal colorbar.
  • Drawn with pcolormesh, so the axis scales follow the norms (log etc.); first data variable on the y-axis, second on the x-axis.
  • Interactive pan/zoom on the colorbar changes the norms, as for a normal colorbar.
  • Public API kept small (see discussion in Multivar colorbar #31214): only ax (read-only) and aspect (settable), plus set_xlabel/set_ylabel, xaxis/yaxis, update_normals, remove. No alpha.
  • aspect is preserved under constrained layout for colorbars at the top/bottom (layout inverts the aspect of horizontal colorbars; BivarColorbar compensates).
  • Figure.colorbar now raises a clear error when given a bivariate colormap, pointing to colorbar_bivar.
  • Toolbar zoom no longer assumes every ax._colorbar has an orientation (backend_bases.py).
  • Two Axes3D docstring cross-references made explicit (they became ambiguous with the new set_ylabel).
  • New test file test_colorbar_multivariate.py; baseline images moved from Multivar colorbar #31214 unchanged.
  • Release note with a plot in doc/release/next_whats_new/colorbar_bivar.rst; new API page colorbar_multivariate_api.rst.

There is no example in the docs yet, that will come in a separate PR.

Here is an example:

im_A = np.arange(200)[np.newaxis, :]*np.ones((200, 200))
im_B = np.arange(200)[:, np.newaxis]*np.ones((200, 200))

im_A = np.sin(im_A**0.5)**2
im_B = np.sin(im_B**0.5)**2

fig, axes = plt.subplots(2, 2, figsize = (10, 6), dpi = 100, layout="constrained")
axes = axes.ravel()
locs = ['right', 'left',  'top', 'bottom']

im = (im_A, im_B)
for i, loc in enumerate(locs):
    cim = axes[i].pcolormesh(im, cmap='BiOrangeBlue', vmax=(1, 1))
    cb = fig.colorbar_bivar(cim, location=loc, fraction = 0.3)
    cb.set_ylabel('A')
    cb.set_xlabel('B')

fig.show()
image

AI Disclosure

The split of #31214 into smaller PRs, and the changes requested in review there, were
made with the assistance of an AI coding assistant (Claude). All changes were reviewed
and tested by me.

PR quality check

  • Use an expressive title, e.g. "Fix title font property precedence"
  • New and changed code is tested
  • Plotting related features are demonstrated in an example
  • New features and API changes have release notes
  • Documentation complies with general and docstring guidelines

trygvrad and others added 2 commits November 13, 2026 16:58
- Colorizer: an existing MultiNorm passed as *norm* is used as is instead
  of being wrapped in a new MultiNorm, which raised a ValueError.
- MultiNorm.autoscale_None only emits the 'changed' signal when the limits
  of a constituent norm actually changed.
- Colorbar.remove no longer fails when the mappable has no Axes.

Changes implemented with the assistance of AI and manually evaluated

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add `Figure.colorbar_bivar` and `pyplot.colorbar_bivar`, which draw the
colorbar of a bivariate colormap as a 2D image, with one data variable
along each axis.

The new `BivarColorbar` class lives in the new module
`matplotlib.colorbar_multivariate`. Its Axes is created by the existing
`colorbar.make_axes` / `colorbar.make_axes_gridspec`, so it takes part in
layout (including constrained layout) like a regular colorbar, and
`colorbar.py` itself is not changed.

Changes implemented with the assistance of AI and manually evaluated

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@trygvrad

Copy link
Copy Markdown
Contributor Author

One question here:
This makes a new file colorbar_multivariate.py which is also used by the subsequent PRs #32607, #32608 for colorbar_multivar.
The bivar colorbar and mulitbar colorbars are sufficiently different that we could place them in separate files. Let me know if you would prefer this.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants