Skip to content
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

Add missing aliases to pygmt.grdgradient #1515

Merged
merged 20 commits into from
Oct 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
91 changes: 70 additions & 21 deletions pygmt/src/grdgradient.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@
D="direction",
E="radiance",
G="outgrid",
N="normalize",
Q="tiles",
R="region",
S="slope_file",
V="verbose",
f="coltypes",
n="interpolation",
willschlitzer marked this conversation as resolved.
Show resolved Hide resolved
)
@kwargs_to_strings(A="sequence", E="sequence", R="sequence")
Expand All @@ -49,35 +53,38 @@ def grdgradient(grid, **kwargs):
Azimuthal direction for a directional derivative; *azim* is the
angle in the x,y plane measured in degrees positive clockwise from
north (the +y direction) toward east (the +x direction). The
negative of the directional derivative, -[dz/dx\*sin(*azim*) +
dz/dy\*cos(\ *azim*)], is found; negation yields positive values
when the slope of z(x,y) is downhill in the *azim* direction, the
correct sense for shading the illumination of an image by a light
source above the x,y plane shining from the *azim* direction.
Optionally, supply two azimuths, *azim*/*azim2*, in which case the
gradients in each of these directions are calculated and the one
larger in magnitude is retained; this is useful for illuminating data
with two directions of lineated structures, e.g., *0*/*270*
negative of the directional derivative,
:math:`-(\frac{{dz}}{{dx}}\sin(\mbox{{azim}}) + \
\frac{{dz}}{{dy}}\cos(\mbox{{azim}}))`, is found; negation yields
positive values when the slope of :math:`z(x,y)` is downhill in the
*azim* direction, the correct sense for shading the illumination of an
image by a light source above the x,y plane shining from the *azim*
direction. Optionally, supply two azimuths, *azim*/*azim2*, in which
case the gradients in each of these directions are calculated and the
one larger in magnitude is retained; this is useful for illuminating
data with two directions of lineated structures, e.g., *0*/*270*
illuminates from the north (top) and west (left). Finally, if *azim*
is a file it must be a grid of the same domain, spacing and
registration as *grid* that will update the azimuth at each output
node when computing the directional derivatives.
direction : str
[**a**][**c**][**o**][**n**].
Find the direction of the positive (up-slope) gradient of the data.
To instead find the aspect (the down-slope direction), use **a**.
By default, directions are measured clockwise from north, as *azim*
in ``azimuth``. Append **c** to use conventional Cartesian angles
measured counterclockwise from the positive x (east) direction.
Append **o** to report orientations (0-180) rather than
directions (0-360). Append **n** to add 90 degrees to all angles
(e.g., to give local strikes of the surface).
The following options are supported:

- **a** - Find the aspect (i.e., the down-slope direction)
- **c** - Use the conventional Cartesian angles measured
counterclockwise from the positive x (east) direction.
- **o** - Report orientations (0-180) rather than directions (0-360).
- **n** - Add 90 degrees to all angles (e.g., to give local strikes of
the surface).
radiance : str or list
[**m**\|\ **s**\|\ **p**]\ *azim/elev*\ [**+a**\ *ambient*][**+d**\
*diffuse*][**+p**\ *specular*][**+s**\ *shine*].
Compute Lambertian radiance appropriate to use with ``grdimage``
and ``grdview``. The Lambertian Reflection assumes an ideal surface
that reflects all the light that strikes it and the surface appears
Compute Lambertian radiance appropriate to use with
:doc:`pygmt.Figure.grdimage` and :doc:`pygmt.Figure.grdview`. The
Lambertian Reflection assumes an ideal surface that reflects all the
light that strikes it and the surface appears
equally bright from all viewing directions. Here, *azim* and *elev* are
the azimuth and elevation of the light vector. Optionally, supply
*ambient* [0.55], *diffuse* [0.6], *specular* [0.4], or *shine* [10],
Expand All @@ -86,11 +93,51 @@ def grdgradient(grid, **kwargs):
simpler Lambertian algorithm. Note that with this form you only have
to provide azimuth and elevation. Alternatively, use **p** for
the Peucker piecewise linear approximation (simpler but faster
algorithm; in this case the *azim* and *elev* are hardwired to 315
algorithm; in this case *azim* and *elev* are hardwired to 315
and 45 degrees. This means that even if you provide other values
they will be ignored.)
they will be ignored.).
normalize : str or bool
[**e**\|\ **t**][*amp*][**+a**\ *ambient*][**+s**\ *sigma*]\
[**+o**\ *offset*].
The actual gradients :math:`g` are offset and scaled to produce
normalized gradients :math:`g_n` with a maximum output magnitude of
*amp*. If *amp* is not given, default *amp* = 1. If *offset* is not
given, it is set to the average of :math:`g`. The following forms are
supported:

