Skip to content

Tutorial: Adding a data set on top of a topographic surface via "drapegrid" of "Figure.grdview" #3316

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 61 commits into from
Sep 2, 2024
Merged
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
5417f38
Add two ideas for gallery example showing the 'drapegrid' parameter
yvonnefroehlich Jul 7, 2024
f849ced
Move and rename file
yvonnefroehlich Jul 7, 2024
0669fa5
Add code block separator
yvonnefroehlich Jul 7, 2024
08549a7
Add shebang
yvonnefroehlich Jul 7, 2024
a3b31c6
Remove shebang
yvonnefroehlich Jul 7, 2024
2ea0b9a
Select thumbnail image
yvonnefroehlich Jul 7, 2024
744287c
Remove 'r'
yvonnefroehlich Jul 7, 2024
7799c8d
TEST: Modifiy exisiting example
yvonnefroehlich Jul 7, 2024
bee9125
TEST: Redo change
yvonnefroehlich Jul 7, 2024
ea05d25
Remove execution permission
yvonnefroehlich Jul 7, 2024
b43228c
Merge branch 'main' into add-gallery-image-on-elevation
yvonnefroehlich Jul 8, 2024
8d5eed7
Merge branch 'main' into add-gallery-image-on-elevation
yvonnefroehlich Jul 10, 2024
d74f5d8
Merge branch 'main' into add-gallery-image-on-elevation
yvonnefroehlich Jul 21, 2024
193743b
Merge branch 'main' into add-gallery-image-on-elevation
yvonnefroehlich Jul 26, 2024
0269127
Use rasterio and xarray to load PNG image
yvonnefroehlich Jul 28, 2024
1d18eea
Remove execute permission
yvonnefroehlich Jul 28, 2024
3b152c4
Merge branch 'main' into add-gallery-image-on-elevation
yvonnefroehlich Jul 28, 2024
520e240
Move to tutoria advanced folder
yvonnefroehlich Jul 29, 2024
3ce58e1
Restructure for tutorial
yvonnefroehlich Jul 29, 2024
a3b5a9e
Remove execution permission
yvonnefroehlich Jul 29, 2024
77d9698
Fix bullet point list
yvonnefroehlich Jul 29, 2024
b09529c
Merge branch 'main' into add-gallery-image-on-elevation
yvonnefroehlich Jul 29, 2024
fc25873
Remove blank line
yvonnefroehlich Jul 29, 2024
9cf465a
Remove execution permission
yvonnefroehlich Jul 29, 2024
ea1369b
Merge branch 'main' into add-gallery-image-on-elevation
yvonnefroehlich Aug 2, 2024
9c14e58
Remove seperation lines
yvonnefroehlich Aug 4, 2024
3e4b55a
Set link to gmt documentation
yvonnefroehlich Aug 4, 2024
e960cf2
Remove variables as only once used in grid examples
yvonnefroehlich Aug 4, 2024
017f320
Pass argument directly to 'perspective' parameter for grid example
yvonnefroehlich Aug 4, 2024
f0c114b
Determine z values from relief grid min max value
yvonnefroehlich Aug 4, 2024
588c07b
Use more clearer comment for 'series' parameter
yvonnefroehlich Aug 4, 2024
07dd23c
Reduce resolution
yvonnefroehlich Aug 4, 2024
9976c5b
Use pandas DataFrame for cities
yvonnefroehlich Aug 4, 2024
150f6f2
Merge branch 'main' into add-gallery-image-on-elevation
yvonnefroehlich Aug 4, 2024
9e68390
Fix code style for DataFrame
yvonnefroehlich Aug 4, 2024
c59af7a
Fix code style 'values' to 'to_numpy'
yvonnefroehlich Aug 4, 2024
56eea56
Fix typo in code
yvonnefroehlich Aug 4, 2024
e88daed
Remove execution permission
yvonnefroehlich Aug 4, 2024
7441a94
Fix typos
yvonnefroehlich Aug 4, 2024
965a29e
Improve comments | Subsection for tutorial
yvonnefroehlich Aug 5, 2024
aafda1a
Fix typos
yvonnefroehlich Aug 5, 2024
8e48b87
Fix link to GMT documentation
yvonnefroehlich Aug 5, 2024
3e5959e
Remove execution permission
yvonnefroehlich Aug 5, 2024
194b7bc
Add explanations
yvonnefroehlich Aug 5, 2024
0e83930
Remove execution permission
yvonnefroehlich Aug 5, 2024
cdf0e60
Adjsut thumbnail image
yvonnefroehlich Aug 5, 2024
90676e9
Add highlighting
yvonnefroehlich Aug 5, 2024
b3da999
Improve file name of tutorial
yvonnefroehlich Aug 5, 2024
1038e86
Use complete line length of 88 characters
yvonnefroehlich Aug 5, 2024
ce940a1
Move pandas.DataFrame for cities to plotting part
yvonnefroehlich Aug 5, 2024
0bbc1bc
Remove double white spaces
yvonnefroehlich Aug 6, 2024
b758166
Merge branch 'main' into add-gallery-image-on-elevation
yvonnefroehlich Aug 6, 2024
bc82fda
Merge branch 'main' into add-gallery-image-on-elevation
yvonnefroehlich Aug 9, 2024
377ae47
Add elevation to DataFrame and use plot3d for cities
yvonnefroehlich Aug 10, 2024
28f6de1
Remove execution permission
yvonnefroehlich Aug 10, 2024
02ad2d7
Merge branch 'main' into add-gallery-image-on-elevation
yvonnefroehlich Aug 14, 2024
488cacb
Merge branch 'main' into add-gallery-image-on-elevation
yvonnefroehlich Aug 31, 2024
5f423b3
Remove code part for plotting features on top of topography
yvonnefroehlich Aug 31, 2024
cb3b095
Remove un-needed import of pandas
yvonnefroehlich Aug 31, 2024
ede2232
Add comment regarding considering the aspect ratio of the image
yvonnefroehlich Sep 1, 2024
539c617
Merge branch 'main' into add-gallery-image-on-elevation
yvonnefroehlich Sep 1, 2024
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
137 changes: 137 additions & 0 deletions examples/tutorials/advanced/draping_on_3d_surface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
"""
Draping a dataset on top of a topographic surface
==================================================

It can be visually appealing to "drape" a dataset over a topographic surface. This can
be accomplished using the ``drapegrid`` parameter of :meth:`pygmt.Figure.grdview`.

This tutorial consists of two examples:

1. Draping a grid

2. Draping an image
"""

