1515__doctest_skip__ = ["grdfilter" ]
1616
1717
18+ def _alias_option_F ( # noqa: N802
19+ filter = None , # noqa: A002
20+ width = None ,
21+ highpass = False ,
22+ ):
23+ """
24+ Helper function to create the alias list for the -F option.
25+
26+ Examples
27+ --------
28+ >>> def parse(**kwargs):
29+ ... return AliasSystem(F=_alias_option_F(**kwargs)).get("F")
30+ >>> parse(filter="boxcar", width=2.0)
31+ 'b2.0'
32+ >>> parse(filter="cosarch", width=(5, 10))
33+ 'c5/10'
34+ >>> parse(filter="gaussian", width=100, highpass=True)
35+ 'g100+h'
36+ """
37+ _filter_mapping = {
38+ "boxcar" : "b" ,
39+ "cosarch" : "c" ,
40+ "gaussian" : "g" ,
41+ "minall" : "l" ,
42+ "minpos" : "L" ,
43+ "maxall" : "u" ,
44+ "maxneg" : "U" ,
45+ }
46+ # Check if the 'filter' parameter is using the old GMT command string syntax.
47+ _old_filter_syntax = isinstance (filter , str ) and filter not in _filter_mapping
48+
49+ if _old_filter_syntax :
50+ kwdict = {"width" : width , "highpass" : highpass }
51+ if any (v is not None and v is not False for v in kwdict .values ()):
52+ raise GMTParameterError (
53+ conflicts_with = ("filter" , kwdict .keys ()),
54+ reason = "'filter' is specified using the unrecommended GMT command string syntax." ,
55+ )
56+ return Alias (filter , name = "filter" ) # Deprecated raw GMT command string.
57+
58+ if filter is None or width is None :
59+ raise GMTParameterError (required = ["filter" , "width" ])
60+
61+ return [
62+ Alias (filter , name = "filter" , mapping = _filter_mapping ),
63+ Alias (width , name = "width" , sep = "/" , size = 2 ),
64+ Alias (highpass , name = "highpass" , prefix = "+h" ),
65+ ]
66+
67+
1868@fmt_docstring
19- @use_alias (F = "filter" , f = "coltypes" )
20- def grdfilter (
69+ @use_alias (f = "coltypes" )
70+ def grdfilter ( # noqa: PLR0913
2171 grid : PathLike | xr .DataArray ,
2272 outgrid : PathLike | None = None ,
73+ filter : Literal [ # noqa: A002
74+ "boxcar" , "cosarch" , "gaussian" , "minall" , "minpos" , "maxall" , "maxneg"
75+ ]
76+ | str
77+ | None = None ,
78+ width : float | Sequence [float ] | None = None ,
79+ highpass : bool = False ,
2380 distance : Literal [
2481 "pixel" ,
2582 "cartesian" ,
@@ -40,7 +97,7 @@ def grdfilter(
4097 cores : int | bool = False ,
4198 ** kwargs ,
4299) -> xr .DataArray | None :
43- r """
100+ """
44101 Filter a grid in the space (or time) domain.
45102
46103 Filter a grid file in the space (or time) domain using one of the selected
@@ -57,6 +114,7 @@ def grdfilter(
57114
58115 $aliases
59116 - D = distance
117+ - F = filter, width, **+h**: highpass
60118 - G = outgrid
61119 - I = spacing
62120 - N = nans
@@ -70,19 +128,35 @@ def grdfilter(
70128 ----------
71129 $grid
72130 $outgrid
73- filter : str
74- **b**\|\ **c**\|\ **g**\|\ **o**\|\ **m**\|\ **p**\|\ **h**\ *width*\
75- [/*width2*\][*modifiers*].
76- Name of the filter type you wish to apply, followed by the *width*:
77-
78- - **b**: Box Car
79- - **c**: Cosine Arch
80- - **g**: Gaussian
81- - **o**: Operator
82- - **m**: Median
83- - **p**: Maximum Likelihood probability
84- - **h**: Histogram
131+ filter
132+ The filter type. Choose among convolution and non-convolution filters.
133+
134+ Convolution filters include:
85135
136+ - ``"boxcar"``: All weights are equal.
137+ - ``"cosarch"``: Weights follow a cosine arch curve.
138+ - ``"gaussian"``: Weights are given by the Gaussian function, where filter width
139+ is 6 times the conventional Gaussian sigma.
140+
141+ Non-convolution filters include:
142+
143+ - ``"minall"``: Return minimum of all values.
144+ - ``"minpos"``: Return minimum of all positive values only.
145+ - ``"maxall"``: Return maximum of all values.
146+ - ``"maxneg"``: Return maximum of all negative values only.
147+
148+ **Note**: There are still a few other filter types available in GMT (e.g.,
149+ histogram and mode filters), but they are not implemented in PyGMT yet. As a
150+ workaround, pass the raw GMT command string to this parameter to use these other
151+ filter types. Refer to :gmt-docs:`grdfilter.html#f` for the full syntax of this
152+ parameter.
153+ width
154+ The full diameter width of the filter. It can be a single value for an isotropic
155+ filter, or a pair of values for a rectangular filter (width in x- and
156+ y-directions, requiring ``distance`` be either ``"pixel"`` or ``"cartesian"``).
157+ highpass
158+ By default, the filter is a low-pass filter. If True, then the filter is a
159+ high-pass filter. [Default is ``False``].
86160 distance
87161 Determine how grid (*x, y*) relates to filter *width* and how distances are
88162 calculated. Valid values are list below. The first four options are fastest
@@ -159,11 +233,12 @@ def grdfilter(
159233 --------
160234 >>> from pathlib import Path
161235 >>> import pygmt
162- >>> # Apply a median filter of 600 km (full width) to the @earth_relief_30m_g grid
236+ >>> # Apply a gaussian filter of 600 km (full width) to the @earth_relief_30m_g grid
163237 >>> # and return a filtered grid (saved as netCDF file).
164238 >>> pygmt.grdfilter(
165239 ... grid="@earth_relief_30m_g",
166- ... filter="m600",
240+ ... filter="gaussian",
241+ ... width=600,
167242 ... distance="geo_spherical",
168243 ... region=[150, 250, 10, 40],
169244 ... spacing=0.5,
@@ -173,10 +248,13 @@ def grdfilter(
173248 >>> # Apply a Gaussian smoothing filter of 600 km to the input DataArray and return
174249 >>> # a filtered DataArray with the smoothed grid.
175250 >>> grid = pygmt.datasets.load_earth_relief()
176- >>> smoothed = pygmt.grdfilter(grid=grid, filter="g600", distance="geo_spherical")
251+ >>> smoothed = pygmt.grdfilter(
252+ ... grid=grid, filter="gaussian", width=600, distance="geo_spherical"
253+ ... )
177254 """
178255 if kwargs .get ("D" , distance ) is None :
179256 raise GMTParameterError (required = "distance" )
257+ # filter is also required but will be checked in _alias_option_F.
180258
181259 aliasdict = AliasSystem (
182260 D = Alias (
@@ -192,6 +270,11 @@ def grdfilter(
192270 "geo_mercator" : 5 ,
193271 },
194272 ),
273+ F = _alias_option_F (
274+ filter = filter ,
275+ width = width ,
276+ highpass = highpass ,
277+ ),
195278 I = Alias (spacing , name = "spacing" , sep = "/" , size = 2 ),
196279 N = Alias (
197280 nans , name = "nans" , mapping = {"ignore" : "i" , "replace" : "r" , "preserve" : "p" }
0 commit comments