Skip to content

Commit 85501bb

Browse files
authored
Figure.grdview: Add parameters surftype/dpi/mesh_fill/nan_transparent/monochrome to control surface types (#4234)
1 parent eead974 commit 85501bb

12 files changed

Lines changed: 303 additions & 106 deletions

examples/gallery/3d_plots/grdview_surface.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@
33
==================
44
55
The :meth:`pygmt.Figure.grdview()` method can plot 3-D surfaces with
6-
``surftype="s"``. Here, we supply the data as an :class:`xarray.DataArray` with
7-
the coordinate vectors ``x`` and ``y`` defined. Note that the ``perspective``
8-
parameter here controls the azimuth and elevation angle of the view. We provide
9-
a list of two arguments to ``frame`` - the first argument specifies the
10-
:math:`x`- and :math:`y`-axes frame attributes and the second argument,
11-
prepended with ``"z"``, specifies the :math:`z`-axis frame attributes.
12-
Specifying the same scale for the ``projection`` and ``zscale`` parameters
13-
ensures equal axis scaling. The ``shading`` parameter specifies illumination;
14-
here we choose an azimuth of 45° with ``shading="+a45"``.
6+
``surftype="surface"``. Here, we supply the data as an :class:`xarray.DataArray` with
7+
the coordinate vectors ``x`` and ``y`` defined. Note that the ``perspective`` parameter
8+
here controls the azimuth and elevation angle of the view. We provide a list of two
9+
arguments to ``frame`` - the first argument specifies the :math:`x`- and :math:`y`-axes
10+
frame attributes and the second argument, prepended with ``"z"``, specifies the
11+
:math:`z`-axis frame attributes. Specifying the same scale for the ``projection`` and
12+
``zscale`` parameters ensures equal axis scaling. The ``shading`` parameter specifies
13+
illumination; here we choose an azimuth of 45° with ``shading="+a45"``.
1514
"""
1615

1716
# %%
@@ -51,7 +50,7 @@ def ackley(x, y):
5150
frame=["a5f1g5", "za5f1g5"],
5251
projection=f"x{SCALE}c",
5352
zscale=f"{SCALE}c",
54-
surftype="s",
53+
surftype="surface",
5554
cmap="SCM/roma",
5655
perspective=[135, 30], # Azimuth southeast (135°), at elevation 30°
5756
shading="+a45",

examples/tutorials/advanced/3d_perspective_image.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,8 @@
4747
frame=["xa", "yaf", "WSnE"],
4848
projection="M15c",
4949
zsize="1.5c",
50-
# Set the surftype to "surface"
51-
surftype="s",
52-
# Set the CPT to "geo"
53-
cmap="gmt/geo",
50+
surftype="surface",
51+
cmap="gmt/geo", # Set the CPT to "geo"
5452
)
5553
fig.show()
5654

@@ -65,7 +63,7 @@
6563
frame=["xa", "yaf", "WSnE"],
6664
projection="M15c",
6765
zsize="1.5c",
68-
surftype="s",
66+
surftype="surface",
6967
cmap="gmt/geo",
7068
plane=1000, # Set the plane elevation to 1,000 meters
7169
facade_fill="gray", # Color the facade in "gray"
@@ -88,7 +86,7 @@
8886
frame=["xaf", "yaf", "WSnE"],
8987
projection="M15c",
9088
zsize="1.5c",
91-
surftype="s",
89+
surftype="surface",
9290
cmap="gmt/geo",
9391
plane=1000,
9492
facade_fill="gray",

examples/tutorials/advanced/draping_on_3d_surface.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
grid=grd_relief, # Use elevation grid for z values
5959
drape_grid=grd_age, # Use crustal age grid for color-coding
6060
cmap=True, # Use colormap created for the crustal age
61-
surftype="i", # Create an image plot
61+
surftype="image", # Create an image plot
6262
# Use an illumination from the azimuthal directions 0° (north) and 270°
6363
# (west) with a normalization via a cumulative Laplace distribution for
6464
# the shading
@@ -122,7 +122,7 @@
122122
grid=grd_relief, # Use elevation grid for z values
123123
drape_grid=drape_grid, # Drape image grid for the EU flag on top
124124
cmap=True, # Use colormap defined for the EU flag
125-
surftype="i", # Create an image plot
125+
surftype="image", # Create an image plot
126126
# Use an illumination from the azimuthal directions 0° (north) and 270° (west) with
127127
# a normalization via a cumulative Laplace distribution for the shading
128128
shading="+a0/270+ne0.6",

pygmt/src/grdview.py

Lines changed: 135 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,45 +10,132 @@
1010
from pygmt._typing import PathLike
1111
from pygmt.alias import Alias, AliasSystem
1212
from pygmt.clib import Session, __gmt_version__
13+
from pygmt.exceptions import GMTInvalidInput
1314
from pygmt.helpers import build_arg_list, deprecate_parameter, fmt_docstring, use_alias
1415
from pygmt.src.grdinfo import grdinfo
1516

1617
__doctest_skip__ = ["grdview"]
1718

1819

20+
def _alias_option_Q( # noqa: N802
21+
surftype=None, dpi=None, mesh_fill=None, monochrome=False, nan_transparent=False
22+
):
23+
"""
24+
Helper function to build the Alias list for the -Q option.
25+
26+
Examples
27+
--------
28+
>>> def parse(**kwargs):
29+
... return AliasSystem(Q=_alias_option_Q(**kwargs)).get("Q")
30+
>>> parse(surftype="surface")
31+
's'
32+
>>> parse(surftype="mesh")
33+
'm'
34+
>>> parse(surftype="surface+mesh")
35+
'sm'
36+
>>> parse(surftype="waterfall_x")
37+
'mx'
38+
>>> parse(surftype="waterfall_y")
39+
'my'
40+
>>> parse(surftype="image")
41+
'i'
42+
>>> parse(surftype="image", nan_transparent=True)
43+
'c'
44+
>>> parse(surftype="image", dpi=150)
45+
'i150'
46+
>>> parse(surftype="image", dpi=150, nan_transparent=True)
47+
'c150'
48+
>>> parse(surftype="mesh", mesh_fill="blue")
49+
'mblue'
50+
>>> parse(surftype="surface", monochrome=True)
51+
's+m'
52+
>>> parse(surftype="surface+mesh", monochrome=True)
53+
'sm+m'
54+
55+
>>> # Check for backward compatibility with old raw GMT syntax.
56+
>>> for surftype in ["s", "m", "sm", "i", "c", "mx", "my", "mblue", "i150"]:
57+
... assert parse(surftype=surftype) == surftype
58+
"""
59+
_surftype_mapping = {
60+
"surface": "s",
61+
"mesh": "m",
62+
"surface+mesh": "sm",
63+
"image": "c" if nan_transparent is True else "i",
64+
"waterfall_x": "mx",
65+
"waterfall_y": "my",
66+
}
67+
# Previously, 'surftype' was aliased to Q.
68+
_old_surftype_syntax = surftype is not None and surftype not in _surftype_mapping
69+
70+
if _old_surftype_syntax and any(
71+
v is not None and v is not False
72+
for v in (dpi, mesh_fill, monochrome, nan_transparent)
73+
):
74+
msg = (
75+
"Parameter 'surftype' is given with a raw GMT command string, and conflicts "
76+
"with parameters 'dpi', 'mesh_fill', 'monochrome', or 'nan_transparent'."
77+
)
78+
raise GMTInvalidInput(msg)
79+
80+
if dpi is not None and surftype != "image":
81+
msg = "Parameter 'dpi' can only be used when 'surftype' is 'image'."
82+
raise GMTInvalidInput(msg)
83+
if nan_transparent and surftype != "image":
84+
msg = "Parameter 'nan_transparent' can only be used when 'surftype' is 'image'."
85+
raise GMTInvalidInput(msg)
86+
if mesh_fill is not None and surftype not in {"mesh", "waterfall_x", "waterfall_y"}:
87+
msg = (
88+
"Parameter 'mesh_fill' can only be used when 'surftype' is 'mesh', "
89+
"'waterfall_x', or 'waterfall_y'."
90+
)
91+
raise GMTInvalidInput(msg)
92+
93+
return [
94+
Alias(
95+
surftype,
96+
name="surftype",
97+
mapping=_surftype_mapping if not _old_surftype_syntax else None,
98+
),
99+
Alias(dpi, name="dpi"),
100+
Alias(mesh_fill, name="mesh_fill"),
101+
Alias(monochrome, name="monochrome", prefix="+m"),
102+
]
103+
104+
19105
@fmt_docstring
20106
# TODO(PyGMT>=0.20.0): Remove the deprecated '*pen' parameters.
21107
# TODO(PyGMT>=0.20.0): Remove the deprecated 'drapegrid' parameter.
22108
@deprecate_parameter("contourpen", "contour_pen", "v0.18.0", remove_version="v0.20.0")
23109
@deprecate_parameter("facadepen", "facade_pen", "v0.18.0", remove_version="v0.20.0")
24110
@deprecate_parameter("meshpen", "mesh_pen", "v0.18.0", remove_version="v0.20.0")
25111
@deprecate_parameter("drapegrid", "drape_grid", "v0.18.0", remove_version="v0.20.0")
26-
@use_alias(
27-
C="cmap",
28-
G="drape_grid",
29-
Q="surftype",
30-
I="shading",
31-
f="coltypes",
32-
n="interpolation",
33-
)
112+
@use_alias(C="cmap", G="drape_grid", I="shading", f="coltypes", n="interpolation")
34113
def grdview( # noqa: PLR0913
35114
self,
36115
grid: PathLike | xr.DataArray,
116+
surftype: Literal[
117+
"mesh", "surface", "surface+mesh", "image", "waterfall_x", "waterfall_y"
118+
]
119+
| None = None,
120+
dpi: int | None = None,
121+
nan_transparent: bool = False,
122+
monochrome: bool = False,
37123
contour_pen: str | None = None,
124+
mesh_fill: str | None = None,
38125
mesh_pen: str | None = None,
39126
plane: float | bool = False,
40127
facade_fill: str | None = None,
41128
facade_pen: str | None = None,
42129
projection: str | None = None,
43130
zscale: float | str | None = None,
44131
zsize: float | str | None = None,
45-
frame: str | Sequence[str] | bool = False,
46132
region: Sequence[float | str] | str | None = None,
133+
frame: str | Sequence[str] | bool = False,
47134
verbose: Literal["quiet", "error", "warning", "timing", "info", "compat", "debug"]
48135
| bool = False,
49136
panel: int | Sequence[int] | bool = False,
50-
transparency: float | None = None,
51137
perspective: float | Sequence[float] | str | bool = False,
138+
transparency: float | None = None,
52139
**kwargs,
53140
):
54141
r"""
@@ -69,6 +156,7 @@ def grdview( # noqa: PLR0913
69156
- JZ = zsize
70157
- N = plane, facade_fill
71158
- R = region
159+
- Q = surftype, dpi, mesh_fill, nan_transparent, **+m**: monochrome
72160
- V = verbose
73161
- Wc = contour_pen
74162
- Wf = facade_pen
@@ -80,15 +168,6 @@ def grdview( # noqa: PLR0913
80168
Parameters
81169
----------
82170
$grid
83-
region : str or list
84-
*xmin/xmax/ymin/ymax*\ [**+r**][**+u**\ *unit*].
85-
Specify the :doc:`region </tutorials/basics/regions>` of interest. When used
86-
with ``perspective``, optionally append */zmin/zmax* to indicate the range to
87-
use for the 3-D axes [Default is the region given by the input grid].
88-
$projection
89-
zscale/zsize
90-
Set z-axis scaling or z-axis size.
91-
$frame
92171
cmap : str
93172
The name of the color palette table to use.
94173
drape_grid : str or :class:`xarray.DataArray`
@@ -97,24 +176,30 @@ def grdview( # noqa: PLR0913
97176
Note that ``zscale`` and ``plane`` always refer to ``grid``. ``drape_grid`` only
98177
provides the information pertaining to colors, which (if ``drape_grid`` is a
99178
grid) will be looked-up via the CPT (see ``cmap``).
100-
surftype : str
101-
Specify cover type of the grid. Select one of following settings:
102-
103-
- **m**: mesh plot [Default].
104-
- **mx** or **my**: waterfall plots (row or column profiles).
105-
- **s**: surface plot, and optionally append **m** to have mesh lines drawn on
106-
top of the surface.
107-
- **i**: image plot.
108-
- **c**: Same as **i** but will make nodes with z = NaN transparent.
109-
110-
For any of these choices, you may force a monochrome image by appending the
111-
modifier **+m**.
179+
surftype
180+
Specify surface type for the grid. Valid values are:
181+
182+
- ``"mesh"``: mesh plot [Default].
183+
- ``"surface"``: surface plot.
184+
- ``"surface+mesh"``: surface plot with mesh lines drawn on top of the surface.
185+
- ``"image"``: image plot.
186+
- ``"waterfall_x"``/``"waterfall_y"``: waterfall plots (row or column profiles).
187+
dpi
188+
Effective dots-per-unit resolution for the rasterization for image plots (i.e.,
189+
``surftype="image"``) [Default is :gmt-term:`GMT_GRAPHICS_DPU`]
190+
nan_transparent
191+
Make grid nodes with z = NaN transparent, using the color-masking feature in
192+
PostScript Level 3. Only applies when ``surftype="image"``.
193+
monochrome
194+
Force conversion to monochrome image using the (television) YIQ transformation.
112195
contour_pen
113196
Draw contour lines on top of surface or mesh (not image). Append pen attributes
114197
used for the contours.
115198
mesh_pen
116-
Set the pen attributes used for the mesh. You must also select ``surftype`` of
117-
**m** or **sm** for meshlines to be drawn.
199+
Set the pen attributes used for the mesh. Need to set ``surftype`` to
200+
``"mesh"``, or ``"surface+mesh"`` to draw meshlines.
201+
mesh_fill
202+
Set the mesh fill in mesh plot or waterfall plots [Default is white].
118203
plane
119204
Draw a plane at the specified z-level. If ``True``, defaults to the minimum
120205
value in the grid. However, if ``region`` was used to set *zmin/zmax* then
@@ -135,6 +220,15 @@ def grdview( # noqa: PLR0913
135220
**+m**\ *ambient* to specify azimuth, intensity, and ambient arguments for that
136221
function, or just give **+d** to select the default arguments [Default is
137222
``"+a-45+nt1+m0"``].
223+
$projection
224+
zscale/zsize
225+
Set z-axis scaling or z-axis size.
226+
region : str or list
227+
*xmin/xmax/ymin/ymax*\ [**+r**][**+u**\ *unit*].
228+
Specify the :doc:`region </tutorials/basics/regions>` of interest. When used
229+
with ``perspective``, optionally append */zmin/zmax* to indicate the range to
230+
use for the 3-D axes [Default is the region given by the input grid].
231+
$frame
138232
$verbose
139233
$panel
140234
$coltypes
@@ -167,7 +261,7 @@ def grdview( # noqa: PLR0913
167261
... # Set the vertical scale (z-axis) to 2 cm
168262
... zsize="2c",
169263
... # Set "surface plot" to color the surface via a CPT
170-
... surftype="s",
264+
... surftype="surface",
171265
... # Specify CPT to "geo"
172266
... cmap="gmt/geo",
173267
... )
@@ -195,6 +289,13 @@ def grdview( # noqa: PLR0913
195289
aliasdict = AliasSystem(
196290
Jz=Alias(zscale, name="zscale"),
197291
JZ=Alias(zsize, name="zsize"),
292+
Q=_alias_option_Q(
293+
surftype=surftype,
294+
dpi=dpi,
295+
mesh_fill=mesh_fill,
296+
monochrome=monochrome,
297+
nan_transparent=nan_transparent,
298+
),
198299
N=[
199300
Alias(plane, name="plane"),
200301
Alias(facade_fill, name="facade_fill", prefix="+g"),
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
outs:
2+
- md5: d384910b17de5a2a842cd2625761c821
3+
size: 224724
4+
hash: md5
5+
path: test_grdview_image_dpi.png
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
outs:
2+
- md5: 9158bd6308a9bb59fdcaf56e406954b3
3+
size: 55008
4+
hash: md5
5+
path: test_grdview_mesh_pen_and_mesh_fill.png
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
outs:
2+
- md5: 9fff6fa175e44085570cb61b6bd62f6e
3+
size: 104557
4+
hash: md5
5+
path: test_grdview_monochrome.png
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
outs:
2+
- md5: 6a8a38827078400854c972bd24b0d898
3+
size: 215417
4+
hash: md5
5+
path: test_grdview_surftype.png

pygmt/tests/baseline/test_grdview_with_cmap_for_image_plot.png.dvc

Lines changed: 0 additions & 4 deletions
This file was deleted.

pygmt/tests/baseline/test_grdview_with_cmap_for_perspective_surface_plot.png.dvc

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)