# %%

# Load the required packages
import pygmt
import rasterio
import xarray as xr

# %%
# 1. Drapping a grid
# ------------------
#
# In the first example, the seafloor crustal age is plotted with color-coding on top of
# the topographic map of an area of the Mid-Atlantic Ridge.

# Define the study area in degrees East or North
region_2d = [-50, 0, 36, 70] # [lon_min, lon_max, lat_min, lat_max]

# Download elevation and crustal age grids for the study region with a resolution of 10
# arc-minutes and load them into xarray.DataArrays
grd_relief = pygmt.datasets.load_earth_relief(resolution="10m", region=region_2d)
grd_age = pygmt.datasets.load_earth_age(resolution="10m", region=region_2d)

# Determine the 3-D region from the minimum and maximum values of the relief grid
region_3d = [*region_2d, grd_relief.min().to_numpy(), grd_relief.max().to_numpy()]

# %%
# The topographic surface is created based on the grid passed to the ``grid`` parameter
# of :meth:`pygmt.Figure.grdview`; here we use a grid of the Earth relief. To add a
# color-coding based on *another* grid we have to pass a second grid to the
# ``drapegrid`` parameter; here we use a grid of the crustal age. In this case the
# colormap specified via the ``cmap`` parameter applies to the grid passed to
# ``drapegrid``, not to ``grid``. The azimuth and elevation a the 3-D plot are set via
# the ``perspective`` parameter.

fig = pygmt.Figure()

# Set up colormap for the crustal age
pygmt.config(COLOR_NAN="lightgray")
pygmt.makecpt(cmap="batlow", series=[0, 200, 1], reverse=True, overrule_bg=True)

