Skip to content

introduction of _ColorbarMappable#31039

Open
trygvrad wants to merge 1 commit intomatplotlib:mainfrom
trygvrad:ColorbarMappable
Open

introduction of _ColorbarMappable#31039
trygvrad wants to merge 1 commit intomatplotlib:mainfrom
trygvrad:ColorbarMappable

Conversation

@trygvrad
Copy link
Contributor

This PR renames _ColorizerInterface to _ColorbarMappable and shifts some functionality such that _ColorbarMappable can function as the mappable for fig.colorbar(mappable).

_ColorbarMappable differs from a ColorizingArtist [the regular input to fig.colobar()] in that it is not an Artist.
This change is needed for improvements to Axes3d.voxel(), see #31032, but may also find other uses.

I don't think there is currently any use case for _ColorizerInterface outside of ColorizingArtist

This PR only changes the private API, with no changes to the public API.

PR checklist



class _ColorizerInterface:
class _ColorbarMappable:
Copy link
Member

Choose a reason for hiding this comment

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

Why Colorbar? Isn't this rather a ColorMappable?

The objects uses a colorizer to map data to colors. It's just a corollary that objects that use colorisers can be associated to a colorbar.

Copy link
Member

Choose a reason for hiding this comment

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

jumping off this comment, I think this object is what would be hooked into for a colormap legend (for example for discrete colormaps) type situation?

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 please clarify, what is a "colormap legend"?

Without understanding, I'd say no 😛. As said in the comment on the docstring, this object is basically "Data+Colorizer". And colorizer is per-se continous. One can make it look discrete through the (IMHO quite quirky) BoundaryNorm approach. But I wouldn't think about discrete colormaps right now - this abstraction doesn't change however good or bad they are currently supported.

Copy link
Member

Choose a reason for hiding this comment

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

what is a "colormap legend"?

A legend where the handler and label information is fed from a colormap. The most commonly requested use case is probably a scatter plot where folks wanna color the dots based on class. Also useful for heatmaps of classes (somewhat common in ml) and my motivating example was coded data on a heatmap.

stas.png

Copy link
Member

@story645 story645 Jan 29, 2026

Choose a reason for hiding this comment

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

I gave up on a categorical colormap a very long time ago b/c it kinda broke the cmap/norm abstractions (#6934), so one of my main reasons for being psyched about the colorizer pipeline is it doesn't have those divisions. A CategoricalColorizer that takes in a {category name : color} dict is almost definitely much cleaner to implement than my old hack of listed colormaps and boundary norm approach.

Comment on lines 318 to 319
Base class that contains the interface to `Colorizer` objects from
a `ColorizingArtist` or `.cm.ScalarMappable`.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Base class that contains the interface to `Colorizer` objects from
a `ColorizingArtist` or `.cm.ScalarMappable`.
Base class for objects that maps data to colors via a `Colorizer`.
This is e.g. the base for `ColorizingArtist` or `.cm.ScalarMappable`.

I think the subsequent note needs allow an update. My understanding is that this class is basically "Data+Colorizer" and related functionality like changed.

Comment on lines +341 to +347
@property
def axes(self):
return self._axes

@axes.setter
def axes(self, axes):
self._axes = axes
Copy link
Member

Choose a reason for hiding this comment

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

We need to be a bit careful with scoping. We've intentionally left out any Artist notion. So this is rather an abstract concept or concern or mixin or trait (or whatever you want to call it). That it needs association with an Axes is not a-priory clear.

axes is not used anywhere in the class itself. If we want to nevertheless add this here, we need a good reason for that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a good point. Instead of having this here we can have a hasattr(mappable, 'axes') in colorbar().

Copy link
Member

Choose a reason for hiding this comment

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

We could make a very nuanced sematnic distinction here: If you keep the original name _ColorbarMappable, we could make the operational definition as "some object that can be passed to a colorbar". That would allow to add whatever is needed, including an optional axes.

OTOH I think I still like the conceptual definition "_ColorMappable = Data + Colorizer" more, even if this means colorbar() has to jump an extra hoop with hasattr(mappable, 'axes') (or possibly isinstance(mappable, Artist) - without having checked I assume that colorbar will do some thing additional for Artists in an Axes, that is not needed/possible for an abstract mapping). I propose to go this direction.

From a quick check, the only usage of axes in Colorbar seems to be

try:
ax = self.mappable.axes
except AttributeError:
return

So the optional axes may already be cared for? Please re-check.

Side-note: I've found

if (isinstance(self.norm, (colors.BoundaryNorm, colors.NoNorm)) or
isinstance(self.mappable, contour.ContourSet)):
self.ax.set_navigate(False)

Would it make sense to encode something like can_navigate() into _ColorMappable so that we move the responsibility for this logic from the colorbar to the mappable? - Possibly still needs a better name.

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.

3 participants