Search code examples
pythonmatplotlibcartopy

Setting axis extent on Cartopy UTM projection


I want to plot a set of UTM coordinates using Matplotlib (v3.1.3) and Cartopy (v0.17.0), and then manually set the extent of the axis. Normally I can do this with axis.set_extent((left, right, bottom, top)), but when I try to do this with UTM coordinates, I get an error message claiming that my coordinates are outside the permitted range. This also occurs when I literally copy and insert the current axis extent (using axis.get_extent()).

See the following minimal example:

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

# Some random UTM coordinates
UTM = np.array([
    [328224.965, 4407328.289],
    [328290.249, 4407612.599],
    [328674.439, 4408309.066],
    [327977.178, 4407603.320],
    [328542.037, 4408510.581]
]).T

# Split into east and north components
east, north = UTM

# Create a canvas with UTM projection
fig = plt.figure()
ax = fig.add_subplot(111, projection=ccrs.UTM(zone="11S"))

# Plot coordinates
ax.scatter(east, north)

# Get the extent of the axis
extent = ax.get_extent()
# Attempt to set the axis extent
ax.set_extent(extent)

plt.show()

This raises the following exception:

ValueError: Failed to determine the required bounds in projection coordinates. Check that the values provided are within the valid range (x_limits=[-250000.0, 1250000.0], y_limits=[-10000000.0, 25000000.0]).

Is this a bug or am I doing something wrong? Is there another way of setting the extent of the axis?


Solution

  • The line of code:

    ax.set_extent(extent)
    

    has an option crs=None, which translates to having ccrs.PlateCarree() as the default value. That means the values in degrees of longitude and latitude are expected in extent in the code.

    To get it right, you must specify the correct crs:-

    ax.set_extent(extent, crs=ccrs.UTM(zone="11S"))