Coming from this stackoverflow question, some strange (to me) behaviour is observed when plotting partial or wedged polar plots. This new feature, which can be used by setting .set_thetamin and .set_thetamax on a polar plot, allows to plot only part of a polar plot without the need to use floating axes - which is of course a great feature.
The problem arises when either using those partial polar plots as subplots or when trying to plot them tightly in a figure. It seems like their position is always set to be in the middle of some kind of subplot with aspect ratio of 1. Especially when using a half circle polar plot, this causes a lot of unnecessary white space around the half-circle.
Consider this code:
importnumpyasnpimportmatplotlib.pyplotaspltfig, axes=plt.subplots(1, 2, subplot_kw={'projection': 'polar'},
figsize=(8, 4))
fori, theta_maxinenumerate([2*np.pi, np.pi]):
# define theta vector with varying end point and some data to plottheta=np.linspace(0, theta_max, 181)
axes[i].set_thetamin(0)
axes[i].set_thetamax(theta_max*180/np.pi)
axes[i].set_xlabel('Magnitude', fontsize=15)
axes[i].set_ylabel('Angles', fontsize=15)
plt.savefig("polarwedges2.svg", facecolor="#e8f4f2")
which produces the top plot in the below image. I have manually marked the region which is occupied by the polar plot, calling it "Incompressible BBox", because it occupies much more space than desired, also making the xlabel appearing totally off. The picture below is what I would expect this subplot to behave like.
The "imcompressibility" of that box also prevents to have such a half-circle polar plot tight in a figure.
In the following code a simple figure with such a plot is attempted.
importmatplotlib.pyplotaspltfig, ax=plt.subplots(1, 1, figsize=(6,3.4), subplot_kw={'projection': 'polar'})
# set 'thetamin' and 'thetamax' according to dataax.set_thetamin(0)
ax.set_thetamax(180)
ax.set_xlabel('Magnitude', fontsize=15)
ax.set_ylabel('Angles', fontsize=15)
plt.savefig("polarwedge3.svg", facecolor="#e8f4f2")
The plot appears much smaller than the figure would allow for and leaves a lot of white space around.
The only workaround I can currently think of is to make the original axes much larger than the figure (ax.set_position( [0.1, -0.45, 0.8, 2])) and shift the xlabel manually by some amount towards the top, as shown in the lower picture. Workaround code.
importmatplotlib.pyplotaspltfig, ax=plt.subplots(1, 1, figsize=(6,3.4), subplot_kw={'projection': 'polar'})
# set 'thetamin' and 'thetamax' according to dataax.set_thetamin(0)
ax.set_thetamax(180)
ax.set_xlabel('Magnitude', fontsize=15, labelpad=-60)
ax.set_ylabel('Angles', fontsize=15)
ax.set_position( [0.1, -0.45, 0.8, 2])
plt.savefig("polarwedge4.svg", facecolor="#e8f4f2")
I guess this behaviour is in general undesired. One would rather have either the same behaviour as for fixed aspect plots (like imshow, i.e. what is called "compressible" above) or even better, some API to set the position to useful values according to the usual subplot mechanism.
This is expected (by me because I wrote it) behaviour, though not really desired. Polar plots set themselves to have equal aspect by default. This is only done in __init__ though, so wedges are simply zoomed as much as possible to fit in that square box.
Since the space for the Axes is provided by the Figure, I never really knew how to get it to resize itself, and still don't really know. If anyone knows, I'd like to find out, because it's something that seems desirable in other places, like Cartopy for instance.
This seems like something a constrained layout manager might be able to
handle? Maybe somewhat?
Allowing a plot to resize a figure is currently a big no-no in matplotlib.
It is technically possible, but it would be a really bad idea in practice.
What I do personally is to call matplotlib.figure.figaspect() to give me a
reasonable figure size ahead of time.
On Wed, Jan 17, 2018 at 7:57 PM, Elliott Sales de Andrade < ***@***.***> wrote:
This is expected (by me because I wrote it) behaviour, though not really
desired. Polar plots set themselves to have equal aspect by default. This
is only done in __init__ though, so wedges are simply zoomed as much as
possible to fit in that square box.
Since the space for the Axes is provided by the Figure, I never really
knew how to get it to resize itself, and still don't really know. If anyone
knows, I'd like to find out, because it's something that seems desirable in
other places, like Cartopy for instance.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#10264 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AARy-IkvVWW25Sz1z_QMzaoEwYnwnllvks5tLpcUgaJpZM4RiMhQ>
.
Well, it's not resizing the Figure that's needed, "just" resizing the space needed for the Axes. But I think that's still managed by the Figure itself, no?
I have to admit that my understanding of the internals is rather limited. But since normal image subplots are handled exactly as desired (i.e. their axes size is as large as the image itself by default) I would have thought that there is a mechanism that provides this behaviour and which can be used here as well.
First there is a constrained layout manager PR #9082.
Since the space for the Axes is provided by the Figure, I never really knew how to get it to resize itself, and still don't really know. If anyone knows, I'd like to find out, because it's something that seems desirable in other places, like Cartopy for instance.
The space that the axes is being drawn is set by subplots, where it returns a position for the axes, called the "original" position. If you set the x/ylim of this axis, and then set the aspect then the there is an "active" position that tells us where the new axis is.
Bizarrely, that new position doesn't calculated until draw time, which is not of too much use if you call get_position(original=False). (please see #9855 which fixes this, but hasn't been reviewed yet).
I don't know the internals of the polar projection. if I was just drawing half a circle on a Cartesian projection, I'd set the ylim = [0.5 1.], xlim=[0., 1.] and then the "active" axis would be the right aspect ratio.
I'd need to play w/ the above, but it seems maybe polar projection should have some awareness of the extent it wants to draw over and modify its transform accordingly. It may need to modify the "active" axis position as well, but I don't know how polar does that at the moment.
xlim and ylim are in data coordinates, so that wouldn't work (your xlim is 0 to 57 degrees). After looking around, I do think some fiddling with the "active" position could probably work, but it would require some tweaking of internals that assume square equal aspect ratio.
Yeah, and I don't understand the Transforms. Whats happening now is that set_aspect('equal') is defining a cartesian box in the middle of the axis with relative limits 0-1, 0-1 that I presume the transform now maps into.
I think that aspect should be changed from 1 to 0.5 (in the present case, or whatever fraction of the circle is being made) and the y part of the transform multiplied by 2.0.
If I set_aspect in PolarAxes, I get half way there with the x-axis stretched. But I don't understand the Transforms well enough to then get the y-direction to stretch and be offset down.
Yes, I've found something similar. Partially, the problem is in the wedge bbox here because it tries extra hard to get equal aspect ratio. I can set aspect ratio in draw where the wedge is updated, but even if that adjustment is ignored, there's still some other bit wrong as clipping is not quite right.
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 have made some progress; the two images from the original post now produce:
I need to clean up the code a bit, but it appears to work nicely in all cases. As you can see above though, the Axis labels might still need some tweaking, as I think they don't account for the optional radial ticks turning on automatically.
Activity
QuLogic commented on Jan 18, 2018
This is expected (by me because I wrote it) behaviour, though not really desired. Polar plots set themselves to have equal aspect by default. This is only done in __init__ though, so wedges are simply zoomed as much as possible to fit in that square box.
Since the space for the Axes is provided by the Figure, I never really knew how to get it to resize itself, and still don't really know. If anyone knows, I'd like to find out, because it's something that seems desirable in other places, like Cartopy for instance.
WeatherGod commented on Jan 18, 2018
QuLogic commented on Jan 18, 2018
Well, it's not resizing the Figure that's needed, "just" resizing the space needed for the Axes. But I think that's still managed by the Figure itself, no?
ImportanceOfBeingErnest commented on Jan 18, 2018
I have to admit that my understanding of the internals is rather limited. But since normal image subplots are handled exactly as desired (i.e. their axes size is as large as the image itself by default) I would have thought that there is a mechanism that provides this behaviour and which can be used here as well.
jklymak commented on Jan 18, 2018
First there is a constrained layout manager PR #9082.
The space that the axes is being drawn is set by subplots, where it returns a position for the axes, called the "original" position. If you set the x/ylim of this axis, and then set the aspect then the there is an "active" position that tells us where the new axis is.
Bizarrely, that new position doesn't calculated until draw time, which is not of too much use if you call get_position(original=False). (please see #9855 which fixes this, but hasn't been reviewed yet).I don't know the internals of the polar projection. if I was just drawing half a circle on a Cartesian projection, I'd set the ylim = [0.5 1.], xlim=[0., 1.] and then the "active" axis would be the right aspect ratio.
I'd need to play w/ the above, but it seems maybe polar projection should have some awareness of the extent it wants to draw over and modify its transform accordingly. It may need to modify the "active" axis position as well, but I don't know how polar does that at the moment.
QuLogic commented on Jan 18, 2018
xlim and ylim are in data coordinates, so that wouldn't work (your xlim is 0 to 57 degrees). After looking around, I do think some fiddling with the "active" position could probably work, but it would require some tweaking of internals that assume square equal aspect ratio.
jklymak commented on Jan 18, 2018
Yeah, and I don't understand the Transforms. Whats happening now is that set_aspect('equal') is defining a cartesian box in the middle of the axis with relative limits 0-1, 0-1 that I presume the transform now maps into.
I think that aspect should be changed from 1 to 0.5 (in the present case, or whatever fraction of the circle is being made) and the y part of the transform multiplied by 2.0.
If I set_aspect in PolarAxes, I get half way there with the x-axis stretched. But I don't understand the Transforms well enough to then get the y-direction to stretch and be offset down.
QuLogic commented on Jan 18, 2018
Yes, I've found something similar. Partially, the problem is in the wedge bbox here because it tries extra hard to get equal aspect ratio. I can set aspect ratio in draw where the wedge is updated, but even if that adjustment is ignored, there's still some other bit wrong as clipping is not quite right.
karlos124c commented on Aug 11, 2021
excellent
github-actions commented on Apr 30, 2023
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!
VladimirIvonin commented on Aug 28, 2024
Any updates?
QuLogic commented on Sep 18, 2024
I have made some progress; the two images from the original post now produce:


I need to clean up the code a bit, but it appears to work nicely in all cases. As you can see above though, the Axis labels might still need some tweaking, as I think they don't account for the optional radial ticks turning on automatically.
juanPabloMiceli commented on Feb 21, 2025
Any updates in merging this PR?