Skip to content

Commit bee3fb4

Browse files
seismanweiji14
authored andcommitted
Allow passing xr.DataArray as shading to grdimage (GenericMappingTools#750)
* Pass xr.DataArray shading to grdimage * Test grdimage with xarray.DataArray input to both grid and shading * Update grdimage shading docstring to mention xarray.DataArray input * Mark the grdimage shading test as xfail [skip ci] Co-authored-by: Wei Ji <[email protected]>
1 parent bb4196b commit bee3fb4

2 files changed

Lines changed: 61 additions & 24 deletions

File tree

pygmt/src/grdimage.py

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
"""
22
grdimage - Plot grids or images.
33
"""
4+
import contextlib
5+
46
from pygmt.clib import Session
5-
from pygmt.helpers import build_arg_string, fmt_docstring, kwargs_to_strings, use_alias
7+
from pygmt.helpers import (
8+
build_arg_string,
9+
data_kind,
10+
fmt_docstring,
11+
kwargs_to_strings,
12+
use_alias,
13+
)
614

715

816
@fmt_docstring
@@ -36,15 +44,17 @@ def grdimage(self, grid, **kwargs):
3644
Project and plot grids or images.
3745
3846
Reads a 2-D grid file and produces a gray-shaded (or colored) map by
39-
building a rectangular image and assigning pixels a gray-shade (or
40-
color) based on the z-value and the CPT file. Optionally, illumination
41-
may be added by providing a file with intensities in the (-1,+1) range
42-
or instructions to derive intensities from the input data grid. Values
43-
outside this range will be clipped. If GMT is built with GDAL support,
44-
``grid`` can be an image file (geo-referenced or not). In this case the
45-
image can optionally be illuminated with the file provided via the
46-
``shading`` parameter. Here, if image has no coordinates then those of the
47-
intensity file will be used.
47+
building a rectangular image and assigning pixels a gray-shade (or color)
48+
based on the z-value and the CPT file. Optionally, illumination may be
49+
added by providing a file with intensities in the (-1,+1) range or
50+
instructions to derive intensities from the input data grid. Values outside
51+
this range will be clipped. Such intensity files can be created from the
52+
grid using :meth:`pygmt.grdgradient` and, optionally, modified by
53+
``grdmath`` or ``grdhisteq``. If GMT is built with GDAL support, ``grid``
54+
can be an image file (geo-referenced or not). In this case the image can
55+
optionally be illuminated with the file provided via the ``shading``
56+
parameter. Here, if image has no coordinates then those of the intensity
57+
file will be used.
4858
4959
When using map projections, the grid is first resampled on a new
5060
rectangular grid with the same dimensions. Higher resolution images can
@@ -116,19 +126,20 @@ def grdimage(self, grid, **kwargs):
116126
paint the mask with the given color. Append **+b** to paint the
117127
background pixels (1) or **+f** for the foreground pixels
118128
[Default is **+f**].
119-
shading : str
120-
*intensfile*\|\ *intensity*\|\ *modifiers*.
121-
Give the name of a grid file with intensities in the (-1,+1) range,
122-
or a constant intensity to apply everywhere (affects the ambient
123-
light). Alternatively, derive an intensity grid from the input data
124-
grid via a call to ``grdgradient``; append **+a**\ *azimuth*,
125-
**+n**\ *args*, and **+m**\ *ambient* to specify azimuth,
126-
intensity, and ambient arguments for that module, or just give
127-
**+d** to select the default arguments
128-
[Default is **+a**\ -45\ **+nt**\ 1\ **+m**\ 0]. If you want a more
129-
specific intensity scenario then run ``grdgradient`` separately first.
130-
If we should derive intensities from another file than grid, specify
131-
the file with suitable modifiers [Default is no illumination].
129+
shading : str or xarray.DataArray
130+
[*intensfile*\|\ *intensity*\|\ *modifiers*].
131+
Give the name of a grid file or a DataArray with intensities in the
132+
(-1,+1) range, or a constant intensity to apply everywhere (affects the
133+
ambient light). Alternatively, derive an intensity grid from the input
134+
data grid via a call to :meth:`pygmt.grdgradient`; append
135+
**+a**\ *azimuth*, **+n**\ *args*, and **+m**\ *ambient* to specify
136+
azimuth, intensity, and ambient arguments for that module, or just give
137+
**+d** to select the default arguments (``+a-45+nt1+m0``). If you want
138+
a more specific intensity scenario then run :meth:`pygmt.grdgradient`
139+
separately first. If we should derive intensities from another file
140+
than grid, specify the file with suitable modifiers [Default is no
141+
illumination]. Note: If the input data is an *image* then an
142+
*intensfile* or constant *intensity* must be provided.
132143
{J}
133144
monochrome : bool
134145
Force conversion to monochrome image using the (television) YIQ
@@ -153,6 +164,12 @@ def grdimage(self, grid, **kwargs):
153164
kwargs = self._preprocess(**kwargs) # pylint: disable=protected-access
154165
with Session() as lib:
155166
file_context = lib.virtualfile_from_data(check_kind="raster", data=grid)
156-
with file_context as fname:
167+
with contextlib.ExitStack() as stack:
168+
# shading using an xr.DataArray
169+
if "I" in kwargs and data_kind(kwargs["I"]) == "grid":
170+
shading_context = lib.virtualfile_from_grid(kwargs["I"])
171+
kwargs["I"] = stack.enter_context(shading_context)
172+
173+
fname = stack.enter_context(file_context)
157174
arg_str = " ".join([fname, build_arg_string(kwargs)])
158175
lib.call_module("grdimage", arg_str)

pygmt/tests/test_grdimage.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,26 @@ def test_grdimage_shading_xarray(grid, shading):
117117
return fig_ref, fig_test
118118

119119

120+
@pytest.mark.xfail(
121+
reason="Incorrect scaling of geo CPT on xarray.DataArray grdimage plot."
122+
"See https://github.com/GenericMappingTools/gmt/issues/5294",
123+
)
124+
@check_figures_equal()
125+
def test_grdimage_grid_and_shading_with_xarray(grid, xrgrid):
126+
"""
127+
Test that shading works well when xarray.DataArray is input to both the
128+
``grid`` and ``shading`` arguments.
129+
"""
130+
fig_ref, fig_test = Figure(), Figure()
131+
fig_ref.grdimage(
132+
grid="@earth_relief_01d_g", region="GL", cmap="geo", shading=xrgrid, verbose="i"
133+
)
134+
fig_ref.colorbar()
135+
fig_test.grdimage(grid=grid, region="GL", cmap="geo", shading=xrgrid, verbose="i")
136+
fig_test.colorbar()
137+
return fig_ref, fig_test
138+
139+
120140
def test_grdimage_fails():
121141
"""
122142
Should fail for unrecognized input.

0 commit comments

Comments
 (0)