-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Fix inset_axes + doc #11060
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix inset_axes + doc #11060
Conversation
I support in general! Sorry if my attempts to fix things made them worse. Thanks for taking a close and careful look |
3dd84b7
to
a859dc0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great, but some minor wording suggestions and clarifications. Thanks!
Bbox that the inset axes will be anchored to. If None, | ||
*parent_axes.bbox* is used. If a tuple, can be either | ||
[left, bottom, width, height], or [left, bottom]. | ||
If *width* and/or *height* are given in relative units, the 2-tuple |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"If the kwargs width and height are specified ..." Otherwise not clear that you are not referring to the width and height just mentioned.
|
||
bbox_transform : `matplotlib.transforms.Transform`, optional | ||
Transformation for the bbox. if None, `parent_axes.transAxes` is used. | ||
Transformation for the bbox. If None, a `.transforms.IdentityTransform` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...for the bbox that contains the inset axes.
"... is used (i.e. pixel co-ordinates). "
Transformation for the bbox. if None, `parent_axes.transAxes` is used. | ||
Transformation for the bbox. If None, a `.transforms.IdentityTransform` | ||
is used. This is useful when not providing any argument to | ||
*bbox_to_anchor*. When using *bbox_to_anchor* it almost always makes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand whats useful about specifying "None", when not specifying a bbox_to_anchor? In that case surely the bbox_to_anchor is the parent_axes and the transform is transAxes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the default case: inset_axes(parent_axes, width="40%", height="30%")
. I suppose that is how people want to use this most often. In that case, bbox_to_achor
is parent_axes.bbox
and bbox_transform
is None
, which is the transforms.IdentityTransform()
. This is not transAxes
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Width and height get turned into pixels?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, width
and height
are either in inches or relative to the bounding box (percentage). At the end of the day, everything is turned into pixels.
Concerning the bounding box, if bbox_transform
is None
, the IdentityTransform()
is used. That means that the bbox_to_anchor
is in pixels. This makes sense, because the standard parent_axes.bbox
is e.g.
(x0=0.125, y0=0.11, x1=0.9, y1=0.88), transformed to (x0=0.0, y0=0.0, x1=6.4, y1=4.8), transformed by the dpi of 100, resulting in
(80.0, 52.8, 496.0, 369.6)
which is in pixels.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think anything should be thought of as pixels until draw time. Axes bboxes are in figure-relative units (as they should be), and not converted until draw time to pixels. Because at draw time, the dpi changes more often than not. See all the inconsistencies in the docs and code that have to do w/ dpi. I really don't think the bbox_transform
should default to None
here, but rather to the units consistent with the default for bbox_to_anchor
which is figure-coordinates. But I appreciate this was the historical way it was done, so we are stuck with it...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, first of all Axes bboxes are TransformedBbox
es. So they are somehow transient until draw time. But then they evaluate to pixels. This is not a problem at all. The problem only occurs when allowing the user to specify some other bounding box. Since the user usually won't create a TransformedBbox
, but rather use a static tuple here, they would usually need to set a different transform as well. But we wouldn't want to include the complete logic of guessing what the user wants inside of this function, right? Like "if a bbox_to_anchor is specified and it is a tuple, chances are 98% that the user would have wanted to use the ax.transAxes, so let's change this silently." is not an option.
I would agree that if writing such function again, one may come up with a better way, possibly simply not allowing for width/height in inches, therefore being able to use a different default transform altogether etc. The aim of this PR is to restore the old behaviour. Anything else can go outside of axes_grid1
into whatever new fancy features to come.
sense to also specify a *bbox_transform*. This might often be the | ||
axes transform *parent_axes.transAxes*. Inversely, when specifying | ||
the axes- or figure-transform here, make sure to provide a bounding | ||
box to *bbox_to_anchor* as well, else the result may be unexpected. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is too vague. What bbox is used if the user doesn't specify bbox_to_anchor? Maybe:
"...figure-transform here, be aware that not specifying bbox_to_anchor will use parent_axes.bbox, the units of which are in figure.transFigure"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm now doing:
Inversely, when specifying the axes- or figure-transform here, be aware that not specifying
bbox_to_anchor will use parent_axes.bbox, the units of which are
in display (pixel) coordinates.
@@ -437,6 +465,8 @@ def inset_axes(parent_axes, width, height, loc=1, | |||
|
|||
borderpad : float, optional | |||
Padding between inset axes and the bbox_to_anchor. Defaults to 0.5. | |||
The units are font size, i.e. for a default font size of 10 points |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are the axes fontsize
if bbox_transform in [parent_axes.transAxes, | ||
parent_axes.figure.transFigure]: | ||
if bbox_to_anchor is None: | ||
warnings.warn("Using the axes or figure transform requires to " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"requires a bounding..."
|
||
bbox_transform : `matplotlib.transforms.Transform`, optional | ||
Transformation for the bbox. if None, `parent_axes.transAxes` is used. | ||
Transformation for the bbox. If None, a `.transforms.IdentityTransform` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above
a859dc0
to
a10831c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks again!
a10831c
to
fe2b396
Compare
9ba94a7
to
3225451
Compare
@tacaswell This would be another example where it's not clear how to handle concerning backporting. This PR mostly enhances documentation and fixes a bug that has previously been introduced into master. In so far it is probably not worth backporting. On the other hand it fixes a critical sentence in the docs which was simply wrong and led to some confusion and even a wrong PR being merged to master based on this one sentence. |
@ImportanceOfBeingErnest why would it conflict if six was removed and you backported? I don't see that your changes use six anywhere, but I didn't check carefully. The confusing thing is that only the diff with the branch is ported so if your diff with master doesn't have anything that requires six, then your diff with 2.2.3 shouldn't either. Where we will run into difficulty is when you use a py3 feature that requires six to be able to work in py2. |
Maybe I didn't understand it correctly. So what you are saying is that there will never be a diff between the file on master and the file on the other branch being calculated? Instead only the diff between my file and the one on master is directly transferred into the other branch? |
3225451
to
d5fe96f
Compare
d5fe96f
to
60e9ec0
Compare
Rebased. |
Ping. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a much needed improvement to me.
I'd like someone more familiar with axes_grid to mash the green button though.
There seem to be a conflict, please backport manually |
Happily mashed! (not that I'm claiming I'm more familiar than you - but "familiar enough".... |
First of all, big thanks to @ImportanceOfBeingErnest and @jklymak (and others) for the effort.
|
@leejjoon It seems this makes sense. Would you have the bandwidth to do a PR on that? Or, if not, point to the places where you envision adding this? |
Yes, I will work on the PR. |
This does not backport cleanly and depends an other changes that are on master branch for the newtests to work. |
The only thing that would strictly need to be backported here is the removal of the docstring saying
because that sentence is blantly wrong. Everything else in this commit is a fix for an issue which was not present in 2.2, and a lot of enhancements for docstrings, tests and understandable errormessages. Now because #11079 is equally not backported, the docstrings are not even shown in the 2.2 documentation builds. |
ok, I'll make a more through attempt to backport both of them. |
…inset_axes Fix inset_axes + doc Conflicts: examples/axes_grid1/inset_locator_demo.py - kept master branch version examples/axes_grid1/inset_locator_demo2.py - kept master branch version lib/mpl_toolkits/axes_grid1/inset_locator.py - conflicts around __future__ import
PR Summary
This PR fixes the mpl_toolkit's
inset_axes
, which got broken via #10756, and adds documentation as well as examples.More in detail:
As seen from #8120 as well as #8952,
inset_axes
can be confusing. While #8952 is solved simply by knowing that in order to use relative units, a 4-tuple must be given, #8120 results from confusion about the transform being None and hence being the display units.The specific case from #8120 has been "fixed" in #10756 by changing the default transform. Unfortunately noone noticed that this broke all the usual intended behaviour of
inset_axes
. Two tests which were introduced in #10756 did not actually assert those default cases.An attempt by @jklymak in #10986 to fix the broken behaviour was too stingent and would have broken other previously working cases.
This PR:
inset_axes
remains completely backward compatible.inset_axes
docstring is significantly extended.The following table summarizes the possible use cases and shows in how far they are now documented and tested.
PR Checklist