Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
095c795
Add first draft for gallery example or tutorial on grdmask
yvonnefroehlich Apr 9, 2026
5456a7f
Adjust regions
yvonnefroehlich Apr 9, 2026
31d1b74
Try extracting a circle
yvonnefroehlich Apr 9, 2026
4584da7
Remove execution permission
yvonnefroehlich Apr 9, 2026
2b8a632
Select US staat
yvonnefroehlich Apr 10, 2026
b936f5d
Zoom in mask grid
yvonnefroehlich Apr 10, 2026
2c1c264
Try inside and outside
yvonnefroehlich Apr 10, 2026
a62befc
Adjust area for US staat, fix typo, improve code
yvonnefroehlich Apr 10, 2026
9cb4b75
Fix style
yvonnefroehlich Apr 10, 2026
c0ef611
Set outside parameter correctly
yvonnefroehlich Apr 10, 2026
6326c19
Fix typo
yvonnefroehlich Apr 10, 2026
a4d8f5e
Adjust title - circles are no polygons
yvonnefroehlich Apr 10, 2026
5173eff
Change back to None
yvonnefroehlich Apr 11, 2026
30ae770
Revert "Change back to None"
yvonnefroehlich Apr 11, 2026
bc14c58
Merge branch 'main' into add-gallery-grdmask
yvonnefroehlich Apr 11, 2026
ac5403d
Fix typo, add folder for cmaps
yvonnefroehlich Apr 18, 2026
98f32db
Merge branch 'main' into add-gallery-grdmask
yvonnefroehlich Apr 18, 2026
3403501
Merge branch 'main' into add-gallery-grdmask
yvonnefroehlich Apr 20, 2026
1b54365
Add first version of intro text
yvonnefroehlich Apr 20, 2026
5938662
Merge branch 'main' into add-gallery-grdmask
yvonnefroehlich Apr 28, 2026
86da3ab
Merge branch 'main' into add-gallery-grdmask
yvonnefroehlich May 1, 2026
904b0fe
Merge branch 'main' into add-gallery-grdmask
yvonnefroehlich May 24, 2026
8bc55d5
Merge branch 'main' into add-gallery-grdmask
yvonnefroehlich Jun 11, 2026
33338a0
Merge branch 'main' into add-gallery-grdmask
yvonnefroehlich Jun 18, 2026
544fc07
Remove white space to fix link to grdlandmask gallery example
yvonnefroehlich Jun 18, 2026
667fbb5
Fix typo
yvonnefroehlich Jun 18, 2026
1a57988
Improve formulation
yvonnefroehlich Jun 24, 2026
4e1d653
Merge branch 'main' into add-gallery-grdmask
yvonnefroehlich Jun 24, 2026
871c469
Merge branch 'main' into add-gallery-grdmask
yvonnefroehlich Jun 25, 2026
c95623c
Fix typo
yvonnefroehlich Jun 25, 2026
114ec89
Adjust color for outline
yvonnefroehlich Jun 25, 2026
e9f0ed5
Merge branch 'main' into add-gallery-grdmask
yvonnefroehlich Jun 25, 2026
bfb2402
Remove colorbar
yvonnefroehlich Jun 25, 2026
4bf9102
Move to advaced tutorials
yvonnefroehlich Jun 28, 2026
7cd4495
Remove execution permission
yvonnefroehlich Jun 28, 2026
70afe29
Reduce resolution of grid, reduce size of subplots
yvonnefroehlich Jun 29, 2026
688f6d7
Merge remote-tracking branch 'origin/add-gallery-grdmask' into add-ga…
yvonnefroehlich Jun 29, 2026
11ef768
Make file name more descriptive
yvonnefroehlich Jun 29, 2026
3fc3bef
Merge branch 'main' into add-gallery-grdmask
yvonnefroehlich Jun 29, 2026
ffd2aec
Add higlighting
yvonnefroehlich Jun 30, 2026
6e17927
Adjust comment to changed value
yvonnefroehlich Jun 30, 2026
d06567e
Improve comments
yvonnefroehlich Jun 30, 2026
14d6f06
Make variable names more exact even they are now longer
yvonnefroehlich Jun 30, 2026
5341e34
Fix highlighting
yvonnefroehlich Jun 30, 2026
a4c27ac
Fix highlighting
yvonnefroehlich Jun 30, 2026
9d67e16
Add more highlighting
yvonnefroehlich Jun 30, 2026
d4d060c
Fix line length
yvonnefroehlich Jun 30, 2026
15328f6
Merge branch 'main' into add-gallery-grdmask
yvonnefroehlich Jun 30, 2026
8ebbfc8
Remove colorbars
yvonnefroehlich Jun 30, 2026
b372fce
Add note regarding not adding colorbars
yvonnefroehlich Jun 30, 2026
7750874
Adjust structure of intro text
yvonnefroehlich Jun 30, 2026
ff6e861
Explain values for nodes in intro text
yvonnefroehlich Jun 30, 2026
e77df68
Improve formulation
yvonnefroehlich Jun 30, 2026
9cc268c
Add missing word
yvonnefroehlich Jun 30, 2026
1116e28
Add word
yvonnefroehlich Jun 30, 2026
583c5ca
Improve intro text
yvonnefroehlich Jun 30, 2026
05e8beb
Merge branch 'main' into add-gallery-grdmask
yvonnefroehlich Jul 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 169 additions & 0 deletions examples/tutorials/advanced/create_grid_masks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
"""
Comment thread
yvonnefroehlich marked this conversation as resolved.
Create grid masks from spatial shapes
=====================================

The functionn :func:`pygmt.grdmask` allows to create a grid mask based on spatial shapes
given as closed polygons. These polygons can be provided as :class:`numpy.ndarray` or
:class:`geopandas.GeoDataFrame`. For the nodes falling inside, outside, and on the
edges, different values can be defined. The created mask can then be applied to a
desired grid.

This value can be any number, or one of ``None``, ``"NaN"``, and ``np.nan`` for NaN. The
defaults are ``0`` for ``outside``, ``0`` for ``edge``, and ``1`` for ``inside``. To
treat edges as inside, use the same value as for ``inside``. When setting these values,
keep in mind you are creating the mask grid first which is thought to be applied to a
real grid in a second step.

To create a land-water mask based on the GMT built-in shoreline data you can directly
use the function :func:`pygmt.grdlandmask` explained in the gallery example
:doc:`Create 'wet-dry' mask grid </gallery/images/grdlandmask>`. As the focus of this
tutorial is on creating a mask grid and the related masked grid, no colorbars for the
elevation grids are added to the maps.
"""

