Feature request: An easier / better way to work with the offset_text when it is used by ticklabel_format

I have already written an extensive post about this on stackoverflow, so I thought it’s best to just link it here. If I should do it differently, please let me know.

Please don’t just link to SO, it makes the discussion hard to follow (particularly because SO questions and answers can change drastically over time or be deleted).

Clicking through I don’t quite understand how that question relates to the title of this post, can you please explain what you mean by “easier / better” and “work with”?

Thanks for your interest, and sorry about being so vague in the title and only linking to SO. I won’t do that in the future anymore.

Let me try to be a little bit more specific:

  • Nowhere in the documentation of ticklabel_format is it mentioned that the offset_text is being used to display the information regarding the order of magnitude and such. It would be great if this could be explained, because how else are you supposed to know that? I only found out about it because somebody else pointed it out to me. Before that, I used get_children and looked for the artist that has the expexted text. By the way, from the examples linked in the description, for me, none of them look like what they are supposed to look like, in particular the lower left panel, but maybe that is setup-dependent.
  • It would be great if there was a way to access the information generated by ticklabel_format without having to draw the figure first, because not only can that be super expensive, it also generally seems to be extreme overkill having to redraw the whole figure just so you can access that information.
  • Lastly, I never understood why this information is displayed like that on default anyways. I have never seen scientific work where data is actually presented that way. Every author puts that kind of information in the axis label, or at least to where the information about the units is displayed. It makes it much more readable. So why not have ticklabel_format return the information as a string (or tuple of strings to include all axis)? That way, everyone can decide on their own where to display that information or if at all. Maybe having keywords like useOffsetText and returnText would already do the trick.

Apart from that, now that I know that all that digging that I did was in fact for nothing, I am still curious as to why:

  • there is no documentation for Artist.get_tightbbox. Is that by accident or deliberate?

  • my ‘detached’ version of get_tightbbox doesn’t work like the instance method:

    Running get_tightbbox(colorbar.ax, renderer) , get_tightbbox is only executed once (as you would assume), but running colorbar.ax.get_tightbbox(renderer) , it runs several times, for a bunch, but not all, of the colorbar.ax 's children.

    from matplotlib.transforms import Bbox
    
    def get_tightbbox(artist, renderer):
        """
        Like `Artist.get_window_extent`, but includes any clipping.
    
        Parameters
        ----------
        renderer : `.RendererBase` instance
            renderer that will be used to draw the figures (i.e.
            ``fig.canvas.get_renderer()``)
    
        Returns
        -------
        bbox : `.BBox`
            The enclosing bounding box (in figure pixel co-ordinates).
        """
        bbox = artist.get_window_extent(renderer)
        if artist.get_clip_on():
            clip_box = artist.get_clip_box()
            if clip_box is not None:
                bbox = Bbox.intersection(bbox, clip_box)
            clip_path = artist.get_clip_path()
            if clip_path is not None and bbox is not None:
                clip_path = clip_path.get_fully_transformed_path()
                bbox = Bbox.intersection(bbox, clip_path.get_extents())
    
        return bbox
    

