Search code examples
pythonmatplotlibcartopy

Plotting line across international dateline with Cartopy


I am trying to plot global storm tracks, but when the storms cross the dateline (and longitudes go from ~360 to ~0), the line loops all the way around the plotting space. Here's what the plot looks like. See the weird straight lines near the top. Here's my code:

ax = plt.axes(projection=ccrs.Robinson())
ax.set_global()

ax.coastlines()

for i in range(nstorms-1): #loop through each TC
        bidx = start_idx[i]
        eidx = start_idx[i+1]
        plt.plot(clons[bidx:eidx],clats[bidx:eidx],transform=ccrs.PlateCarree())

If I try changing the transform to Geodetic, it looks like this: this is what happens


Solution

  • To plot polylines that cross the dateline, you need to sanitize the longitudes properly. For example, values 359 to 2 should be adjusted to 359 to 362. In the demo code below, sanitize_lonlist() is used to sanitize a list of longitude values before using it to plot a red zigzag line.

    import cartopy.crs as ccrs
    import matplotlib.pyplot as plt
    
    def sanitize_lonlist(lons):
        new_list = []
        oldval = 0
        treshold = 10  # used to compare adjacent longitudes
        for ix,ea in enumerate(lons):
            diff = oldval - ea
            if (ix>0):
                if (diff>treshold):
                    ea = ea+360
            oldval = ea
            new_list.append(ea)
        return new_list
    
    ax = plt.axes(projection=ccrs.Robinson()) 
    ax.set_global() 
    ax.coastlines(alpha=0.3)
    
    # sample long/lat data for demo purposes
    # xdateline: list of longitudes that cross dateline several times
    xdateline = [347,349,352,358,4,7,8,3,359,358,360,3,5,359,1,357,0,8,12,6,357,349]
    # ydateline: list of accompanying latitudes
    ydateline = range(len(xdateline))
    
    # plot the line crossing dateline using `sanitized` values of longitudes
    plt.plot(sanitize_lonlist(xdateline), ydateline, transform=ccrs.PlateCarree(), color='red') 
    
    plt.show()
    

    datelinexing

    Using the raw values of xdateline to plot with the line of code:-

    plt.plot(xdateline, ydateline, transform=ccrs.PlateCarree(), color='red')
    

    the plot will be:-

    bad-plot