# %%
import geopandas
import numpy as np
import pygmt
from shapely.geometry import Point

# %%
# Polygons based on a :class:`numpy.ndarray`
# ------------------------------------------

# Define a study region
region = [125, 135, 25, 36]

# Define two closed polygons, here a square and a triangle.
# Use a record with np.nan to separate the polygons
polygon = np.array(
[
[129, 31],
[134, 31],
[134, 35],
[129, 35],
[129, 31],
[np.nan, np.nan],
[126, 26],
[131, 26],
[131, 30],
[126, 26],
],
)

# Download elevation grid
grid = pygmt.datasets.load_earth_relief(region=region, resolution="01m")

# Create a grid mask based on the two polygons defined above
# Set all grid nodes outside the polygons to NaN
mask_outside = pygmt.grdmask(region=region, data=polygon, spacing="01m", outside="NaN")
# Set all grid nodes inside the polygons to NaN
# Set the outside parameter to a value larger 0 to keep the nodes outside unchanged
mask_inside = pygmt.grdmask(
region=region, data=polygon, spacing="01m", inside="NaN", outside=1
)
Comment on lines +57 to +64

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we should explain the default values for inside/outside/edge to better understand the behavior.


# Apply the grid mask to the downloaded elevation grid by multiplying the two grids
grid_masked_outside = grid * mask_outside
grid_masked_inside = grid * mask_inside


fig = pygmt.Figure()
pygmt.makecpt(cmap="SCM/oleron", series=[-2000, 2000])

# Plot the elevation grid
fig.basemap(region=region, projection="M10c", frame=True)
fig.grdimage(grid=grid, cmap=True)
fig.plot(data=polygon, pen="2p,cyan")

fig.shift_origin(xshift="+w+2c")

# Plot the masked elevation grid outside
fig.basemap(region=region, projection="M10c", frame=True)
fig.grdimage(grid=grid_masked_outside, cmap=True)
fig.plot(data=polygon, pen="2p,cyan")

