21
21
D = "direction" ,
22
22
E = "radiance" ,
23
23
G = "outgrid" ,
24
+ N = "normalize" ,
25
+ Q = "tiles" ,
24
26
R = "region" ,
27
+ S = "slope_file" ,
25
28
V = "verbose" ,
29
+ f = "coltypes" ,
26
30
n = "interpolation" ,
27
31
)
28
32
@kwargs_to_strings (A = "sequence" , E = "sequence" , R = "sequence" )
@@ -49,35 +53,38 @@ def grdgradient(grid, **kwargs):
49
53
Azimuthal direction for a directional derivative; *azim* is the
50
54
angle in the x,y plane measured in degrees positive clockwise from
51
55
north (the +y direction) toward east (the +x direction). The
52
- negative of the directional derivative, -[dz/dx\*sin(*azim*) +
53
- dz/dy\*cos(\ *azim*)], is found; negation yields positive values
54
- when the slope of z(x,y) is downhill in the *azim* direction, the
55
- correct sense for shading the illumination of an image by a light
56
- source above the x,y plane shining from the *azim* direction.
57
- Optionally, supply two azimuths, *azim*/*azim2*, in which case the
58
- gradients in each of these directions are calculated and the one
59
- larger in magnitude is retained; this is useful for illuminating data
60
- with two directions of lineated structures, e.g., *0*/*270*
56
+ negative of the directional derivative,
57
+ :math:`-(\frac{{dz}}{{dx}}\sin(\mbox{{azim}}) + \
58
+ \frac{{dz}}{{dy}}\cos(\mbox{{azim}}))`, is found; negation yields
59
+ positive values when the slope of :math:`z(x,y)` is downhill in the
60
+ *azim* direction, the correct sense for shading the illumination of an
61
+ image by a light source above the x,y plane shining from the *azim*
62
+ direction. Optionally, supply two azimuths, *azim*/*azim2*, in which
63
+ case the gradients in each of these directions are calculated and the
64
+ one larger in magnitude is retained; this is useful for illuminating
65
+ data with two directions of lineated structures, e.g., *0*/*270*
61
66
illuminates from the north (top) and west (left). Finally, if *azim*
62
67
is a file it must be a grid of the same domain, spacing and
63
68
registration as *grid* that will update the azimuth at each output
64
69
node when computing the directional derivatives.
65
70
direction : str
66
71
[**a**][**c**][**o**][**n**].
67
72
Find the direction of the positive (up-slope) gradient of the data.
68
- To instead find the aspect (the down-slope direction), use **a**.
69
- By default, directions are measured clockwise from north, as *azim*
70
- in ``azimuth``. Append **c** to use conventional Cartesian angles
71
- measured counterclockwise from the positive x (east) direction.
72
- Append **o** to report orientations (0-180) rather than
73
- directions (0-360). Append **n** to add 90 degrees to all angles
74
- (e.g., to give local strikes of the surface).
73
+ The following options are supported:
74
+
75
+ - **a** - Find the aspect (i.e., the down-slope direction)
76
+ - **c** - Use the conventional Cartesian angles measured
77
+ counterclockwise from the positive x (east) direction.
78
+ - **o** - Report orientations (0-180) rather than directions (0-360).
79
+ - **n** - Add 90 degrees to all angles (e.g., to give local strikes of
80
+ the surface).
75
81
radiance : str or list
76
82
[**m**\|\ **s**\|\ **p**]\ *azim/elev*\ [**+a**\ *ambient*][**+d**\
77
83
*diffuse*][**+p**\ *specular*][**+s**\ *shine*].
78
- Compute Lambertian radiance appropriate to use with ``grdimage``
79
- and ``grdview``. The Lambertian Reflection assumes an ideal surface
80
- that reflects all the light that strikes it and the surface appears
84
+ Compute Lambertian radiance appropriate to use with
85
+ :doc:`pygmt.Figure.grdimage` and :doc:`pygmt.Figure.grdview`. The
86
+ Lambertian Reflection assumes an ideal surface that reflects all the
87
+ light that strikes it and the surface appears
81
88
equally bright from all viewing directions. Here, *azim* and *elev* are
82
89
the azimuth and elevation of the light vector. Optionally, supply
83
90
*ambient* [0.55], *diffuse* [0.6], *specular* [0.4], or *shine* [10],
@@ -86,11 +93,51 @@ def grdgradient(grid, **kwargs):
86
93
simpler Lambertian algorithm. Note that with this form you only have
87
94
to provide azimuth and elevation. Alternatively, use **p** for
88
95
the Peucker piecewise linear approximation (simpler but faster
89
- algorithm; in this case the *azim* and *elev* are hardwired to 315
96
+ algorithm; in this case *azim* and *elev* are hardwired to 315
90
97
and 45 degrees. This means that even if you provide other values
91
- they will be ignored.)
98
+ they will be ignored.).
99
+ normalize : str or bool
100
+ [**e**\|\ **t**][*amp*][**+a**\ *ambient*][**+s**\ *sigma*]\
101
+ [**+o**\ *offset*].
102
+ The actual gradients :math:`g` are offset and scaled to produce
103
+ normalized gradients :math:`g_n` with a maximum output magnitude of
104
+ *amp*. If *amp* is not given, default *amp* = 1. If *offset* is not
105
+ given, it is set to the average of :math:`g`. The following forms are
106
+ supported:
107
+
108
+ - **True** - Normalize using :math:`g_n = \mbox{{amp}}\
109
+ (\frac{{g - \mbox{{offset}}}}{{max(|g - \mbox{{offset}}|)}})`
110
+ - **e** - Normalize using a cumulative Laplace distribution yielding:
111
+ :math:`g_n = \mbox{{amp}}(1 - \
112
+ \exp{{(\sqrt{{2}}\frac{{g - \mbox{{offset}}}}{{\sigma}}))}}`, where
113
+ :math:`\sigma` is estimated using the L1 norm of
114
+ :math:`(g - \mbox{{offset}})` if it is not given.
115
+ - **t** - Normalize using a cumulative Cauchy distribution yielding:
116
+ :math:`g_n = \
117
+ \frac{{2(\mbox{{amp}})}}{{\pi}}(\tan^{{-1}}(\frac{{g - \
118
+ \mbox{{offset}}}}{{\sigma}}))` where :math:`\sigma` is estimated
119
+ using the L2 norm of :math:`(g - \mbox{{offset}})` if it is not
120
+ given.
121
+
122
+ As a final option, you may add **+a**\ *ambient* to add *ambient* to
123
+ all nodes after gradient calculations are completed.
124
+ tiles : str
125
+ **c**\|\ **r**\|\ **R**.
126
+ Controls how normalization via ``normalize`` is carried out. When
127
+ multiple grids should be normalized the same way (i.e., with the same
128
+ *offset* and/or *sigma*),
129
+ we must pass these values via ``normalize``. However, this is
130
+ inconvenient if we compute these values from a grid. Use **c** to
131
+ save the results of *offset* and *sigma* to a statistics file; if
132
+ grid output is not needed for this run then do not specify
133
+ ``outgrid``. For subsequent runs, just use **r** to read these
134
+ values. Using **R** will read then delete the statistics file.
92
135
{R}
136
+ slope_file : str
137
+ Name of output grid file with scalar magnitudes of gradient vectors.
138
+ Requires ``direction`` but makes ``outgrid`` optional.
93
139
{V}
140
+ {f}
94
141
{n}
95
142
96
143
Returns
@@ -103,6 +150,8 @@ def grdgradient(grid, **kwargs):
103
150
``outgrid``)
104
151
"""
105
152
with GMTTempFile (suffix = ".nc" ) as tmpfile :
153
+ if "Q" in kwargs and "N" not in kwargs :
154
+ raise GMTInvalidInput ("""Must specify normalize if tiles is specified.""" )
106
155
if not args_in_kwargs (args = ["A" , "D" , "E" ], kwargs = kwargs ):
107
156
raise GMTInvalidInput (
108
157
"""At least one of the following parameters must be specified:
0 commit comments