Cartopy: projections with non-`PlateCarree` transformations don't work.

Created on 19 Jul 2017  路  4Comments  路  Source: SciTools/cartopy

I'm using (slightly modified) example code from the webpage (below). Using ccrs.PlateCarree() things work fine, but using ccrs.Orthographic() or ccrs.LamberConformal() do not work. Everything is plotted at the origin.

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

# proj = ccrs.PlateCarree()
proj = ccrs.LambertConformal()

ax = plt.axes(projection=proj)
ax.stock_img()

ny_lon, ny_lat = -75, 43
delhi_lon, delhi_lat = 77.23, 28.61

plt.plot([ny_lon, delhi_lon], [ny_lat, delhi_lat],
         color='0.5', linewidth=2, marker='o',
         transform=ccrs.Geodetic(),
         )

plt.plot([ny_lon, delhi_lon], [ny_lat, delhi_lat],
         color='0.5', 
         transform=proj,
         )

plt.scatter([ny_lon, delhi_lon], [ny_lat, delhi_lat],
         color='blue', marker='+', s=400,
         transform=proj,
         )

plt.scatter(ny_lon, ny_lat, s=300, color='red', alpha=0.5, transform=proj)

plt.show()

Success:
screen shot 2017-07-19 at 7 40 08 pm

Failure:
screen shot 2017-07-19 at 7 39 54 pm

matplotlib Question

Most helpful comment

Here's how I think about this: the value given as the projection keyword when setting up a plot determines what the plot will look like. The value given to the transform argument when plotting should answer the question "what coordinate system are the points I'm plotting given in?".

The transform argument is solely determined by the points you want to plot, and not related to the projection you plot them on to. It is not good practice to leave out the transform argument as this will only do the right thing when the projection matches the data. You should always specify transform, and when you have lat/lon points it will be PlateCarree (or sometimes Geodetic as in this example), and it should never depend on the projection you are plotting on to.

All 4 comments

You are providing the wrong value for the transform argument. Your locations for New York and Delhi are always provided in latitude/longitude, so you should always be using Geodetic or PlateCarree for these. You would only choose transform=LambertConformal() if the actual points you were plotting were given in coordinates on the Lambert conformal projection.

I think the correct example is:

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

# proj = ccrs.PlateCarree()
proj = ccrs.LambertConformal()

ax = plt.axes(projection=proj)
ax.stock_img()

ny_lon, ny_lat = -75, 43
delhi_lon, delhi_lat = 77.23, 28.61

plt.plot([ny_lon, delhi_lon], [ny_lat, delhi_lat],
         color='0.5', linewidth=2, marker='o',
         transform=ccrs.Geodetic(),
         )

plt.plot([ny_lon, delhi_lon], [ny_lat, delhi_lat],
         color='0.5', 
         transform=ccrs.PlateCarree(),
         )

plt.scatter([ny_lon, delhi_lon], [ny_lat, delhi_lat],
         color='blue', marker='+', s=400,
         transform=ccrs.PlateCarree(),  # Coordinates are given in lat/lon, so use PlateCarree
         )

plt.scatter(ny_lon, ny_lat, s=300, color='red', alpha=0.5, transform=proj)

plt.show()

Thanks @ajdawson, that does seem to be working! But I totally don't understand why... the data coordinates are always lon/lat, but the transformation is specifying how those data coordinates are being converted to positions on the figure. And isn't the projection argument what determines that transformation? I would think that either the transform parameter should be left blank to use the same transformation as the projection, or to always use the same transform parameter as the projection parameter.

Here's how I think about this: the value given as the projection keyword when setting up a plot determines what the plot will look like. The value given to the transform argument when plotting should answer the question "what coordinate system are the points I'm plotting given in?".

The transform argument is solely determined by the points you want to plot, and not related to the projection you plot them on to. It is not good practice to leave out the transform argument as this will only do the right thing when the projection matches the data. You should always specify transform, and when you have lat/lon points it will be PlateCarree (or sometimes Geodetic as in this example), and it should never depend on the projection you are plotting on to.

I'm wondering if there's a need for a cartopy plotting wrapper with clearer keywords like transform_from and project_into?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

leecronce picture leecronce  路  8Comments

choldgraf picture choldgraf  路  7Comments

maxnoe picture maxnoe  路  5Comments

rutgerhofste picture rutgerhofste  路  3Comments

mjarrett picture mjarrett  路  5Comments