You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A Colorbar currently stores the Axes that is used for drawing in the cbar.ax attribute, which many of the methods are then called internally like self.ax.pcolormesh(). My proposal is to move the Axes up a level and have Colorbar inherit from the new CbarAxes class (to become an Axes itself) and turn the previous call into self.pcolormesh() dropping ax attribute.
Benefits: This would help with interactivity as proposed in #19515, by being able to identify if an axes is a Colorbar or not and then controlling properties based on that. It would also help with #20330, by giving the CbarAxes the ability to remove colorbar callbacks.
Drawbacks: This adds a lot of easy-to-use methods onto a Colorbar now that may not be desired to directly expose to users. i.e. they could do cbar.plot() now, whereas before cbar.ax.plot() hides those capabilities a little bit more.
Proposed fix
Define the class as class ColorbarBase(ColorbarAxes):
and set self.ax = self for people to keep using cbar.ax if they prefer. We could deprecate that on pass-through as well.
Can you just make a pull of that branch, and put in Draft if you prefer?
As always, I think about this sort of thing from "what would we do if we were starting over " point of view. Would we just call a colorbar a type of Axes? I guess I'm not sure...
I wasn't sure whether an Issue was preferred before a PR for discussion purposes or not...
My thought is that making a Colorbar a type of Axes would help with being able to directly override methods of the Axes, rather than having to dispatch to the cbar.ax attribute. The real benefit is that cbar.ax Axes now explicitly has access to the extra Colorbar attributes (callbacks, lines, ...). One downside I see to this is that cbar now has three methods: set_xticks(), set_yticks(), and set_ticks(), which could potentially lead to confusion. But, it doesn't seem that bad to me either.
I'm not convinced this is the right design choice.
First, as you mentioned, there's a lot of additional functionality, that doesn't make much sense for colorbars. While one can question whether it's reasonable to have all the plotting methods on the Axes, it certainly doesn't help for a clean colorbar API. This might be addressable by extracting an appropriate common base class, which is backwards-compatible. I haven't checked, but _AxesBase might be a good start.
Second, AFAIR the dance with the inner Axes is done to get extremes-arrows and layout work together. These might be a reason that a colorbar is fundamentally different from a regular Axes.
I'm afraid we haven't clarified exactly what an Axes is. I assume it's multple things. At least:
It's a plotting area, in which the directions have individual scales
It's a namespace for functions that can add artists to this plotting area. This is mainly what the Axes class itself brings in addtion to _AxesBase (possibly modulo title functionality).
It's a container for elements outside the plotting area (ticks/ticklabels, labels, title()
It is a top-level building block for the layout engines (unless it's a free or inner Axes).
The point here is that you need an Axes as a layout element with the same height as your data Axes to be able to put a properly sizing colorbar.
It might be reasonable to separate these functionalities better conceptually. E.g. I think it would help if we would have layout blocks, that do not necessarily come with all the other semantics. Also factoring out the plotting functions would open up a path for others to add their own functions (whether or not we want that could be decided). We would still mix everything together for standard Axes to keep backward-compatibility. But that'd be a larger design project.
.. I mean the PR looks appealing - the question is if we want users to have that functionality directly. I'm also not clear that it is actually a simplification. i.e. I don't see how colorbar.cla will be any easier than colorbar.ax.cla.
That is a good point about defining what an Axes should be and potentially breaking that out into separate subclasses. The reason I even thought that a Colorbar could be an Axes is due to the similarity in the first place. So, is a Colorbar really a completely different animal with a separate API, or is it similar enough to warrant subclassing Axes? (Note: we still need the plotting methods somewhere due to adding QuadMesh and LineCollection for the colors/lines)
The inner/outer dance is for the extends portion, but also so that the inner can leverage the base Axes locator/formatter logic without reimplementing those as separate _ColorbarLocators. Trying to be more consistent with Axes, so my thought in this issue is how far can we take that and can/should we bring it directly into Colorbar?
The reason this makes it easier for something like cla() is that you can access the mappable and other Colorbar attributes from the Axes functions now:
and for the interactive Colorbar it would be nice to say isinstance(ax, Colorbar) over in backend_bases to control which features to turn on/off for Colorbars. We currently can't distinguish if the Axes is a Colorbar or not. (a hack around that may be to put a _colorbar = True private attribute on the axes and do a hasattr() check, but that doesn't seem quite as nice)
OK, so the cla thing is a bit orthogonal... The mappable callback issue for multiple colorbars still stand, and the cla will still have to be as complicated for the inner and outer axes mapping I think.
by being able to identify if an axes is a Colorbar or not and then controlling properties based on that.
I think the concern about directly exposing the axes methods is a valid one, and indeed it will be confusing to have cb.set_ticks and cb.set_xticks and cb.set_yticks.
The desire to know if a given axes is a colorbar is a valid one. But we already do this a couple of ways. For non gridspec axes:
and lines following add a cax._colorbar_info attribute to the colorbar axes....
For gridspec colorbar axes we don't add all the information, but the label is still set to <colorbar>. We actually should set all the same information gridspec axes, but that information was needed for constrained_layout, so didn't get passed to the gridspec axes.
I actually think making the API more Axes-like is easier to understand. Someone doesn't have to learn new lingo to interact with a Colorbar. A Colorbar adds a convenience helper method of set_ticks() that dispatches to the long axis, but if someone already knows they want to update the x/y specific axes they can call that directly. The question seems to revolve around whether Colorbar should be a restricted API with only the minimum functions required, or an expanded API from Axes that adds additional convenience methods (what's proposed here).
... actually, now all colorbar axes should be of type ColorbarAxes so that should be an easy way to tell if an axes is a Colorbar.
I think the issue I was running into was that the Zoom/Pan are interacting on the outer_axes, rather than the ColorbarAxes class... I'll have to revisit this, I know I tried that and it didn't work immediately out of the box, but there may be a way to get to it that I'm missing.
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
I propose to close this, I think it's a too broad API going with a full Axes subclass. If we want to rearchitect #20341 (comment) would be the way, but I don't see a strong need here; in particular also because #27167 introduced the long_axis property so that you can handle all the tick-related topics on the Axis level.
I agree with closing this 👍 We can bring it back up later if someone has the desire to push it through. The colorbar is in a better state now than when this was proposed.
Activity
jklymak commentedon Jun 2, 2021
Can you just make a pull of that branch, and put in Draft if you prefer?
As always, I think about this sort of thing from "what would we do if we were starting over " point of view. Would we just call a colorbar a type of Axes? I guess I'm not sure...
greglucas commentedon Jun 2, 2021
I wasn't sure whether an Issue was preferred before a PR for discussion purposes or not...
My thought is that making a Colorbar a type of Axes would help with being able to directly override methods of the Axes, rather than having to dispatch to the
cbar.axattribute. The real benefit is thatcbar.axAxes now explicitly has access to the extra Colorbar attributes (callbacks, lines, ...). One downside I see to this is that cbar now has three methods:set_xticks(),set_yticks(), andset_ticks(), which could potentially lead to confusion. But, it doesn't seem that bad to me either.timhoffm commentedon Jun 2, 2021
I'm not convinced this is the right design choice.
First, as you mentioned, there's a lot of additional functionality, that doesn't make much sense for colorbars. While one can question whether it's reasonable to have all the plotting methods on the
Axes, it certainly doesn't help for a clean colorbar API. This might be addressable by extracting an appropriate common base class, which is backwards-compatible. I haven't checked, but_AxesBasemight be a good start.Second, AFAIR the dance with the inner Axes is done to get extremes-arrows and layout work together. These might be a reason that a colorbar is fundamentally different from a regular Axes.
I'm afraid we haven't clarified exactly what an Axes is. I assume it's multple things. At least:
Axesclass itself brings in addtion to_AxesBase(possibly modulo title functionality).The point here is that you need an Axes as a layout element with the same height as your data Axes to be able to put a properly sizing colorbar.
It might be reasonable to separate these functionalities better conceptually. E.g. I think it would help if we would have layout blocks, that do not necessarily come with all the other semantics. Also factoring out the plotting functions would open up a path for others to add their own functions (whether or not we want that could be decided). We would still mix everything together for standard
Axesto keep backward-compatibility. But that'd be a larger design project.jklymak commentedon Jun 2, 2021
.. I mean the PR looks appealing - the question is if we want users to have that functionality directly. I'm also not clear that it is actually a simplification. i.e. I don't see how
colorbar.clawill be any easier thancolorbar.ax.cla.greglucas commentedon Jun 3, 2021
That is a good point about defining what an
Axesshould be and potentially breaking that out into separate subclasses. The reason I even thought that a Colorbar could be an Axes is due to the similarity in the first place. So, is a Colorbar really a completely different animal with a separate API, or is it similar enough to warrant subclassing Axes? (Note: we still need the plotting methods somewhere due to adding QuadMesh and LineCollection for the colors/lines)The inner/outer dance is for the extends portion, but also so that the inner can leverage the base
Axeslocator/formatter logic without reimplementing those as separate_ColorbarLocators. Trying to be more consistent with Axes, so my thought in this issue is how far can we take that and can/should we bring it directly into Colorbar?The reason this makes it easier for something like cla() is that you can access the mappable and other Colorbar attributes from the Axes functions now:
and for the interactive Colorbar it would be nice to say
isinstance(ax, Colorbar)over in backend_bases to control which features to turn on/off for Colorbars. We currently can't distinguish if the Axes is a Colorbar or not. (a hack around that may be to put a_colorbar = Trueprivate attribute on the axes and do ahasattr()check, but that doesn't seem quite as nice)jklymak commentedon Jun 3, 2021
OK, so the
clathing is a bit orthogonal... The mappable callback issue for multiple colorbars still stand, and the cla will still have to be as complicated for the inner and outer axes mapping I think.jklymak commentedon Jun 11, 2021
I think the concern about directly exposing the axes methods is a valid one, and indeed it will be confusing to have
cb.set_ticksandcb.set_xticksandcb.set_yticks.The desire to know if a given axes is a colorbar is a valid one. But we already do this a couple of ways. For non gridspec axes:
matplotlib/lib/matplotlib/colorbar.py
Line 1374 in 3cf46cb
and lines following add a
cax._colorbar_infoattribute to the colorbar axes....For gridspec colorbar axes we don't add all the information, but the label is still set to
<colorbar>. We actually should set all the same information gridspec axes, but that information was needed for constrained_layout, so didn't get passed to the gridspec axes.jklymak commentedon Jun 11, 2021
... actually, now all colorbar axes should be of type
ColorbarAxesso that should be an easy way to tell if an axes is a Colorbar.greglucas commentedon Jun 11, 2021
I actually think making the API more Axes-like is easier to understand. Someone doesn't have to learn new lingo to interact with a Colorbar. A Colorbar adds a convenience helper method of
set_ticks()that dispatches to the long axis, but if someone already knows they want to update the x/y specific axes they can call that directly. The question seems to revolve around whether Colorbar should be a restricted API with only the minimum functions required, or an expanded API from Axes that adds additional convenience methods (what's proposed here).I think the issue I was running into was that the Zoom/Pan are interacting on the
outer_axes, rather than theColorbarAxesclass... I'll have to revisit this, I know I tried that and it didn't work immediately out of the box, but there may be a way to get to it that I'm missing.github-actions commentedon Oct 24, 2025
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
timhoffm commentedon Oct 27, 2025
I propose to close this, I think it's a too broad API going with a full Axes subclass. If we want to rearchitect #20341 (comment) would be the way, but I don't see a strong need here; in particular also because #27167 introduced the
long_axisproperty so that you can handle all the tick-related topics on the Axis level.greglucas commentedon Oct 27, 2025
I agree with closing this 👍 We can bring it back up later if someone has the desire to push it through. The colorbar is in a better state now than when this was proposed.