python-3.xcartopyextent

get_extent not returning updated extent after set_aspect is set to equal in Cartopy


When setting set_aspect('equal', adjustable='datalim') the actual extent of my plot gets adjusted and is slightly wider than the extent I initially set - which is expected.
When I'm trying to get these adjusted boundaries, however, get_extent() only returns what I input with set_extent().

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cpf
import shapely.geometry as sgeom

EXT = (9000000, 13500000, -450000, 3500000)

def to_bounds(extent):
    xmin, a, b, ymax = extent
    return xmin, b, a, ymax

platecarree = ccrs.PlateCarree(globe=ccrs.Globe(datum='WGS84', ellipse='WGS84'))

fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(1, 1, 1, projection=platecarree)

ax.set_extent(EXT, crs=platecarree) # setting extent
ax.set_aspect('equal', adjustable='datalim', anchor='C')
ext2 = ax.get_extent() # trying to get the updated extent

ax.add_feature(cpf.LAND, facecolor='#bababa')
ax.add_feature(cpf.BORDERS, edgecolor='white')
ax.add_geometries([sgeom.box(*to_bounds(EXT))], crs=platecarree, facecolor='none', edgecolor='yellow', linewidth=3)     # initial extent
ax.add_geometries([sgeom.box(*to_bounds(ext2))], crs=platecarree, facecolor='none', edgecolor='indianred', linewidth=1) # updated extent

enter image description here

Obvioulsy, EXT and ext2 are the same.
The weirdest thing is, after I run the above code, get_extent() will actually give me the updated values.

ext2 # (9000000.0, 13499999.999999998, -449999.99999999994, 3500000.0)

ax.get_extent() # (8546909.492273731, 13953090.507726269, -449999.99999999994, 3500000.0)

What's wrong ?


Solution

  • Nothing wrong with what you found. When you set extent, you declare the values associated with the extent you want to plot, and they are not applied yet until the map is processed and rendered. Therefore, when you ask for the current extent (with ax.get_extent()) you dont get the values you just set. To get what you expect, you must run plt.draw(). Here is the modified code and the output that describe the process:

    import matplotlib.pyplot as plt
    import cartopy.crs as ccrs
    import cartopy.feature as cpf
    import shapely.geometry as sgeom
    
    EXT = (9000000, 13500000, -450000, 3500000)
    
    def to_bounds(extent):
        xmin, a, b, ymax = extent
        return xmin, b, a, ymax
    
    platecarree = ccrs.PlateCarree(globe=ccrs.Globe(datum='WGS84', ellipse='WGS84'))
    
    fig = plt.figure(figsize=(8, 6))
    ax = fig.add_subplot(1, 1, 1, projection=platecarree)
    
    ax.set_extent(EXT, crs=platecarree) # setting extent
    print("1. ax.set_extent(EXT..):", ax.get_extent())  # after EXT is used
    
    ax.set_aspect('equal', adjustable='datalim', anchor='C')  # the extent changes at this step
    
    ext2 = ax.get_extent()    # trying to get the updated extent; fails here!
    print("2. ext2:", ext2 )  # print check; extent is not updated yet!
    
    plt.draw()  # this updates the extent
    print("3. ax.get_extent():", ax.get_extent())  # expected to have other values; OK now
    
    ax.add_feature(cpf.LAND, facecolor='#bababa')
    ax.add_feature(cpf.BORDERS, edgecolor='white')
    ax.add_geometries([sgeom.box(*to_bounds(EXT))], crs=platecarree, facecolor='none', edgecolor='yellow', linewidth=4)     # initial extent
    ax.add_geometries([sgeom.box(*to_bounds(ax.get_extent()))], crs=platecarree, facecolor='none', edgecolor='indianred', linewidth=5) # updated extent
    
    plt.show()
    

    Output:

    enter image description here