cartopy
cartopy copied to clipboard
requesting a re-draw "on limits change" causes infinite loop
Description
I've been working on EOmaps (an interactive layer on top of cartopy I'm developing) and I've noticed that requesting a re-draw of the Agg buffer if the axis-limits change causes an infinite loop for cartopy axes!
Somehow the re-draw triggers a strange cascade of limits changes... (e.g. for PlateCarree the limits switch between: (-198.0, 198.0) ⬌ (-180.0, 180.0) )
This does NOT happen with ordinary matplotlib axes!
Code to reproduce
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
f = plt.figure()
ax = f.add_subplot(projection=ccrs.PlateCarree())
def xlims_change(ax, *args, **kwargs):
print("xlims changed", ax.get_xlim())
f.canvas.draw_idle()
ax.callbacks.connect("xlim_changed", xlims_change)
>>> ...
>>> ylims changed (-198.0, 198.0)
>>> ylims changed (-180.0, 180.0)
>>> ylims changed (-198.0, 198.0)
>>> ylims changed (-180.0, 180.0)
>>> ylims changed (-198.0, 198.0)
>>> ...
Note that this works just fine with ordinary axes!
f = plt.figure()
ax = f.add_subplot()
def xlims_change(*args, **kwargs):
print("xlims changed", ax.get_xlim())
f.canvas.draw_idle()
ax.callbacks.connect("xlim_changed", xlims_change)
Full environment definition
Operating system
Windows
Cartopy version
0.20.2
I can't reproduce this. I get a couple of limit changes, but definitely not an infinite loop. What MPL backend are you using? It could have something to do with the draw_idle()
request that you added in which is implemented differently for various backends. (macosx and tkagg both work as expected for me)
This is the only place that Cartopy hooks into that callback and sets things to stale, but note that it doesn't explicitly request a redraw. https://github.com/SciTools/cartopy/blob/22cdafca511744143c5b673598a1889f169c1e3d/lib/cartopy/mpl/geoaxes.py#L2255-L2264
hey, thanks for the quick response!
I'm on Windows using Qt5Agg
at the moment...
I've checked and you are right... the tkagg
backend seems to work just fine...
There are still 2 limit-changes but no infinite loops... very strange... I guess this is on the matplotlib-backend side then...
Hm... Definitely with the qt5 backend, I can reproduce it with that as well. Are you able to just set the figure to stale rather than requesting a redraw?
f.stale = True
Hey, thanks for the suggestion!
It took me a while but I feel I understand some things a bit better now 😅
Using f.stale = True
seemed to help at first, but then I realized that fetching backgrounds etc. gets a bit more messy
with jupyter-notebook backends such as nbagg
or ipympl
...
Anyways, your hint led me on a new track on how to implement what I want and for now things are working fine... (In the end I've decided to keep track myself if an immediate re-draw is required or not)
Considering the issue in general, I've investigated a bit further and found that the origin of the problem is actually here:
https://github.com/SciTools/cartopy/blob/22cdafca511744143c5b673598a1889f169c1e3d/lib/cartopy/mpl/geoaxes.py#L475-L491
... or more precisely the first 2 lines, e.g.:
if self.get_autoscale_on() and self.ignore_existing_data_limits:
self.autoscale_view()
I'm not completely sure why this results in a problem but it seems to be the cause of the infinite loop...
(commenting the above lines or explicitly using ax.autoscale(False)
solves the problem )