-
Notifications
You must be signed in to change notification settings - Fork 368
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
Using Gridliner and Figure(layout="constrained") together misbehaves #2245
Comments
A workaround for this is to manually call the layout engine before save so that the algorithm gets more iterations to figure out where everything is supposed to be (as well as setting #!/usr/bin/env python3
import cartopy.crs
import numpy
from matplotlib import pyplot as plt
from matplotlib.collections import PolyCollection
# Make a figure with a specific size
figure = plt.figure(figsize=(8, 4), layout="constrained")
# Make some axes that will fill the available space while maintaining correct aspect ratio
axes = figure.add_subplot(projection=cartopy.crs.PlateCarree())
axes.set_aspect(aspect='equal', adjustable='datalim')
# Add some polygon to the map, with a colour bar
collection = PolyCollection(
verts=[
[[0, 0], [1, 0], [1, 1], [0, 1]],
[[1, 0], [2, 0], [2, 1], [1, 1]],
[[0, 1], [1, 1], [1, 2], [0, 2]],
[[1, 1], [2, 1], [2, 2], [1, 2]],
],
array=[1, 2, 3, 4],
)
axes.add_collection(collection)
figure.colorbar(collection, ax=axes, location='right', label='index')
# Set up the axes data limits to keep the polygon in view
axes.autoscale()
# Add some gridlines
gridlines = axes.gridlines(draw_labels=["bottom", "left"], auto_update=True)
# Extra call to the layout engine
figure.get_layout_engine().execute(figure)
figure.savefig('figure.png') |
There are currently a number of problems with gridlines on plots in Jupyter notebooks. There are different solutions that depend on whether you want an interactive plot, a static plot in a notebook, or are saving the plot to a file. Unfortunately there is no single solution that works in all cases currently. Until a proper solution is found, users can disable gridlines and then re-enable them in the way that works for their current environment. SciTools/cartopy#2245 SciTools/cartopy#2246 SciTools/cartopy#2247
There are currently a number of problems with gridlines on plots in Jupyter notebooks. There are different solutions that depend on whether you want an interactive plot, a static plot in a notebook, or are saving the plot to a file. Unfortunately there is no single solution that works in all cases currently. Until a proper solution is found, users can disable gridlines and then re-enable them in the way that works for their current environment. SciTools/cartopy#2245 SciTools/cartopy#2246 SciTools/cartopy#2247
The problem is here: cartopy/lib/cartopy/mpl/geoaxes.py Lines 485 to 489 in f2bb81d
The first time the constrained layout algorithm runs, everything works as it should and constrained layout gives the axes a new position taking up more of the figure. The second time the algorithm runs, cartopy/lib/cartopy/mpl/gridliner.py Lines 1177 to 1182 in f2bb81d
So this time the y-axis labels get positioned inside the axes. There is also some logic (which I haven't quite followed) that sets them to invisible based on their (wrong) position. So ultimately constrained layout is trying to make space for artists that keep appearing and disappearing. The fix is simply to call |
Thanks for looking in to this! Much appreciated |
Description
I am trying to use the new constrained layout engine from matplotlib in combination with a GeoAxes with gridlines. I can not find a combination that works properly. All combinations I try fail in some way or another, some with poor styling and some with actual crashes.
I need to make plots of a specific size, and I would like the axes, titles, colour bars, etc to fill the available space. A
Figure(layout="constrained")
combined withaxes.set_aspect("equal", "datalim")
works perfectly for this. The figure is always of the correct size, and the axes are reshaped to fill the figure. By setting the appropriate xlim/ylim, or by usingaxes.autoscale()
the elements to be plotted are arranged within the axes correctly.I would also like to include grid lines on the axes. No matter which options I choose, I can not get the grid lines to behave.
Code to reproduce
I installed the latest versions of Python, cartopy, matplotlib:
I then added the following to a script and ran it:
This results in the grid lines not filling the available space correctly:
My best guess is that the gridlines don't notice that the layout engine has done its thing and so the grid lines are now misplaced.
If I remove the
axes.set_aspect(...)
line the gridlines correctly cover the area, but the axes are shrunk to only take up the necessary space leaving a large gap. It would be possible to configure anchor points and etc to arrange this a little nicer, but I want the axes to take up the available space:If I instead remove the
layout="constrained"
from the figure, the plot components do not fill up the entire space. This plot looks the best of the lot, but I would like to make use of the new layout engine.I tried adding
auto_update=True
to the gridlines, and while this does result in the gridlines being adjusted correctly, the labels are now off the edge of the figure:Full environment definition
Operating system
Ubuntu 20.04
Cartopy version
0.22.0
conda list
The text was updated successfully, but these errors were encountered: