Topographic map clipped by coastlines in Python

Learn how to create visually compelling relief maps in Python by clipping topographic data to specific geographic boundaries, such as coastlines. This tutorial walks you through the process of using matplotlib and Basemap to focus your visualizations on land features within the Taiwan coastline, or alternatively, highlight bathymetric features by masking the land.

Introduction

In this post, we will walk through the process of creating a clipped relief map in Python. This technique is particularly useful for visualizing topographic data within specific geographic boundaries, such as coastlines. If you’re interested in plotting geospatial data clipped by coastlines, you can refer to our previous post here.

In this tutorial, we’ll apply a similar approach, but instead of a general geospatial dataset, we will use a 1-arc minute topographic map, which we also employed in a previous post. This allows us to generate a visually compelling map that highlights the relief of the land while masking out regions outside the coastlines.

To achieve this, we’ll leverage the Path module from matplotlib to work with the polylines representing the coastline of Taiwan. The concept is straightforward—though it may not be the most computationally efficient. We first plot the topography on the map, select the coastal polylines using Path, and then mask the regions outside the coastline with a specified color, such as light blue for the sea.

Creating a Clipped Relief Map: Step by Step

Step 1: Setting Up the Basemap

We start by importing the necessary libraries, including Basemap from mpl_toolkits.basemap, matplotlib, and netCDF4 for handling gridded datasets like ETOPO1. This dataset provides global topography data at a 1-arc minute resolution, which we will use for our map.

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np
import netCDF4
from matplotlib.colors import LightSource
from matplotlib.patches import Path, PathPatch

etopo_file = "/Users/utpalkumar50/Documents/bin/ETOPO1_Bed_g_gmt4.grd"

lonmin, lonmax = 119.5, 122.5
latmin, latmax = 21.5, 25.5

fig, ax = plt.subplots(figsize=(10, 10))
map = Basemap(projection='merc', resolution='f', area_thresh=10000., 
              llcrnrlon=lonmin, llcrnrlat=latmin, urcrnrlon=lonmax, urcrnrlat=latmax)

Step 2: Loading and Preparing the Topographic Data

Next, we load the ETOPO1 data and extract the relevant sections based on our specified latitude and longitude ranges. The data is then sliced to focus on the region around Taiwan.

f = netCDF4.Dataset(etopo_file)
lons = f.variables['lon'][:]
lats = f.variables['lat'][:]
etopo = f.variables['z'][:]

lonmin, lonmax = lonmin - 1, lonmax + 1
latmin, latmax = latmin - 1, latmax + 1

lons_col_index = np.where((lons > lonmin) & (lons < lonmax))[0]
lats_col_index = np.where((lats > latmin) & (lats < latmax))[0]

etopo_sl = etopo[lats_col_index[0]:lats_col_index[-1]+1, lons_col_index[0]:lons_col_index[-1]+1]
lons_sl, lats_sl = np.meshgrid(lons[lons_col_index], lats[lats_col_index])

Step 3: Shading the Relief Map

To create a visually appealing relief map, we use LightSource to add shading, which enhances the three-dimensional appearance of the topography.

ls = LightSource(azdeg=315, altdeg=45)
rgb = ls.shade(np.array(etopo_sl), cmap=plt.cm.terrain, vert_exag=1, blend_mode='soft')

map.imshow(rgb, zorder=2, alpha=0.8, cmap=plt.cm.terrain, interpolation='bilinear')
map.drawcoastlines(color='k', linewidth=1, zorder=3)
map.drawcountries(color='k', linewidth=1, zorder=3)

Step 4: Masking the Regions Outside the Coastline

To highlight the land features within Taiwan while masking out the surrounding sea, we create a PathPatch using the coastline polygons. The patch is then added to the plot, effectively hiding the regions outside the specified boundaries.

x0, x1 = ax.get_xlim()
y0, y1 = ax.get_ylim()
map_edges = np.array([[x0, y0], [x1, y0], [x1, y1], [x0, y1]])
polys = [p.boundary for p in map.landpolygons]
polys = [map_edges] + polys[:]
codes = [[Path.MOVETO] + [Path.LINETO for _ in p[1:]] for p in polys]
verts = [v for p in polys for v in p]
codes = [code for cs in codes for code in cs]

path = Path(verts, codes)
patch = PathPatch(path, facecolor='lightblue', edgecolor='none', zorder=4)

ax.add_patch(patch)
plt.savefig('station_map_masked.png', bbox_inches='tight', dpi=300)
plt.close('all')

Step 5: Reversing the Mask

It’s also possible to reverse the masking, keeping the bathymetric features of the sea while masking out the land regions. This can be done by adjusting the facecolor in the PathPatch.

# Reuse previous code with a slight modification in PathPatch facecolor
patch = PathPatch(path, facecolor='white', edgecolor='none', zorder=4)
ax.add_patch(patch)

plt.savefig('station_map_masked_reverse.png', bbox_inches='tight', dpi=300)
plt.close('all')

Conclusion

In this post, we’ve demonstrated how to generate a clipped relief map using Python, focusing on topographic data within the coastlines of Taiwan. This method, while simple, is a powerful tool for creating focused visualizations of geographic regions. Whether you’re interested in highlighting land features or bathymetric data, the matplotlib and Basemap libraries provide robust capabilities for geospatial analysis and visualization.

For further exploration, you can download the complete code here.

Utpal Kumar
Utpal Kumar

Geophysicist | Geodesist | Seismologist | Open-source Developer
I am a geophysicist with a background in computational geophysics, currently working as a postdoctoral researcher at UC Berkeley. My research focuses on seismic data analysis, structural health monitoring, and understanding deep Earth structures. I have had the opportunity to work on diverse projects, from investigating building characteristics using smartphone data to developing 3D models of the Earth's mantle beneath the Yellowstone hotspot.

In addition to my research, I have experience in cloud computing, high-performance computing, and single-board computers, which I have applied in various projects. This includes working with platforms like AWS, GCP, Linode, DigitalOcean, as well as supercomputing environments such as STAMPEDE2, ANVIL, Savio and PERLMUTTER (and CORI). My work involves developing innovative solutions for structural health monitoring and advancing real-time seismic response analysis. I am committed to applying these skills to further research in computational seismology and structural health monitoring.

Articles: 40

Leave a Reply

Your email address will not be published. Required fields are marked *