Skip to content

Using Gridliner and Figure(layout="constrained") together misbehaves #2245

@mx-moth

Description

@mx-moth

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 with axes.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 using axes.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:

$ conda install -c conda-forge python cartopy matplotlib

I then added the following to a script and ran it:

#!/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"])

figure.savefig('figure.png')

This results in the grid lines not filling the available space correctly:

figure

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:

figure

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.

figure

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:

figure

Full environment definition

Operating system

Ubuntu 20.04

Cartopy version

0.22.0

conda list

# packages in environment at /home/hea211/hecking-around/emsarray/.conda:
#
# Name                    Version                   Build  Channel
_libgcc_mutex             0.1                 conda_forge    conda-forge
_openmp_mutex             4.5                       2_gnu    conda-forge
alsa-lib                  1.2.10               hd590300_0    conda-forge
attr                      2.5.1                h166bdaf_1    conda-forge
brotli                    1.1.0                hd590300_0    conda-forge
brotli-bin                1.1.0                hd590300_0    conda-forge
bzip2                     1.0.8                h7f98852_4    conda-forge
c-ares                    1.19.1               hd590300_0    conda-forge
ca-certificates           2023.7.22            hbcca054_0    conda-forge
cairo                     1.16.0            h0c91306_1017    conda-forge
cartopy                   0.22.0          py311h320fe9a_0    conda-forge
certifi                   2023.7.22          pyhd8ed1ab_0    conda-forge
contourpy                 1.1.1           py311h9547e67_0    conda-forge
cycler                    0.11.0             pyhd8ed1ab_0    conda-forge
dbus                      1.13.6               h5008d03_3    conda-forge
expat                     2.5.0                hcb278e6_1    conda-forge
font-ttf-dejavu-sans-mono 2.37                 hab24e00_0    conda-forge
font-ttf-inconsolata      3.000                h77eed37_0    conda-forge
font-ttf-source-code-pro  2.038                h77eed37_0    conda-forge
font-ttf-ubuntu           0.83                 hab24e00_0    conda-forge
fontconfig                2.14.2               h14ed4e7_0    conda-forge
fonts-conda-ecosystem     1                             0    conda-forge
fonts-conda-forge         1                             0    conda-forge
fonttools                 4.42.1          py311h459d7ec_0    conda-forge
freetype                  2.12.1               h267a509_2    conda-forge
geos                      3.12.0               h59595ed_0    conda-forge
gettext                   0.21.1               h27087fc_0    conda-forge
glib                      2.78.0               hfc55251_0    conda-forge
glib-tools                2.78.0               hfc55251_0    conda-forge
graphite2                 1.3.13            h58526e2_1001    conda-forge
gst-plugins-base          1.22.5               h8e1006c_1    conda-forge
gstreamer                 1.22.5               h98fc4e7_1    conda-forge
harfbuzz                  8.2.1                h3d44ed6_0    conda-forge
icu                       73.2                 h59595ed_0    conda-forge
keyutils                  1.6.1                h166bdaf_0    conda-forge
kiwisolver                1.4.5           py311h9547e67_0    conda-forge
krb5                      1.21.2               h659d440_0    conda-forge
lame                      3.100             h166bdaf_1003    conda-forge
lcms2                     2.15                 h7f713cb_2    conda-forge
ld_impl_linux-64          2.40                 h41732ed_0    conda-forge
lerc                      4.0.0                h27087fc_0    conda-forge
libblas                   3.9.0           18_linux64_openblas    conda-forge
libbrotlicommon           1.1.0                hd590300_0    conda-forge
libbrotlidec              1.1.0                hd590300_0    conda-forge
libbrotlienc              1.1.0                hd590300_0    conda-forge
libcap                    2.69                 h0f662aa_0    conda-forge
libcblas                  3.9.0           18_linux64_openblas    conda-forge
libclang                  15.0.7          default_h7634d5b_3    conda-forge
libclang13                15.0.7          default_h9986a30_3    conda-forge
libcups                   2.3.3                h4637d8d_4    conda-forge
libcurl                   8.3.0                hca28451_0    conda-forge
libdeflate                1.19                 hd590300_0    conda-forge
libedit                   3.1.20191231         he28a2e2_2    conda-forge
libev                     4.33                 h516909a_1    conda-forge
libevent                  2.1.12               hf998b51_1    conda-forge
libexpat                  2.5.0                hcb278e6_1    conda-forge
libffi                    3.4.2                h7f98852_5    conda-forge
libflac                   1.4.3                h59595ed_0    conda-forge
libgcc-ng                 13.2.0               h807b86a_1    conda-forge
libgcrypt                 1.10.1               h166bdaf_0    conda-forge
libgfortran-ng            13.2.0               h69a702a_1    conda-forge
libgfortran5              13.2.0               ha4646dd_1    conda-forge
libglib                   2.78.0               hebfc3b9_0    conda-forge
libgomp                   13.2.0               h807b86a_1    conda-forge
libgpg-error              1.47                 h71f35ed_0    conda-forge
libiconv                  1.17                 h166bdaf_0    conda-forge
libjpeg-turbo             2.1.5.1              hd590300_1    conda-forge
liblapack                 3.9.0           18_linux64_openblas    conda-forge
libllvm15                 15.0.7               h5cf9203_3    conda-forge
libnghttp2                1.52.0               h61bc06f_0    conda-forge
libnsl                    2.0.0                h7f98852_0    conda-forge
libogg                    1.3.4                h7f98852_1    conda-forge
libopenblas               0.3.24          pthreads_h413a1c8_0    conda-forge
libopus                   1.3.1                h7f98852_1    conda-forge
libpng                    1.6.39               h753d276_0    conda-forge
libpq                     15.4                 hfc447b1_0    conda-forge
libsndfile                1.2.2                hbc2eb40_0    conda-forge
libsqlite                 3.43.0               h2797004_0    conda-forge
libssh2                   1.11.0               h0841786_0    conda-forge
libstdcxx-ng              13.2.0               h7e041cc_1    conda-forge
libsystemd0               254                  h3516f8a_0    conda-forge
libtiff                   4.6.0                h29866fb_1    conda-forge
libuuid                   2.38.1               h0b41bf4_0    conda-forge
libvorbis                 1.3.7                h9c3ff4c_0    conda-forge
libwebp-base              1.3.2                hd590300_0    conda-forge
libxcb                    1.15                 h0b41bf4_0    conda-forge
libxkbcommon              1.5.0                h5d7e998_3    conda-forge
libxml2                   2.11.5               h232c23b_1    conda-forge
libzlib                   1.2.13               hd590300_5    conda-forge
lz4-c                     1.9.4                hcb278e6_0    conda-forge
matplotlib                3.8.0           py311h38be061_0    conda-forge
matplotlib-base           3.8.0           py311h54ef318_0    conda-forge
mpg123                    1.31.3               hcb278e6_0    conda-forge
munkres                   1.1.4              pyh9f0ad1d_0    conda-forge
mysql-common              8.0.33               hf1915f5_4    conda-forge
mysql-libs                8.0.33               hca2cd23_4    conda-forge
ncurses                   6.4                  hcb278e6_0    conda-forge
nspr                      4.35                 h27087fc_0    conda-forge
nss                       3.92                 h1d7d5a4_0    conda-forge
numpy                     1.26.0          py311h64a7726_0    conda-forge
openjpeg                  2.5.0                h488ebb8_3    conda-forge
openssl                   3.1.2                hd590300_0    conda-forge
packaging                 23.1               pyhd8ed1ab_0    conda-forge
pcre2                     10.40                hc3806b6_0    conda-forge
pillow                    10.0.1          py311h8aef010_0    conda-forge
pip                       23.2.1             pyhd8ed1ab_0    conda-forge
pixman                    0.40.0               h36c2ea0_0    conda-forge
ply                       3.11                       py_1    conda-forge
proj                      8.2.1                ha227179_0  
pthread-stubs             0.4               h36c2ea0_1001    conda-forge
pulseaudio-client         16.1                 hb77b528_5    conda-forge
pyparsing                 3.1.1              pyhd8ed1ab_0    conda-forge
pyproj                    3.4.1           py311h93e2b2c_0  
pyqt                      5.15.9          py311hf0fb5b6_4    conda-forge
pyqt5-sip                 12.12.2         py311hb755f60_4    conda-forge
pyshp                     2.3.1              pyhd8ed1ab_0    conda-forge
python                    3.11.5          hab00c5b_0_cpython    conda-forge
python-dateutil           2.8.2              pyhd8ed1ab_0    conda-forge
python_abi                3.11                    3_cp311    conda-forge
qt-main                   5.15.8              hc47bfe8_16    conda-forge
readline                  8.2                  h8228510_1    conda-forge
setuptools                68.2.2             pyhd8ed1ab_0    conda-forge
shapely                   2.0.1           py311he06c224_2    conda-forge
sip                       6.7.11          py311hb755f60_0    conda-forge
six                       1.16.0             pyh6c4a22f_0    conda-forge
sqlite                    3.43.0               h2c6b66d_0    conda-forge
tk                        8.6.12               h27826a3_0    conda-forge
toml                      0.10.2             pyhd8ed1ab_0    conda-forge
tomli                     2.0.1              pyhd8ed1ab_0    conda-forge
tornado                   6.3.3           py311h459d7ec_0    conda-forge
tzdata                    2023c                h71feb2d_0    conda-forge
wheel                     0.41.2             pyhd8ed1ab_0    conda-forge
xcb-util                  0.4.0                hd590300_1    conda-forge
xcb-util-image            0.4.0                h8ee46fc_1    conda-forge
xcb-util-keysyms          0.4.0                h8ee46fc_1    conda-forge
xcb-util-renderutil       0.3.9                hd590300_1    conda-forge
xcb-util-wm               0.4.1                h8ee46fc_1    conda-forge
xkeyboard-config          2.39                 hd590300_0    conda-forge
xorg-kbproto              1.0.7             h7f98852_1002    conda-forge
xorg-libice               1.1.1                hd590300_0    conda-forge
xorg-libsm                1.2.4                h7391055_0    conda-forge
xorg-libx11               1.8.6                h8ee46fc_0    conda-forge
xorg-libxau               1.0.11               hd590300_0    conda-forge
xorg-libxdmcp             1.1.3                h7f98852_0    conda-forge
xorg-libxext              1.3.4                h0b41bf4_2    conda-forge
xorg-libxrender           0.9.11               hd590300_0    conda-forge
xorg-renderproto          0.11.1            h7f98852_1002    conda-forge
xorg-xextproto            7.3.0             h0b41bf4_1003    conda-forge
xorg-xf86vidmodeproto     2.3.1             h7f98852_1002    conda-forge
xorg-xproto               7.0.31            h7f98852_1007    conda-forge
xz                        5.2.6                h166bdaf_0    conda-forge
zlib                      1.2.13               hd590300_5    conda-forge
zstd                      1.5.5                hfc55251_0    conda-forge

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions