Skip to content

Cartopy: Delete Gridliner Object (not hide, actually remove) for making multiple plots #1658

@sam-gillette

Description

@sam-gillette

Description

** This was answered on Stack Overflow already **
I am trying to plot source and receiver points on a map in cartopy, where I zoom into the map based on the locations of the source and receiver. For each combination of source and receiver, I have a new map, with a new extent. I would like to find a way where I can download the map image once, and then just change the extent each time so I don't have to load in the map image every time (I have to make thousands of these). All of the events take place in one country, so I am hoping to just download the map of the whole country and then just change the extent for each loop through.

I have actually partially solved this problem, but I ran into an issue with the grid. Initially, I first set the extent to the whole country, loaded in the image, and then saved it. Then I could reset the extent for each source receiver pair, plot the two points, and then save the image. Afterwards, I just needed to erase each of the two points, and then I could set the extent another time.

However, once I added in the grid with latitude and longitude labels, I ran into an issue. I can't erase the grid and labels after each iteration, so they end up just layering on top of eachother, and the labels start to move all over the figure. The only way I can get rid of the grid is by clearing the axis, but that erases the map image.

My question: is there a way to just erase a gridliner object (not hide the labels and grid but actually delete)?

I have uploaded two of the images of the plots here, and you can see the problem in the second one. The first image is the first plot in the loop, and each iteration adds another gridliner on top of the previous one. The second image is the last image in the loop. I can't figure out how to erase the grid, and clearing the axis deletes the map image.

image
image

Code to reproduce

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from cartopy.io.img_tiles import Stamen

whole_extent = [18,42,8,36]
tiler = Stamen('terrain-background')

fig = plt.figure(figsize=(13.75,10))
ax1 = plt.axes(projection=ccrs.PlateCarree())
ax1.set_extent(whole_extent, crs=ccrs.PlateCarree())
ax1.add_image(tiler,6)
#Need to save initial figure to lock in initial picture, otherwise it locks in the extent from the first loop and any map that goes outside the extent of the first loop is white space
plt.savefig('plots/001_WholeFigure.png')


eventlist=[['A',22,15,30,30],['B',30,15,30,18],['C',38,24,21,15],['D',25,12,28,16],['E',38,32,21,11]]

for i in eventlist:
    eventname = i[0]
    slon = i[1] #source lon
    slat = i[2] #source lat
    lon = i[3] #receiver lon
    lat = i[4] #receiver lat

    print(f'{eventname} in progress')
    
    # Sets the zoomed in extent based on source/receiver locations
    if lon > slon:
        lonmin = slon - 2
        lonmax = lon + 2
    else:
        lonmin = lon - 2
        lonmax = slon + 2

    if lat > slat:
        latmin = slat -2
        latmax = lat + 2
    else:
        latmin = lat - 2
        latmax = slat + 2

    zoomextent = [lonmin,lonmax,latmin,latmax]


    # MAP
    ax1.set_extent(zoomextent, crs=ccrs.PlateCarree())
    receiverloc = ax1.plot(lon,lat,'r*',label='Receiver')
    sourceloc = ax1.plot(slon,slat,'k^',label='Source')
    text = ax1.text(slon+0.1,slat+0.1,eventname)
    legend = ax1.legend(loc="upper right")
    
    gl = ax1.gridlines(crs=ccrs.PlateCarree(),draw_labels=True,
        linewidth=2,color='gray',alpha=0.5,linestyle='--')
    gl.bottom_labels = gl.right_labels = False

    plt.savefig(f'plots/{eventname}.png')

    # Delete the two markers and the text so they don't show up on next loop
    receiverloc.pop(0).remove()
    sourceloc.pop(0).remove()
    text.remove()

Adding this to the end of the code fixed the problem

# Remove all artists created by the gridliner
for artist in (gl.xline_artists + gl.yline_artists +
               gl.bottom_label_artists + gl.top_label_artists +
               gl.left_label_artists + gl.right_label_artists):
    artist.remove()

# Remove the created gridliner from the list
ax1._gridliners.remove(gl)

# Try to re-connect to the draw event, which since it's already
# connected will return the existing connection id
cid = gl.axes.figure.canvas.mpl_connect('draw_event', gl._draw_event)

# Disconnect using that cid
gl.axes.figure.canvas.mpl_disconnect(cid)

Operating system

Linux Mint 18.3 Ubuntu

Cartopy version

cartopy 0.18.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions