Skip to content

Conversation

trygvrad
Copy link
Contributor

@trygvrad trygvrad commented Sep 3, 2025

This PR continues the work of #28658 and #28454, #29876, aiming to close #14168. (Feature request: Bivariate colormapping)

This PR allows Colorizer and ColorizingArtist to work with MultiNorm and BivarColormap and MultivarColormap

i.e. this PR will allow:

import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
a = np.arange(12).reshape(3,4)
b = np.arange(12).reshape(4,3).T

norm = mpl.colors.Normalize(vmin=0, vmax=11)
col = mpl.colorizer.Colorizer(cmap='BiOrangeBlue', norm=[norm, norm])

plt.imshow(col.to_rgba((a, b)))
image

Features not included in this PR:

  • Exposes the functionality provided by MultiNorm together with BivarColormap and MultivarColormap to the plotting functions axes.imshow(...), axes.pcolor(...), and axes.pcolormesh(...)`
  • fig.colorbar() equivalents for BivarColormap and MultivarColormap
  • Examples in the docs

PR checklist

  • new and changed code is tested

@trygvrad
Copy link
Contributor Author

trygvrad commented Sep 4, 2025

Thank you for the feedback @QuLogic and apologies for my sloppy mistakes :)

improved testing for colorizer+multinorm

Apply suggestions from code review

Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>

updates based on feedback from @QuLogic
dt = np.dtype('float64, float64')
else:
dt = np.dtype('float32, float32')
reconstructed = np.ma.frombuffer(data.data, dtype=dt).reshape(data.shape)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use a view to get this, instead of poking at the internal data buffer?

Copy link
Contributor Author

@trygvrad trygvrad Sep 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, the following appears to work for regular arrays, but not masked arrays

reconstructed = np.ma.array(data.view(dt))

So the issue with masked arrays is that when the dtype is chnaged from 'comlex128' to 'float64, float64' the shape of the mask changes, so we cannot do data.view(dt) on masked data.

To support both masked and not-masked input data, we can do:

reconstructed = np.ma.array(np.asarray(data).view(dt))

To me, this looks like an improvement over poking the internal data buffer

The mask is in either case addressed in the lines following this:

if np.ma.is_masked(data):
     for descriptor in dt.descr:
         reconstructed[descriptor[0]][data.mask] = np.ma.masked

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we're already in a isinstance(data, np.ndarray), would it make more sense to do np.ma.getdata instead of np.asarray, which at first glance looks superfluous?

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

Successfully merging this pull request may close these issues.

Feature request: Bivariate colormapping
2 participants