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

Gridliner tick labels are attached to background patch, not to the boundary spines #1541

Closed
greglucas opened this issue Apr 29, 2020 · 13 comments
Milestone

Comments

@greglucas
Copy link
Contributor

greglucas commented Apr 29, 2020

Description

When panning on a map, the tick labels are attached to the background and move around with the pan. I would expect them to be attached to the boundary and be right on the axes spines.
Here is an example where I panned over a little bit.
Figure_1

I came across this looking at the recent Gridliner example in #1537

@stefraynaud, I'm going to ping you here since you've dealt a lot with the gridliner ticks.

Code to reproduce

import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker

lambert_crs = ccrs.LambertConformal(central_longitude=105) 

ax0 = plt.axes(projection=lambert_crs)
ax0.set_extent([75, 130, 18, 54], crs=ccrs.PlateCarree())
ax0.add_feature(cfeature.LAND)
ax0.add_feature(cfeature.BORDERS)
gl = ax0.gridlines(draw_labels=True, dms=True, x_inline=False, y_inline=False)
gl.xlocator = mticker.FixedLocator([70, 80, 90, 100, 110, 120, 130])
gl.ylocator = mticker.FixedLocator([10, 20, 30, 40, 50])
gl.rotate_labels = False
gl.top_labels = gl.right_labels = False
ax0.coastlines(resolution='10m')
plt.show()
Full environment definition Reproduced on both `macosx` and `qt5agg` backends.

matplotlib==3.2.0
cartopy==0.18.0b3.dev25+

Cartopy version

master

@stefraynaud
Copy link
Contributor

Sorry, I was not able to reproduce the figure.
The algo uses self.axes.patch.get_path(), which seems to be synced with self.axes.spines['geo'].get_path().
It does not use other self.axes.spines entries since they do not always coincide with the map boundary. However, as slightly suggested in #1530, we should probably take them into account to better determine the real side of a label.

@greglucas
Copy link
Contributor Author

I'm able to reproduce this on both macosx and qt5agg backends. What environment are you using? It could be something to do with different versions of MPL or a backend...

The versions of mpl and Cartopy I'm using are: matplotlib==3.2.0 and cartopy==0.18.0b3.dev25+.

@stefraynaud
Copy link
Contributor

I've been able to reproduce it by playing with the zoom tool in intercative mode.
I already successfully tried a solution:

  • connect the draw event to the _draw_gridliner method
  • remove all lines and labels already plotted at the beginning of _draw_gridliner
  • then do the normal stuff

This means that lines and labels are recomputed and redrawn everytime, but it works well.
I can update the PR #1538.

@greglucas
Copy link
Contributor Author

I'd say those are two different features, so a new different PR may be better?

What you say makes sense to me. I only wonder if you need to redraw every single time, or if you can just update the transforms/locations of the already drawn items so that it can be rendered faster by keeping the same artists that are already present?

@stefraynaud
Copy link
Contributor

I agree with about creating another PR, once PR #1537 (not #1538) is merged.
So this is more for 0.19.

About refreshing, It seems to be fast enough to be acceptable, since only the lines and labels are redrawn. The point of doing it this way is that when you zoom in for instance, you may quickly no longer have grid line and label. This makes the system really nice!

@stefraynaud
Copy link
Contributor

Here is a first overview.
gridliner

@stefraynaud
Copy link
Contributor

I'm ready to make a PR, once #1537 is ok since the former starts from the latter.

@QuLogic
Copy link
Member

QuLogic commented Sep 10, 2021

Closed by #1537

@QuLogic QuLogic closed this as completed Sep 10, 2021
@PAGWatson
Copy link

PAGWatson commented Dec 14, 2021

Hello, I'm using cartopy 0.20.1 and matplotlib 3.5.0 and I'm getting this issue with the tick labels moving with the background (which I can reproduce using the code in the first post above) - was this actually supposed to have been fixed, and if so is any modification of the code necessary? Or is there code that can be used in the meantime to make this work?

(bringing to attention of @stefraynaud since you seem to be the person who has worked on fixing this)

@stefraynaud
Copy link
Contributor

stefraynaud commented Dec 14, 2021

Hi @PAGWatson

Try to pass the auto_update keyword to gridlines.

@PAGWatson
Copy link

@stefraynaud - thanks, yes that seems to work. This feature seems quite hidden in the docs, I hadn't found it after quite a bit of searching - it would perhaps be good if it were included in a plotting example somewhere.

@stefraynaud
Copy link
Contributor

You are right. We should add content to the documentation on the gridliner capabilities.
Maybe you can make a PR!

@PAGWatson
Copy link

@stefraynaud An issue I came across with this is that if I run code in a jupyter notebook, set auto_update=True and set gridlines to be added to the plot (e.g. gl.bottom_labels=True), then if I've not run "%matplotlib notebook" beforehand I get an error, the last part of which is copied below. I found that I could prevent it by only setting the auto_update option if matplotlib.get_backend()!='module://matplotlib_inline.backend_inline' . I'm not sure if there are other situations where it could fail and if there's a better check. It took a while to find a solution for this, so it would be helpful if the code checked that this error wouldn't occur and gave a warning or something. I got this with both matplotlib 3.5.0 and 3.5.1 with cartopy 0.20.1.

~/.conda/envs/xxx/lib/python3.9/site-packages/matplotlib/text.py in get_window_extent(self, renderer, dpi)
    894             return Bbox.unit()
    895         if dpi is None:
--> 896             dpi = self.figure.dpi
    897         if self.get_text() == '':
    898             with cbook._setattr_cm(self.figure, dpi=dpi):

AttributeError: 'NoneType' object has no attribute 'dpi'

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

No branches or pull requests

4 participants