- **True** - Normalize using :math:`g_n = \mbox{{amp}}\
(\frac{{g - \mbox{{offset}}}}{{max(|g - \mbox{{offset}}|)}})`
- **e** - Normalize using a cumulative Laplace distribution yielding:
:math:`g_n = \mbox{{amp}}(1 - \
\exp{{(\sqrt{{2}}\frac{{g - \mbox{{offset}}}}{{\sigma}}))}}`, where
:math:`\sigma` is estimated using the L1 norm of
:math:`(g - \mbox{{offset}})` if it is not given.
- **t** - Normalize using a cumulative Cauchy distribution yielding:
:math:`g_n = \
\frac{{2(\mbox{{amp}})}}{{\pi}}(\tan^{{-1}}(\frac{{g - \
\mbox{{offset}}}}{{\sigma}}))` where :math:`\sigma` is estimated
using the L2 norm of :math:`(g - \mbox{{offset}})` if it is not
given.

As a final option, you may add **+a**\ *ambient* to add *ambient* to
all nodes after gradient calculations are completed.
tiles : str
**c**\|\ **r**\|\ **R**.
Controls how normalization via ``normalize`` is carried out. When
multiple grids should be normalized the same way (i.e., with the same
*offset* and/or *sigma*),
we must pass these values via ``normalize``. However, this is
inconvenient if we compute these values from a grid. Use **c** to
save the results of *offset* and *sigma* to a statistics file; if
grid output is not needed for this run then do not specify
``outgrid``. For subsequent runs, just use **r** to read these
values. Using **R** will read then delete the statistics file.
{R}
slope_file : str
Name of output grid file with scalar magnitudes of gradient vectors.
Requires ``direction`` but makes ``outgrid`` optional.
{V}
{f}
{n}
willschlitzer marked this conversation as resolved.
Show resolved Hide resolved

Returns
Expand All @@ -103,6 +150,8 @@ def grdgradient(grid, **kwargs):
``outgrid``)
"""
with GMTTempFile(suffix=".nc") as tmpfile:
if "Q" in kwargs and "N" not in kwargs:
raise GMTInvalidInput("""Must specify normalize if tiles is specified.""")
maxrjones marked this conversation as resolved.
Show resolved Hide resolved
if not args_in_kwargs(args=["A", "D", "E"], kwargs=kwargs):
raise GMTInvalidInput(
"""At least one of the following parameters must be specified:
Expand Down
11 changes: 8 additions & 3 deletions pygmt/tests/test_grdgradient.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,13 @@ def test_grdgradient_no_outgrid(grid):

def test_grdgradient_fails(grid):
"""
Check that grdgradient fails correctly when neither of azimuth, direction
or radiance is given.
Check that grdgradient fails correctly.

Check that grdgradient fails correctly when `tiles` is specified but
normalize is not.
"""
with pytest.raises(GMTInvalidInput):
grdgradient(grid=grid)
grdgradient(grid=grid) # fails without required arguments
with pytest.raises(GMTInvalidInput):
# failes when tiles is specified but not normalize
grdgradient(grid=grid, azimuth=10, direction="c", tiles="c")