fig.shift_origin(xshift="+w+2c")

# Plot the masked elevation grid inside
fig.basemap(region=region, projection="M10c", frame=True)
fig.grdimage(grid=grid_masked_inside, cmap=True)
fig.plot(data=polygon, pen="2p,cyan")

fig.show()


# %%
Comment thread
seisman marked this conversation as resolved.
# US state Missouri based on a :class:`geopandas.GeoDataFrame` polygon geometry
# -----------------------------------------------------------------------------

region = [-126, -66, 25, 49]

provider = "https://naciscdn.org/naturalearth"
states = geopandas.read_file(
f"{provider}/50m/cultural/ne_50m_admin_1_states_provinces.zip"
)
missouri = states[states["name"] == "Missouri"]

grid = pygmt.datasets.load_earth_relief(region=region, resolution="01m")
mask = pygmt.grdmask(region=region, data=missouri, spacing="01m", outside="NaN")
mask_lonlat = mask.rename(new_name_or_name_dict={"x": "lon", "y": "lat"})
grid_masked = grid * mask_lonlat


fig = pygmt.Figure()
pygmt.makecpt(cmap="SCM/oleron", series=[-2000, 2000])

# Plot the elevation grid
fig.basemap(projection="L-96/35/33/41/12c", region=region, frame=True)
fig.grdimage(grid=grid, cmap=True)
fig.plot(data=missouri, pen="1p,cyan")

fig.shift_origin(xshift="+w+1c")

# Plot the masked elevation grid
# fig.basemap(projection="L-96/35/33/41/12c", region=region, frame=True)
fig.basemap(projection="M10c", region=[-96.5, -88.5, 35.8, 41], frame=True)
fig.grdimage(grid=grid_masked, cmap=True)
fig.plot(data=missouri, pen="1p,cyan")

fig.show()


# %%
# Circle based on GeoPandas polygon geometry
# ------------------------------------------
#
# Note the distortion of the circle due the projection making it appear as an ellipse.

region = [125, 135, 25, 36]

# Create a point and buffer it
point = geopandas.GeoSeries([Point(126.5, 33.5)])
circle = point.buffer(0.6) # 0.6 is the radius

# Create masked grid
grid = pygmt.datasets.load_earth_relief(region=region, resolution="30s")
mask = pygmt.grdmask(region=region, data=circle, spacing="30s", outside="NaN")
mask_lonlat = mask.rename(new_name_or_name_dict={"x": "lon", "y": "lat"})
grid_masked = grid * mask_lonlat


fig = pygmt.Figure()
pygmt.makecpt(cmap="SCM/oleron", series=[-2000, 2000])

# Plot the elevation grid
fig.basemap(region=region, projection="M12c", frame=True)
fig.grdimage(grid=grid, cmap=True)
fig.plot(data=circle, pen="2p,cyan")

fig.shift_origin(xshift="+w+2c")

# Plot the masked elevation grid
fig.basemap(region=[125.5, 127.5, 32.5, 34.5], projection="M12c", frame=True)
fig.grdimage(grid=grid_masked, cmap=True)
fig.plot(data=circle, pen="2p,cyan")

fig.show()

# sphinx_gallery_thumbnail_number = 1
4 changes: 2 additions & 2 deletions pygmt/src/grdmask.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,15 +167,15 @@ def grdmask(
Can be any number, or one of ``None``, ``"NaN"``, and ``np.nan`` for NaN.
Defaults are ``0`` for ``outside``, ``0`` for ``edge``, and ``1`` for
``inside``. When setting these values, keep in mind you are creating a mask grid
which is thought to be applied to a real grid in a second step.
here which is thought to be applied to a real grid in a second step.

``edge`` and ``inside`` can also be set to one of the following values:

- ``"z"``: Use the z-values from polygon data (segment header ``-Zzval``,
``-Lheader``, or via ``-aZ=name``).
- ``"id"``: Use a running polygon ID number.

To treat edges as inside, use the same value as ``inside``.
To treat edges as inside, use the same value as for ``inside``.
id_start
The starting number for polygon IDs when ``inside="id"`` [Default is ``0``].
Only valid when ``inside="id"``.
Expand Down