It sounds like what you want is to write a custom Formatter subclass (see https://matplotlib.org/3.3.0/api/ticker_api.html) that at draw time updates the axis label with a templated string? That will almost certainly being less work than trying to scrape information back out of the default formatter. We don’t do that by default because that introduces a very strong coupling between the tick lables and the axis label that is not generally desired.

A different formatter may use the offset string differently, assuming you can parse the text to extract information is going to be extremely brittle.

If you are willing to assume that you always have a ScalerFormatter, then the values you want are (definitely after the first draw, maybe a bit sooner) the .offset and .orderOfMagnitude` attributes on the formatter.

There are some internally derived values that we only update on draw. If the user is changing things about the figure we do not want to waste time doing a computation that we are then going to immediately re-do. We do not have a “phased” draw process, either the figure is “stale” and you should assume that internally computed values may be inconsistent or we done a draw more recently than the state of the figure has been changed all of the internal state is consistent.

Please be careful about extrapolating from your personal experience and opinions to be either general or facts. Matplotlib has an extremely diverse user base and different fields have different conventions. Because our default behavior does not match your field’s conventions does not mean the defaults are wrong.

The figures rendered on the website look correct to me, can you please elaborate on this?

We are a majority volunteer project that has grown organically over the 15+ years, just like there are bugs, there are gaps in the documentation. That the method has a docstring but is not included in the html docs is likely an oversight. We always love to see PRs that extend or correct the documentation :slight_smile:

The documentation is always going to leave out some details about the implementation

I am again having a very hard time understanding what you mean. I suspect that this is something interesting, but I am missing so much of the context that is in your head. I could probably come up with something, but it is unlikely that I would re-implement exactly what you are seeing. If you could provide a self-contained copy-paste-runnable example of what you are seeing it makes everything much easier.

It sounds like what you want is to write a custom Formatter subclass (see https://matplotlib.org/3.3.0/api/ticker_api.html) that at draw time updates the axis label with a templated string? That will almost certainly being less work than trying to scrape information back out of the default formatter.

That sounds like a very interesting suggestion. I have no idea how to do that, and it doesn’t seem to be something super straight forward, but I will keep that in mind! It looks like an elegant solution.

Please be careful about extrapolating from your personal experience and opinions to be either general or facts. Matplotlib has an extremely diverse user base and different fields have different conventions. Because our default behavior does not match your field’s conventions does not mean the defaults are wrong.

I absolutely agree, which is also why I never made such definitive statements. I never said that because I experienced a certain convetion, it must be the general way of things, or even worse, that my preference is right, and matplotlibs defaults are wrong. But seeing that my posts got flagged so much after I made this post (for advertisement or promotion of all the reasons), I take it many people here were already offended by it, which was never my intention. But it’s also wierd, because it would still be fair to provide constructive critique like that. Anyways, that makes me even more grateful that you are taking the time and make the effort for elaborate responses! Thanks a lot. I know this is off topic, but the message tells me to “please consider how you might revise your post to reflect their feedback.” which I have no idea what that’s even supposed to mean in this context. But I guess it’s not like it matters anyways, because not many would care about if my posts are visible or not.

The figures rendered on the website look correct to me, can you please elaborate on this?

Here is what it looks like to me, e.g. (I can only show one image as a new user appearently):

We are a majority volunteer project that has grown organically over the 15+ years, just like there are bugs, there are gaps in the documentation. That the method has a docstring but is not included in the html docs is likely an oversight. We always love to see PRs that extend or correct the documentation

Yes of course! This certainly wasn’t meant to be rude. I just wanted to point out stuff that I noticed. There might have been a good reason for why it was not documented.

The documentation is always going to leave out some details about the implementation

I undestand that, but I feel like knowing this piece of information could be very useful. I think knowing how to change, or at least have access to the text is something that comes quite naturally when using ticklabel_format.

I am again having a very hard time understanding what you mean. I suspect that this is something interesting, but I am missing so much of the context that is in your head. I could probably come up with something, but it is unlikely that I would re-implement exactly what you are seeing. If you could provide a self-contained copy-paste-runnable example of what you are seeing it makes everything much easier.

I’m sorry, I’ll try to come up with something.

I cleared the moderation requests, I think it was an automated check from discourse not human flagged.


I’m sorry for miss-reading what you meant. We currently barely know each other and only having text it is easy to read the wrong meaning.

Criticism of the library is definitely fair game! That is how we get better, but please be respectful about it. Everything in the library is there because at some point it solved a problem for someone.

Thanks a lot! I know that written communication can sometimes be missleading, so I am sorry if my statements were ambiguous. I will try to be more careful next time.

I gave an example of how to write a locator to do this on stackoverflow.

I know, sorry for opening this up on two fronts. Your answer came in shortly after I posted this here. I actually thought you saw my post here and then went to answer it on SO.
But now I am a little confused again. Is locator = formatter?

Sorry typo: formatter.