fig.grdview(
projection="M12c", # Mercator projection with a width of 12 centimeters
region=region_3d,
grid=grd_relief, # Use elevation grid for z values
drapegrid=grd_age, # Use crustal age grid for color-coding
cmap=True, # Use colormap created for the crustal age
surftype="i", # Create an image plot
# Use an illumination from the azimuthal directions 0° (north) and 270°
# (west) with a normalization via a cumulative Laplace distribution for
# the shading
shading="+a0/270+ne0.6",
perspective=[157.5, 30], # Azimuth and elevation for the 3-D plot
zsize="1.5c",
plane="+gdarkgray",
frame=True,
)

# Add colorbar for the crustal age
fig.colorbar(frame=["x+lseafloor crustal age", "y+lMyr"], position="+n")

fig.show()


# %%
# 2. Draping an image
# -------------------
#
# In the second example, the flag of the European Union (EU) is plotted on top of a
# topographic map of northwest Europe. This example is modified from
# :gmt-docs:`GMT example 32 </gallery/ex32.html>`.
# We have to consider the dimension of the image we want to drap. The image we will
# download in this example has 1000 x 667 pixels, i.e. a aspect ratio of 3 x 2.

# Define the study area in degrees East or North, with an extend of 6 degrees for
# the longitude and 4 degrees for the latitude
region_2d = [3, 9, 50, 54] # [lon_min, lon_max, lat_min, lat_max]

# Download elevation grid for the study region with a resolution of 30 arc-seconds and
# pixel registration and load it into an xarray.DataArray
grd_relief = pygmt.datasets.load_earth_relief(resolution="30s", region=region_2d)

# Determine the 3-D region from the minimum and maximum values of the relief grid
region_3d = [*region_2d, grd_relief.min().to_numpy(), grd_relief.max().to_numpy()]

# Download an PNG image of the flag of the EU using rasterio and load it into a
# xarray.DataArray
url_to_image = "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/Flag_of_Europe.svg/1000px-Flag_of_Europe.svg.png"
with rasterio.open(url_to_image) as dataset:
data = dataset.read()
drapegrid = xr.DataArray(data, dims=("band", "y", "x"))

# %%
# Again we create a 3-D plot with :meth:`pygmt.Figure.grdview` and passe an Earth relief
# grid to the ``grid`` parameter to create the topographic surface. But now we pass the
# PNG image which was loaded into an :class:`xarray.DataArray` to the ``drapgrid``
# parameter.

fig = pygmt.Figure()

# Set up a colormap with two colors for the EU flag: blue (0/51/153) for the background
# (value 0 in the nedCDF file -> lower half of 0-255 range) and yellow (255/204/0) for
# the stars (value 255 -> upper half)
pygmt.makecpt(cmap="0/51/153,255/204/0", series=[0, 256, 128])

fig.grdview(
Copy link
Member

Choose a reason for hiding this comment

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

Did you forget zsize here?

Copy link
Member Author

@yvonnefroehlich yvonnefroehlich Aug 8, 2024

Choose a reason for hiding this comment

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

I removed the zsize parameter (temporarily), as I have not figured out yet, how to adjust the position of the following plotting elements (added via coast, plot, text) corresponding to the value of zsize:

no zsize zsize="1c"
flag_0c flag_1c
zsize="1.5c" zsize="2c"
flag_1 5c flag_2c

Copy link
Member

Choose a reason for hiding this comment

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

For points, plot3d is needed. For coastlines, it's likely we need to dump the coastlines and the use grdtrack to determine the z-value for each data points and then pass them to plot3d.

projection="M12c", # Mercator projection with a width of 12 centimeters
region=region_3d,
grid=grd_relief, # Use elevation grid for z values
drapegrid=drapegrid, # Drap image grid for the EU flag on top
cmap=True, # Use colormap defined for the EU flag
surftype="i", # Create an image plot
# Use an illumination from the azimuthal directions 0° (north) and 270° (west) with
# a normalization via a cumulative Laplace distribution for the shading
shading="+a0/270+ne0.6",
perspective=[157.5, 30], # Define azimuth, elevation for the 3-D plot
zsize="1c",
plane="+gdarkgray",
frame=True,
)

fig.show()

# sphinx_gallery_thumbnail_number = 2