ztl
ztl

Reputation: 2592

Adapting coordinates in cartopy depending on the projection of a plot

In the following example, I am losing my point (i.e., I don't understand the change in coordinates) if I am using the ccrs.Mercator() projection instead of the ccrs.PlateCarree():

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

mypt = (6, 56)

ax0 = plt.subplot(221, projection=ccrs.PlateCarree()) # OK
ax1 = plt.subplot(222, projection=ccrs.Mercator())    # NOT OK
ax2 = plt.subplot(224, projection=ccrs.Mercator())    # NOT OK

def plotpt(ax, extent=(-15,15,46,62)):
    ax.plot(mypt[0], mypt[1], 'r*', ms=20)
    ax.set_extent(extent)
    ax.coastlines(resolution='50m')
    ax.gridlines(draw_labels=True)

plotpt(ax0)
plotpt(ax1)
plotpt(ax2, extent=(-89,89,-89,89))

plt.show()

enter image description here

It looks like the coordinates of my point go from (6,56) to (0,0) What am I missing? Why is the behaviour correct with ccrs.PlateCarree() and not with ccrs.Mercator()? Should I add any transform somewhere?


[EDIT with the solution]

My initial confusion came from the fact that projection applies to the plot, while transform applies to the data, meaning they should be set different when they do not share the same system - my first attempts with transform where wrong as in ax1 below, ax1bis is the solution.

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

mypt = (6, 56)

ax0 = plt.subplot(221, projection=ccrs.PlateCarree())
ax1 = plt.subplot(222, projection=ccrs.Mercator())
ax1bis = plt.subplot(223, projection=ccrs.Mercator())
ax2 = plt.subplot(224, projection=ccrs.Mercator())

def plotpt(ax, extent=(-15,15,46,62), **kwargs):
    ax.plot(mypt[0], mypt[1], 'r*', ms=20, **kwargs)
    ax.set_extent(extent)
    ax.coastlines(resolution='50m')
    ax.gridlines(draw_labels=True)
    ax.xaxis.set_ticks_position('bottom')
    ax.yaxis.set_ticks_position('left')

plotpt(ax0) # correct because projection and data share the same system
plotpt(ax1, transform=ccrs.Mercator()) # WRONG
plotpt(ax1bis, transform=ccrs.PlateCarree()) # Correct, projection and transform are different!
plotpt(ax2, extent=(-89,89,-89,89), transform=ccrs.Mercator()) # WRONG

plt.show()

enter image description here

Upvotes: 1

Views: 2592

Answers (1)

ajdawson
ajdawson

Reputation: 3333

Yes, you should add the transform keyword to the plot call. You should also specify the coordinate system you want to set the extents in:

def plotpt(ax, extent=(-15,15,46,62)):
    ax.plot(mypt[0], mypt[1], 'r*', ms=20, transform=ccrs.PlateCarree())
    ax.set_extent(extent, crs=ccrs.PlateCarree())
    ax.coastlines(resolution='50m')
    ax.gridlines(draw_labels=True)

A basic guide on transforms and projections is now available in the cartopy documentation http://scitools.org.uk/cartopy/docs/latest/tutorials/understanding_transform.html. To avoid surprises, you should always specify a transform when plotting data on a map.

Upvotes: 4

Related Questions