1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
.. _understanding_transform:
Understanding the ``transform`` and ``projection`` keywords
===========================================================
It can be easy to get confused about what the ``projection`` and ``transform``
keyword arguments actually mean. Here we'll use some simple examples to
illustrate the effect of each.
The core concept is that the projection of your axes is independent of the
coordinate system your data is defined in. The ``projection`` argument is used
when creating plots and determines the projection of the resulting plot (i.e.
what the plot looks like). The ``transform`` argument to plotting functions
tells Cartopy what coordinate system your data are defined in.
First we'll create some dummy data defined on a regular latitude/longitude
grid:
.. plot::
:include-source:
:context:
:nofigs:
import numpy as np
lon = np.linspace(-80, 80, 25)
lat = np.linspace(30, 70, 25)
lon2d, lat2d = np.meshgrid(lon, lat)
data = np.cos(np.deg2rad(lat2d) * 4) + np.sin(np.deg2rad(lon2d) * 4)
Let's try making a plot in the :class:`~cartopy.crs.PlateCarree` projection
without specifying the ``transform`` argument. Since the data happen to be defined
in the same coordinate system as we are plotting in, this actually works
correctly:
.. plot::
:include-source:
:context:
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
# The projection keyword determines how the plot will look
plt.figure(figsize=(6, 3))
ax = plt.axes(projection=ccrs.PlateCarree())
ax.set_global()
ax.coastlines()
ax.contourf(lon, lat, data) # didn't use transform, but looks ok...
plt.show()
Now let's add in the ``transform`` keyword when we plot:
.. plot::
:include-source:
:context: close-figs
# The data are defined in lat/lon coordinate system, so PlateCarree()
# is the appropriate choice:
data_crs = ccrs.PlateCarree()
# The projection keyword determines how the plot will look
plt.figure(figsize=(6, 3))
ax = plt.axes(projection=ccrs.PlateCarree())
ax.set_global()
ax.coastlines()
ax.contourf(lon, lat, data, transform=data_crs)
plt.show()
See that the plot doesn't change? This is because the default assumption when
the ``transform`` argument is not supplied is that the coordinate system matches
the projection, which has been the case so far.
Now we'll try this again but using a different projection for our plot. We'll
plot onto a rotated pole projection, and we'll omit the ``transform`` argument to
see what happens:
.. plot::
:include-source:
:context: close-figs
# Now we plot a rotated pole projection
projection = ccrs.RotatedPole(pole_longitude=-177.5, pole_latitude=37.5)
plt.figure(figsize=(6, 3))
ax = plt.axes(projection=projection)
ax.set_global()
ax.coastlines()
ax.contourf(lon, lat, data) # didn't use transform, uh oh!
plt.show()
The resulting plot is incorrect! We didn't tell Cartopy what coordinate system
our data are defined in, so it assumed it was the same as the projection we are
plotting on, and the data are plotted in the wrong place.
We can fix this by supplying the ``transform`` argument, which remains the same as
before since the data's coordinate system hasn't changed:
.. plot::
:include-source:
:context: close-figs
# A rotated pole projection again...
projection = ccrs.RotatedPole(pole_longitude=-177.5, pole_latitude=37.5)
plt.figure(figsize=(6, 3))
ax = plt.axes(projection=projection)
ax.set_global()
ax.coastlines()
# ...but now using the transform argument
ax.contourf(lon, lat, data, transform=data_crs)
plt.show()
The safest thing to do is always provide the ``transform`` keyword regardless of
the projection you are using, and avoid letting Cartopy make assumptions about
your data's coordinate system. Doing so allows you to choose any map projection
for your plot and allow Cartopy to plot your data where it should be:
.. plot::
:include-source:
:context: close-figs
# We can choose any projection we like...
projection = ccrs.InterruptedGoodeHomolosine()
plt.figure(figsize=(6, 7))
ax1 = plt.subplot(211, projection=projection)
ax1.set_global()
ax1.coastlines()
ax2 = plt.subplot(212, projection=ccrs.NorthPolarStereo())
ax2.set_extent([-180, 180, 20, 90], crs=ccrs.PlateCarree())
ax2.coastlines()
# ...as long as we provide the correct transform, the plot will be correct
ax1.contourf(lon, lat, data, transform=data_crs)
ax2.contourf(lon, lat, data, transform=data_crs)
plt.show()
|