Skip to content
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

Missing y-axis gridline labels when rotated to 90 degrees #2394

Open
nmstreethran opened this issue May 24, 2024 · 2 comments
Open

Missing y-axis gridline labels when rotated to 90 degrees #2394

nmstreethran opened this issue May 24, 2024 · 2 comments

Comments

@nmstreethran
Copy link

nmstreethran commented May 24, 2024

Description

Some y-axis gridline labels are missing when rotated to 90 degrees. This doesn't seem to happen when the rotation is about 89.9 degrees or less. I only noticed this happening after upgrading Cartopy to 0.23.0.

Code to reproduce

import cartopy.crs as ccrs
import matplotlib.pyplot as plt


def plot_example_map(ylabel_rotation):
    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
    ax.set_extent([80, 170, -45, 30], crs=ccrs.PlateCarree())

    ax.stock_img()

    ax.gridlines(
        draw_labels={"bottom": "x", "left": "y"},
        ylabel_style={"rotation": ylabel_rotation},
    )

    ax.coastlines()

    plt.tight_layout()
    plt.show()

Results

# rotation = 90 degrees
plot_example_map(ylabel_rotation=90)

rotation = 90 degrees

# rotation = 89.9 degrees
plot_example_map(ylabel_rotation=89.9)

image

Full environment definition

Operating system

Linux (Pop!_OS 22.04 LTS x86_64)

Cartopy version

0.23.0

pip list

Package                   Version
------------------------- --------------
anyio                     4.3.0
argon2-cffi               23.1.0
argon2-cffi-bindings      21.2.0
arrow                     1.3.0
asttokens                 2.4.1
async-lru                 2.0.4
attrs                     23.2.0
Babel                     2.15.0
beautifulsoup4            4.12.3
bleach                    6.1.0
Cartopy                   0.23.0
certifi                   2024.2.2
cffi                      1.16.0
charset-normalizer        3.3.2
comm                      0.2.2
contourpy                 1.2.1
cycler                    0.12.1
debugpy                   1.8.1
decorator                 5.1.1
defusedxml                0.7.1
executing                 2.0.1
fastjsonschema            2.19.1
fonttools                 4.52.1
fqdn                      1.5.1
h11                       0.14.0
httpcore                  1.0.5
httpx                     0.27.0
idna                      3.7
ipykernel                 6.29.4
ipython                   8.24.0
isoduration               20.11.0
jedi                      0.19.1
Jinja2                    3.1.4
json5                     0.9.25
jsonpointer               2.4
jsonschema                4.22.0
jsonschema-specifications 2023.12.1
jupyter_client            8.6.2
jupyter_core              5.7.2
jupyter-events            0.10.0
jupyter-lsp               2.2.5
jupyter_server            2.14.0
jupyter_server_terminals  0.5.3
jupyterlab                4.2.1
jupyterlab_pygments       0.3.0
jupyterlab_server         2.27.2
kiwisolver                1.4.5
MarkupSafe                2.1.5
matplotlib                3.9.0
matplotlib-inline         0.1.7
mistune                   3.0.2
nbclient                  0.10.0
nbconvert                 7.16.4
nbformat                  5.10.4
nest-asyncio              1.6.0
notebook_shim             0.2.4
numpy                     1.26.4
overrides                 7.7.0
packaging                 24.0
pandocfilters             1.5.1
parso                     0.8.4
pexpect                   4.9.0
pillow                    10.3.0
pip                       24.0
platformdirs              4.2.2
prometheus_client         0.20.0
prompt-toolkit            3.0.43
psutil                    5.9.8
ptyprocess                0.7.0
pure-eval                 0.2.2
pycparser                 2.22
Pygments                  2.18.0
pyparsing                 3.1.2
pyproj                    3.6.1
pyshp                     2.3.1
python-dateutil           2.9.0.post0
python-json-logger        2.0.7
PyYAML                    6.0.1
pyzmq                     26.0.3
referencing               0.35.1
requests                  2.32.2
rfc3339-validator         0.1.4
rfc3986-validator         0.1.1
rpds-py                   0.18.1
Send2Trash                1.8.3
setuptools                70.0.0
shapely                   2.0.4
six                       1.16.0
sniffio                   1.3.1
soupsieve                 2.5
stack-data                0.6.3
terminado                 0.18.1
tinycss2                  1.3.0
tornado                   6.4
traitlets                 5.14.3
types-python-dateutil     2.9.0.20240316
typing_extensions         4.12.0
uri-template              1.3.0
urllib3                   2.2.1
wcwidth                   0.2.13
webcolors                 1.13
webencodings              0.5.1
websocket-client          1.8.0
wheel                     0.43.0

Environment

python3.11 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip setuptools wheel
python -m pip install cartopy jupyterlab
@rcomer
Copy link
Member

rcomer commented May 25, 2024

Thanks for the clear report @nmstreethran. I confirm that I can reproduce this in a script if I replace the plt.show() with plt.savefig('test.png', bbox_inches='tight'). In notebooks the bbox_inches='tight' is automatic. If I remove that option in the script, or disable it in the notebook, then all the labels show. So we seem to somehow have a bad interaction with bbox_inches='tight'.

I think the relevant difference between Cartopy 0.22 and 0.23 is that we changed the default of the auto_update parameter to True in #2330. So the logic that decides where the labels go is now running twice: once when you call tight_layout and again when you call show. If you manually set auto_update=False in your call to gridlines then you get the previous behaviour back.

@rcomer
Copy link
Member

rcomer commented May 25, 2024

I added some prints to try to debug this

diff --git a/lib/cartopy/mpl/gridliner.py b/lib/cartopy/mpl/gridliner.py
index c750a754..6e1e1acb 100644
--- a/lib/cartopy/mpl/gridliner.py
+++ b/lib/cartopy/mpl/gridliner.py
@@ -1277,4 +1277,6 @@ class Label:
         overlapping = self.path.intersects_path(label.path)
         if overlapping:
             self.set_visible(False)
+            print(self.artist, 'overlaps', label.artist)
+            print('overlapping paths:', self.path, label.path, '===', sep='\n')
         return overlapping

and got

Text(80.00000009, -30.000000000000007, '30°S') overlaps Text(80.00000009, -40.00000000000001, '40°S')
overlapping paths:
Path(array([[ 24.       , 100.1305552],
       [ 24.       , 133.3805552],
       [ 10.       , 133.3805552],
       [ 10.       , 100.1305552],
       [ 24.       , 100.1305552]]), array([ 1,  2,  2,  2, 79], dtype=uint8))
Path(array([[24.        , 42.92314774],
       [24.        , 76.17314774],
       [10.        , 76.17314774],
       [10.        , 42.92314774],
       [24.        , 42.92314774]]), array([ 1,  2,  2,  2, 79], dtype=uint8))
===
Text(80.00000009, -10.000000000000007, '10°S') overlaps Text(80.00000009, -20.000000000000007, '20°S')
overlapping paths:
Path(array([[ 24.        , 214.48287011],
       [ 24.        , 247.85787011],
       [ 10.        , 247.85787011],
       [ 10.        , 214.48287011],
       [ 24.        , 214.48287011]]), array([ 1,  2,  2,  2, 79], dtype=uint8))
Path(array([[ 24.        , 157.33796266],
       [ 24.        , 190.58796266],
       [ 10.        , 190.58796266],
       [ 10.        , 157.33796266],
       [ 24.        , 157.33796266]]), array([ 1,  2,  2,  2, 79], dtype=uint8))
===
Text(80.00000009, -7.105427357601002e-15, '0°') overlaps Text(80.00000009, -20.000000000000007, '20°S')
overlapping paths:
Path(array([[ 24.        , 280.50277757],
       [ 24.        , 296.25277757],
       [ 10.        , 296.25277757],
       [ 10.        , 280.50277757],
       [ 24.        , 280.50277757]]), array([ 1,  2,  2,  2, 79], dtype=uint8))
Path(array([[ 24.        , 157.33796266],
       [ 24.        , 190.58796266],
       [ 10.        , 190.58796266],
       [ 10.        , 157.33796266],
       [ 24.        , 157.33796266]]), array([ 1,  2,  2,  2, 79], dtype=uint8))
===

This makes no sense to me. It's as if the Path.intersects_path method is seeing different vertices to what gets printed. 😕

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants