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
Currently, setting a Colorbar's formatter is done by assigning to the cbar.formatter property. It would be nice if a getter/setter was provided following the standard Matplotlib API (ditto for minor formatters), as that would also allow directly setting the formatter in the constructor (fig.colorbar(..., formatter=...)) or via a general cbar.set(..., formatter=...)
The same issue applies for ticks, although in that case there's actually already set_ticks which already accepts taking a locator as argument; here I guess(?) it should be possible to just let ticks be an alias for locator.
Sure, though in that case one may even ask why cbar.locator/cbar.formatter even exists as accessing through the axis would likewise work. I think the advantage of having direct/shorthand access is in particular because it is generic wrt orientation (i.e. you can write the same code for horizontal and for vertical axes); what I'm suggesting here is that the shorthand versions should go through getters/setters like many other Matplotlib APIs rather than through properties.
I'm not super against adding these, I just think we should decide if we want all these shortcuts, or if we want to make the API more like axes. Another idea is to provide long_axis as a property and then you could do cax.long_axis.set_major_formatter so that the same code could be used for horizontal and vertical
Added to the weekly meeting. If he cannot make it, perhaps @timhoffm has an opinion. @greglucas has also though a lot about colorbar.
My personal take would be that exposing long_axis stops us from having to expose a whole shadow axis API on colorbar, in keeping with the goal of making colorbar a more normal axes.
My personal take would be that exposing long_axis stops us from having to expose a whole shadow axis API on colorbar, in keeping with the goal of making colorbar a more normal axes.
This is reasonable and should be done for the arguments given. Maybe there's a better name than long_axis? value_axis, color_axis ...?
Of course, it does not allow the orignally requested calls ((fig.colorbar(..., formatter=...)) or cbar.set(..., formatter=...)). While they would be nice as well, this indeed means reexposing already existing axis functions. I suggest to not do this right now. If there is a strong desire for that later and the cbar.*_axis access is not sufficient, we can always add that later.
BTW, I don't think this precludes passing formatter= etc in the colorbar constructor. The only issue there is if we want major/minor to be differentiated.
Ah, I had completely missed that API; I agree that's enough for the high-level interface. Perhaps ticks and format could gain aliases (locator and formatter respectively), though, so that they are available under more standard names?
I'm -0.5 on aliases here. Aliases have a cost (additional code, longer documentation). AFAIK, we don't have other cases where we pass in Formatters or Locators as a configuration parameter, so it's not strictly a consistency topic.
Maybe even more important: aside from Locators/Formatters the kwargs accept a list of tick positions/a format string. While the present kwargs read well both ways (colorbar(..., format='%.3f', ticks=[1, 2, 3]) and colorbar(..., format=DateFormatter("%Y-%m-%d"), ticks=MaxNLocator(5))), using colorbar(..., formatter='%.3f', locator=[1, 2, 3]) feels a bit odd. - The reason being: The current kwargs format/ticks generically describe semantics, but formatter/locator call for specific specific code representations (classes) of the semantics.
The current kwargs format/ticks generically describe semantics, but formatter/locator call for specific specific code representations (classes) of the semantics.
Note that this is already not really anymore the case, as Axis.set_major_formatter already accepts format strings and arbitrary callables (respectively autoconverting them to StrMethodFormatter and to FuncFormatter). Colorbar tries to accept both %-format strings and {}-format strings, so at least something like formatter="{:.3f}" still only requires an alias, and is consistent with the set_major_formatter API.
Can you please comment on the reasoning behind going with long_axis? While that name is ok and clear enough to understand, the purely geometrical description is a different logical approach than x/y axis. color_axis or value_axis seem more logically consistent with x/yaxis to me:
color_axis: the scatter(x, y, color) inputs go to the xaxis/yaxis/color_axis).
value_axis: the type of data in the axis are the values associated with the colors - note that the color name part will typically come in via the Colorbar Axes, I.e. colorbar.value_axis, so that we don’t need an extra “color” in the axis attribute like colorbar.color_value_axis
Bluntly speaking, long_axis feels a bit like if we had named yaxisvertical_axis instead. It’s clear, but vertical_axis and xaxis do not rhyme.
The logic against "color_axis" was that it would cross with the things you change through the norm / colormap vs the things you change via the axis.
The logic against "value_axis" is that everything is a "value". It leaves too much space for users to do "wishful API reading" and have incorrect expectations about what it refers to.
The logic for "long_axis" is that if two people are looking at a figure with a color bar Q: "which axis of the colorbar are the ticks on?" A: "the long axis" is completely unambiguous.
With x and y there are very ingrained expectations of what those mean (and we Axes level API with x/y/z in the names). With the color axis there is less ingrained expectations. Rather than try to induce those expectations, go with the super clear geometric naming.
Thanks for the explanation and patience. I want to make sure we have carefully chosen the new API. If there is still a majority for long_axis after weighing the arguments, I'll submit to that.
The key distinction between a colorbar Axes and and a standard x/y Axes is that the colorbar is conceptually 1D: we only have one axis that contains semantic information. If possible, I'd like to have that captured in the name. labelled_axis basically works, but feels a bit bulky (maybe that is just me always struggling to remember whether there's a double "l" or not).
I just started to like data_axis. While data is a very generic term and should usually be avoided, maybe we actually want that generic aspect here. We don't need to focus on the exact type of data (one can think label, color, numeric value as one likes). data generically captures the semantic information aspect, contrasting from the other non-data axis.
Activity
jklymak commentedon Sep 23, 2023
You can access the yaxis and set these like you do for any other axes, can't you?
anntzer commentedon Sep 23, 2023
Sure, though in that case one may even ask why cbar.locator/cbar.formatter even exists as accessing through the axis would likewise work. I think the advantage of having direct/shorthand access is in particular because it is generic wrt orientation (i.e. you can write the same code for horizontal and for vertical axes); what I'm suggesting here is that the shorthand versions should go through getters/setters like many other Matplotlib APIs rather than through properties.
jklymak commentedon Sep 24, 2023
I'm not super against adding these, I just think we should decide if we want all these shortcuts, or if we want to make the API more like axes. Another idea is to provide
long_axisas a property and then you could docax.long_axis.set_major_formatterso that the same code could be used for horizontal and verticalanntzer commentedon Sep 24, 2023
Publically exposing long_axis seems fine to me too.
jklymak commentedon Sep 27, 2023
Added to the weekly meeting. If he cannot make it, perhaps @timhoffm has an opinion. @greglucas has also though a lot about colorbar.
My personal take would be that exposing
long_axisstops us from having to expose a whole shadow axis API on colorbar, in keeping with the goal of making colorbar a more normal axes.timhoffm commentedon Sep 28, 2023
This is reasonable and should be done for the arguments given. Maybe there's a better name than
long_axis?value_axis,color_axis...?Of course, it does not allow the orignally requested calls (
(fig.colorbar(..., formatter=...))orcbar.set(..., formatter=...)). While they would be nice as well, this indeed means reexposing already existing axis functions. I suggest to not do this right now. If there is a strong desire for that later and thecbar.*_axisaccess is not sufficient, we can always add that later.anntzer commentedon Sep 28, 2023
I think exposing long_axis (name TBD) would be good enough, and agree that "exposing a whole shadow axis API on colorbar" is not great.
jklymak commentedon Sep 28, 2023
main_axis?primary_axis?value_axisandcolor_axisare good too. Agree thatlong_axisis probably not intuitive - it's just what we have internally.jklymak commentedon Sep 28, 2023
BTW, I don't think this precludes passing
formatter=etc in the colorbar constructor. The only issue there is if we want major/minor to be differentiated.timhoffm commentedon Oct 5, 2023
Note that there is already a
formatkwarg in the factory function https://matplotlib.org/stable/api/figure_api.html#matplotlib.figure.Figure.colorbar. That applies to the major formatter should be enough as a high level interface forcolorbar(). In the rare case that users need more conrol, they should go through the axis.anntzer commentedon Oct 5, 2023
Ah, I had completely missed that API; I agree that's enough for the high-level interface. Perhaps ticks and format could gain aliases (locator and formatter respectively), though, so that they are available under more standard names?
timhoffm commentedon Oct 5, 2023
I'm -0.5 on aliases here. Aliases have a cost (additional code, longer documentation). AFAIK, we don't have other cases where we pass in Formatters or Locators as a configuration parameter, so it's not strictly a consistency topic.
Maybe even more important: aside from Locators/Formatters the kwargs accept a list of tick positions/a format string. While the present kwargs read well both ways (
colorbar(..., format='%.3f', ticks=[1, 2, 3])andcolorbar(..., format=DateFormatter("%Y-%m-%d"), ticks=MaxNLocator(5))), usingcolorbar(..., formatter='%.3f', locator=[1, 2, 3])feels a bit odd. - The reason being: The current kwargsformat/ticksgenerically describe semantics, butformatter/locatorcall for specific specific code representations (classes) of the semantics.anntzer commentedon Oct 5, 2023
Note that this is already not really anymore the case, as Axis.set_major_formatter already accepts format strings and arbitrary callables (respectively autoconverting them to StrMethodFormatter and to FuncFormatter). Colorbar tries to accept both %-format strings and {}-format strings, so at least something like
formatter="{:.3f}"still only requires an alias, and is consistent with the set_major_formatter API.timhoffm commentedon Oct 5, 2023
Point taken. Still, I'm unsure whether aliases are worth it. Let's say. I'm -0 on
formatteralias now.tacaswell commentedon Oct 12, 2023
The consensus of the developer call is to expose
long_axisas a public property .timhoffm commentedon Oct 24, 2023
Can you please comment on the reasoning behind going with
long_axis? While that name is ok and clear enough to understand, the purely geometrical description is a different logical approach than x/y axis.color_axisorvalue_axisseem more logically consistent with x/yaxis to me:color_axis: the scatter(x, y, color) inputs go to the xaxis/yaxis/color_axis).value_axis: the type of data in the axis are the values associated with the colors - note that the color name part will typically come in via the Colorbar Axes, I.e.colorbar.value_axis, so that we don’t need an extra “color” in the axis attribute likecolorbar.color_value_axisBluntly speaking,
long_axisfeels a bit like if we had namedyaxisvertical_axisinstead. It’s clear, butvertical_axisandxaxisdo not rhyme.anntzer commentedon Oct 24, 2023
Fwiw value_axis and color_axis both sound good to me, with a slight preference for the former I think.
tacaswell commentedon Oct 24, 2023
The logic against "color_axis" was that it would cross with the things you change through the norm / colormap vs the things you change via the axis.
The logic against "value_axis" is that everything is a "value". It leaves too much space for users to do "wishful API reading" and have incorrect expectations about what it refers to.
The logic for "long_axis" is that if two people are looking at a figure with a color bar Q: "which axis of the colorbar are the ticks on?" A: "the long axis" is completely unambiguous.
With x and y there are very ingrained expectations of what those mean (and we Axes level API with x/y/z in the names). With the color axis there is less ingrained expectations. Rather than try to induce those expectations, go with the super clear geometric naming.
My preference is long > color > value.
jklymak commentedon Oct 24, 2023
long_axis is pretty intuitive - in my view xaxis is only intuitive because of long tradition; certainly the xaxis is often not the xaxis.
I don't like either color_axis or value_axis for the reasons above, though I find color_axis the most confusing. I'd rank long > value >> color.
Maybe
labelled_axissince that is what is functionally being done here?timhoffm commentedon Oct 26, 2023
Thanks for the explanation and patience. I want to make sure we have carefully chosen the new API. If there is still a majority for
long_axisafter weighing the arguments, I'll submit to that.The key distinction between a colorbar Axes and and a standard x/y Axes is that the colorbar is conceptually 1D: we only have one axis that contains semantic information. If possible, I'd like to have that captured in the name.
labelled_axisbasically works, but feels a bit bulky (maybe that is just me always struggling to remember whether there's a double "l" or not).I just started to like
data_axis. Whiledatais a very generic term and should usually be avoided, maybe we actually want that generic aspect here. We don't need to focus on the exact type of data (one can think label, color, numeric value as one likes).datagenerically captures thesemantic informationaspect, contrasting from the other non-data axis.timhoffm commentedon Oct 27, 2025
I think this is reasonably solved via the
long_axisproperty #27167. You can docbar.long_axis,set_minor_locator()and the likes.@anntzer please reopen if I'm missing something.
anntzer commentedon Oct 27, 2025
That's close enough, indeed.