1515__doctest_skip__ = ["grdgradient" ]
1616
1717
18+ def _alias_option_N ( # noqa: N802
19+ normalize = False ,
20+ norm_amp = None ,
21+ norm_ambient = None ,
22+ norm_sigma = None ,
23+ norm_offset = None ,
24+ ):
25+ """
26+ Create the alias for the N option in grdgradient.
27+ """
28+ _normalize_mapping = {"laplace" : "e" , "cauchy" : "t" }
29+ # Check for old syntax for normalize
30+ if isinstance (normalize , str ) and normalize not in _normalize_mapping :
31+ if any (
32+ v is not None and v is not False
33+ for v in [norm_amp , norm_ambient , norm_sigma , norm_offset ]
34+ ):
35+ msg = (
36+ "Parameter 'normalize' using old syntax with raw GMT CLI string "
37+ "conflicts with parameters 'norm_amp', 'norm_ambient', 'norm_sigma', "
38+ "or 'norm_offset'."
39+ )
40+ raise GMTInvalidInput (msg )
41+ _normalize_mapping = None
42+
43+ return [
44+ Alias (normalize , name = "normalize" , mapping = _normalize_mapping ),
45+ Alias (norm_amp , name = "norm_amp" ),
46+ Alias (norm_ambient , name = "norm_ambient" , prefix = "+a" ),
47+ Alias (norm_sigma , name = "norm_sigma" , prefix = "+s" ),
48+ Alias (norm_offset , name = "norm_offset" , prefix = "+o" ),
49+ ]
50+
51+
1852@fmt_docstring
19- @use_alias (
20- D = "direction" ,
21- N = "normalize" ,
22- Q = "tiles" ,
23- S = "slope_file" ,
24- f = "coltypes" ,
25- n = "interpolation" ,
26- )
27- def grdgradient (
53+ @use_alias (D = "direction" , Q = "tiles" , S = "slope_file" , f = "coltypes" , n = "interpolation" )
54+ def grdgradient ( # noqa: PLR0913
2855 grid : PathLike | xr .DataArray ,
2956 outgrid : PathLike | None = None ,
3057 azimuth : float | Sequence [float ] | None = None ,
3158 radiance : Sequence [float ] | str | None = None ,
59+ normalize : Literal ["laplace" , "cachy" ] | bool = False ,
60+ norm_amp : float | None = None ,
61+ norm_ambient : float | None = None ,
62+ norm_sigma : float | None = None ,
63+ norm_offset : float | None = None ,
3264 region : Sequence [float | str ] | str | None = None ,
3365 verbose : Literal ["quiet" , "error" , "warning" , "timing" , "info" , "compat" , "debug" ]
3466 | bool = False ,
@@ -44,6 +76,8 @@ def grdgradient(
4476
4577 $aliases
4678 - A = azimuth
79+ - N = normalize, norm_amp, **+a**: norm_ambient, **+s**: norm_sigma,
80+ **+o**: norm_offset
4781 - E = radiance
4882 - R = region
4983 - V = verbose
@@ -100,31 +134,37 @@ def grdgradient(
100134 algorithm; in this case *azim* and *elev* are hardwired to 315
101135 and 45 degrees. This means that even if you provide other values
102136 they will be ignored.).
103- normalize : str or bool
104- [**e**\|\ **t**][*amp*][**+a**\ *ambient*][**+s**\ *sigma*]\
105- [**+o**\ *offset*].
106- The actual gradients :math:`g` are offset and scaled to produce
107- normalized gradients :math:`g_n` with a maximum output magnitude of
108- *amp*. If *amp* is not given, default *amp* = 1. If *offset* is not
109- given, it is set to the average of :math:`g`. The following forms are
110- supported:
111-
112- - **True**: Normalize using math:`g_n = \mbox{amp}\
113- (\frac{g - \mbox{offset}}{max(|g - \mbox{offset}|)})`
114- - **e**: Normalize using a cumulative Laplace distribution yielding:
115- :math:`g_n = \mbox{amp}(1 - \
116- \exp{(\sqrt{2}\frac{g - \mbox{offset}}{\sigma}))}`, where
117- :math:`\sigma` is estimated using the L1 norm of
118- :math:`(g - \mbox{offset})` if it is not given.
119- - **t**: Normalize using a cumulative Cauchy distribution yielding:
120- :math:`g_n = \
121- \frac{2(\mbox{amp})}{\pi}(\tan^{-1}(\frac{g - \
122- \mbox{offset}}{\sigma}))` where :math:`\sigma` is estimated
123- using the L2 norm of :math:`(g - \mbox{offset})` if it is not
124- given.
125-
126- As a final option, you may add **+a**\ *ambient* to add *ambient* to
127- all nodes after gradient calculations are completed.
137+ normalize
138+ Normalize the output gradients. Valid values are:
139+
140+ - ``False``: No normalization is done [Default].
141+ - ``True``: Normalize using max absolute value.
142+ - ``"laplace"``: Normalize using cumulative Laplace distribution.
143+ - ``"cauchy"``: Normalize using cumulative Cauchy distribution.
144+
145+ The normalization process is controlled via the additional parameters
146+ ``norm_amp``, ``norm_ambient``, ``norm_sigma``, and ``norm_offset``.
147+
148+ Let :math:`g` denote the actual gradients, :math:`g_n` the normalized gradients,
149+ :math:`a` the maximum output magnitude (``norm_amp``), :math:`o` the offset
150+ value (``norm_offset``), and :math:`\sigma` the sigma value (``norm_sigma``).
151+ The normalization is computed as follows:
152+
153+ - ``True``: :math:`g_n = a (\frac{g - o}{\max(|g - o|)})`
154+ - ``"laplace"``: :math:`g_n = a(1 - \exp(\sqrt{2}\frac{g - o}{\sigma}))`
155+ - ``"cauchy"``: :math:`g_n = \frac{2a}{\pi}\arctan(\frac{g - o}{\sigma})`
156+ norm_amp
157+ Set the maximum output magnitude [Default is 1].
158+ norm_ambient
159+ The ambient value to add to all nodes after gradient calculations are completed
160+ [Default is 0].
161+ norm_offset
162+ The offset value used in the normalization. If not given, it is set to the
163+ average of :math:`g`.
164+ norm_sigma
165+ The *sigma* value used in the Laplace or Cauchy normalization. If not given,
166+ it is estimated from the L1 norm of :math:`g-o` for Laplace or the L2 norm of
167+ :math:`g-o` for Cauchy.
128168 tiles : str
129169 **c**\|\ **r**\|\ **R**.
130170 Control how normalization via ``normalize`` is carried out. When
@@ -181,6 +221,13 @@ def grdgradient(
181221 aliasdict = AliasSystem (
182222 A = Alias (azimuth , name = "azimuth" , sep = "/" , size = 2 ),
183223 E = Alias (radiance , name = "radiance" , sep = "/" , size = 2 ),
224+ N = _alias_option_N (
225+ normalize ,
226+ norm_amp ,
227+ norm_ambient ,
228+ norm_sigma ,
229+ norm_offset ,
230+ ),
184231 ).add_common (
185232 R = region ,
186233 V = verbose ,
0 commit comments