How do I transform matplotlib ConnectionPatch, i.e for Cartopy projection

Viewed 623

Problem: I want to use matplotlib.patches.ConnectionPatch to connect two axes, one of them a Cartopy map projection.

Expected: The two lat/lon coordinates in each axes should be connected by a line.

Result: The line goes to 0,0 coordinate in the map projection, rather than the defined lat/lon.

It does work as expected if the projection is an unmodified cartopy.crs.PlateCarree(), but any other such as Robinson(), or with alternate central_longitude does not.

Code:

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

plt.close('all')
fig = plt.figure()
ax = plt.subplot(projection=ccrs.Robinson())

lon,lat = 145,-30

ax.stock_img()
ax.plot(lon,lat, marker='x', color='r', transform=ccrs.PlateCarree())

ax2 = fig.add_axes([0.1,0.06,0.8,0.1])
ax2.plot(lon,lat,marker='x', color='r')

# line between axes
con = patches.ConnectionPatch(
    xyA=(lon,lat), 
    xyB=(lon,lat), 
    coordsA='data', coordsB='data', axesA=ax, axesB=ax2, color='r')
ax2.add_artist(con)

plt.show()

2 Answers

You use wrong values in xyA=(lon,lat). It doesn't match the declaration coordsA='data'. To get proper values, do these steps:

use_proj = ccrs.Robinson()
xyA = use_proj.transform_point(lon, lat, ccrs.PlateCarree())
# You get xyA=(13151177.842976002, -3208556.0608129553)

And use this to plot the connection patch:

con = patches.ConnectionPatch(
    xyA=xyA, 
    xyB=(lon,lat), 
    coordsA='data', coordsB='data', axesA=ax, axesB=ax2, color='r')

The plot will be:

enter image description here

Though the previous answer was very helpful, it did not work in slightly different different situations for me (using different projections and axes). I did not manage to find a MWE that would break it, though, so I don't really not what the problem is, but in case it also breaks for someone else, here is a version that worked in all cases for me.

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

fig = plt.figure()

projA = ccrs.Robinson()
projB = ccrs.Mollweide()

pc = ccrs.PlateCarree()

ax = plt.subplot(projection=projA)

lon,lat = 145,-30

ax.stock_img()
ax.plot(lon,lat, marker='x', color='r', transform=pc)

ax2 = fig.add_axes([0.1,0.06,0.8,0.1], projection=projB)
ax2.stock_img()
ax2.plot(lon,lat, marker='x', color='r', transform=pc)

xyA = projA.transform_point(lon, lat, pc)
xyB = projB.transform_point(lon, lat, pc)

# line between axes
con = patches.ConnectionPatch(
    xyA=xyA, xyB=xyB, coordsA=ax.transData, coordsB=ax2.transData, color='r')

fig.add_artist(con)

plt.show()

inter-plot connexion for two geo plots with different projections

I know that this does not 100% relate to the OP, but it does answer the title's question so it is more intended as a potential help for others who would run into the same (uknown) issue I encountered.

Related