Search code examples
pythonmatplotlibcartopy

How to find the right cartopy projection?


I need to plot some data in Germany with cartopy. The data part of my plot works fine (so I deleted it for now). Unfortunately, the shape of the country is deformed due to the projection.

I am currently using the PlateCarree projection, but changing it to Orthographic or others created the same plot.

How to improve the shape?

Link to image of output vs. wanted output

Code:

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from cartopy.io import shapereader

# get country borders
resolution = '10m'
category = 'cultural'
name = 'admin_0_countries'
shpfilename = shapereader.natural_earth(resolution, category, name)
df = geopandas.read_file(shpfilename)
poly = df.loc[df['ADMIN'] == 'Germany']['geometry'].values[0]

# plot
ax = plt.axes(projection=ccrs.PlateCarree())
ax.set_extent([5.8, 15.1, 47.25, 55.1],
              crs=ccrs.PlateCarree())
ax.add_geometries(poly,
                  crs=ccrs.PlateCarree(),
                  facecolor='gainsboro',
                  edgecolor='slategray',
                  lw=0.1,
                  alpha=.8)

# save plot
save_path = 'germany.png'
plt.savefig(save_path, dpi=250, bbox_inches='tight', pad_inches=0.)
plt.close()

Solution

  • The solution is transforming the Geopandas Dataframe using the same projection as explained here

    New output: germany.png

    New code:

        import matplotlib.pyplot as plt
        import cartopy.crs as ccrs
        import geopandas
        from cartopy.io import shapereader
    
        # get country borders
        resolution = "10m"
        category = "cultural"
        name = "admin_0_countries"
        shpfilename = shapereader.natural_earth(resolution, category, name)
        df = geopandas.read_file(shpfilename)
        df_de = df.loc[df["ADMIN"] == "Germany"]
    
    
        extent = [6., 14.8, 47.1, 55.1]
    
        # plot
        crs = ccrs.Orthographic(
            central_longitude=(0.5 * (extent[0] + extent[1])),
            central_latitude=(0.5 * (extent[2] + extent[3])),
        )
    
        crs_proj4 = crs.proj4_init
    
        df_de.crs = "EPSG:4326"
        df_ae = df_de.to_crs(crs_proj4)
    
        fig, ax = plt.subplots(subplot_kw={"projection": crs})
        ax.set_extent(extent)
        ax.add_geometries(
            df_ae["geometry"],
            crs=crs,
            facecolor="gainsboro",
            edgecolor="slategray",
            lw=0.1,
            alpha=0.8,
        )
    
        # save plot
        save_path = "germany.png"
        plt.savefig(save_path, dpi=250, bbox_inches="tight", pad_inches=0.0)
        plt.close()