"""
grdview - Create 3-D perspective image or surface mesh from a grid.
"""
from collections.abc import Sequence
from typing import Literal
import xarray as xr
from packaging.version import Version
from pygmt._typing import PathLike
from pygmt.alias import Alias, AliasSystem
from pygmt.clib import Session, __gmt_version__
from pygmt.helpers import build_arg_list, deprecate_parameter, fmt_docstring, use_alias
from pygmt.src.grdinfo import grdinfo
__doctest_skip__ = ["grdview"]
@fmt_docstring
@deprecate_parameter("contourpen", "contour_pen", "v0.18.0", remove_version="v0.20.0")
@deprecate_parameter("facadepen", "facade_pen", "v0.18.0", remove_version="v0.20.0")
@deprecate_parameter("meshpen", "mesh_pen", "v0.18.0", remove_version="v0.20.0")
@deprecate_parameter("drapegrid", "drape_grid", "v0.18.0", remove_version="v0.20.0")
@use_alias(
C="cmap",
G="drape_grid",
Q="surftype",
I="shading",
f="coltypes",
n="interpolation",
)
def grdview( # noqa: PLR0913
self,
grid: PathLike | xr.DataArray,
contour_pen: str | None = None,
mesh_pen: str | None = None,
plane: float | bool = False,
facade_fill: str | None = None,
facade_pen: str | None = None,
projection: str | None = None,
zscale: float | str | None = None,
zsize: float | str | None = None,
frame: str | Sequence[str] | bool = False,
region: Sequence[float | str] | str | None = None,
verbose: Literal["quiet", "error", "warning", "timing", "info", "compat", "debug"]
| bool = False,
panel: int | Sequence[int] | bool = False,
transparency: float | None = None,
perspective: float | Sequence[float] | str | bool = False,
**kwargs,
):
r"""
Create 3-D perspective image or surface mesh from a grid.
Reads a 2-D grid file and produces a 3-D perspective plot by drawing a mesh,
painting a colored/gray-shaded surface made up of polygons, or by scanline
conversion of these polygons to a raster image. Options include draping a data
set on top of a surface, plotting of contours on top of the surface, and apply
artificial illumination based on intensities provided in a separate grid file.
Full GMT docs at :gmt-docs:`grdview.html`.
$aliases
- B = frame
- J = projection
- Jz = zscale
- JZ = zsize
- N = plane, facade_fill
- R = region
- V = verbose
- Wc = contour_pen
- Wf = facade_pen
- Wm = mesh_pen
- c = panel
- p = perspective
- t = transparency
Parameters
----------
$grid
region : str or list
*xmin/xmax/ymin/ymax*\ [**+r**][**+u**\ *unit*].
Specify the :doc:`region </tutorials/basics/regions>` of interest. When used
with ``perspective``, optionally append */zmin/zmax* to indicate the range to
use for the 3-D axes [Default is the region given by the input grid].
$projection
zscale/zsize
Set z-axis scaling or z-axis size.
$frame
cmap : str
The name of the color palette table to use.
drape_grid : str or :class:`xarray.DataArray`
The file name or a :class:`xarray.DataArray` of the image grid to be draped on
top of the relief provided by ``grid`` [Default determines colors from ``grid``]
Note that ``zscale`` and ``plane`` always refer to ``grid``. ``drape_grid`` only
provides the information pertaining to colors, which (if ``drape_grid`` is a
grid) will be looked-up via the CPT (see ``cmap``).
surftype : str
Specify cover type of the grid. Select one of following settings:
- **m**: mesh plot [Default].
- **mx** or **my**: waterfall plots (row or column profiles).
- **s**: surface plot, and optionally append **m** to have mesh lines drawn on
top of the surface.
- **i**: image plot.
- **c**: Same as **i** but will make nodes with z = NaN transparent.
For any of these choices, you may force a monochrome image by appending the
modifier **+m**.
contour_pen
Draw contour lines on top of surface or mesh (not image). Append pen attributes
used for the contours.
mesh_pen
Set the pen attributes used for the mesh. You must also select ``surftype`` of
**m** or **sm** for meshlines to be drawn.
plane
Draw a plane at the specified z-level. If ``True``, defaults to the minimum
value in the grid. However, if ``region`` was used to set *zmin/zmax* then
*zmin* is used if it is less than the grid minimum value. Use ``facade_pen`` and
``facade_fill`` to control the appearance of the plane.
**Note**: For GMT<=6.6.0, *zmin* set in ``region`` has no effect due to a GMT
bug.
facade_fill
Fill for the frontal facade between the plane specified by ``plane`` and the
data perimeter.
facade_pen
Set the pen attributes used for the facade.
shading : str or float
Provide the name of a grid file with intensities in the (-1,+1) range, or a
constant intensity to apply everywhere (affects the ambient light).
Alternatively, derive an intensity grid from the main input data grid by using
:func:`pygmt.grdgradient` first; append **+a**\ *azimuth*, **+n**\ *args*, and
**+m**\ *ambient* to specify azimuth, intensity, and ambient arguments for that
function, or just give **+d** to select the default arguments [Default is
``"+a-45+nt1+m0"``].
$verbose
$panel
$coltypes
$interpolation
$perspective
$transparency
Example
-------
>>> import pygmt
>>> # Load the 30 arc-minutes grid with "gridline" registration in a given region
>>> grid = pygmt.datasets.load_earth_relief(
... resolution="30m",
... region=[-92.5, -82.5, -3, 7],
... registration="gridline",
... )
>>> # Create a new figure instance with pygmt.Figure()
>>> fig = pygmt.Figure()
>>> # Create the contour plot
>>> fig.grdview(
... # Pass in the grid downloaded above
... grid=grid,
... # Set the perspective to an azimuth of 130° and an elevation of 30°
... perspective=[130, 30],
... # Add a frame to the x- and y-axes
... # Specify annotations on the south and east borders of the plot
... frame=["xa", "ya", "wSnE"],
... # Set the projection of the 2-D map to Mercator with a 10 cm width
... projection="M10c",
... # Set the vertical scale (z-axis) to 2 cm
... zsize="2c",
... # Set "surface plot" to color the surface via a CPT
... surftype="s",
... # Specify CPT to "geo"
... cmap="gmt/geo",
... )
>>> # Show the plot
>>> fig.show()
"""
self._activate_figure()
# Enable 'plane' if 'facade_fill' or 'facade_pen' are set
if plane is False and (facade_fill is not None or facade_pen is not None):
plane = True
# Workaround for GMT bug https://github.com/GenericMappingTools/gmt/pull/8838
# Fix the plane value to be the grid minimum if plane=True.
# Notes:
# 1. It's the minimum of the grid, not a subset of the grid defined by 'region'.
# 2. The GMT docs says "if -R was used to set zmin/zmax then we use that value if
# it is less than the grid minimum value.". We can't add a workaround for this
# case since we can't parse zmin/zmax from 'region' if 'region' was set in
# previous plotting commands.
# TODO(GMT>6.6.0): Remove this workaround.
if Version(__gmt_version__) <= Version("6.6.0") and plane is True:
plane = grdinfo(grid, per_column=True).split()[4]
aliasdict = AliasSystem(
Jz=Alias(zscale, name="zscale"),
JZ=Alias(zsize, name="zsize"),
N=[
Alias(plane, name="plane"),
Alias(facade_fill, name="facade_fill", prefix="+g"),
],
Wc=Alias(contour_pen, name="contour_pen"),
Wf=Alias(facade_pen, name="facade_pen"),
Wm=Alias(mesh_pen, name="mesh_pen"),
).add_common(
B=frame,
J=projection,
R=region,
V=verbose,
c=panel,
p=perspective,
t=transparency,
)
aliasdict.merge(kwargs)
with Session() as lib:
with (
lib.virtualfile_in(check_kind="raster", data=grid) as vingrd,
lib.virtualfile_in(
check_kind="raster", data=kwargs.get("G"), required=False
) as vdrapegrid,
):
aliasdict["G"] = vdrapegrid
lib.call_module(
module="grdview", args=build_arg_list(aliasdict, infile=vingrd)
)