Skip to content

Commit 2291371

Browse files
carocamargoweiji14seisman
authored
Wrap grdfilter (#616)
Wrapping the grdfilter function which "Filters a grid in the space (or time) domain" under gridops.py. Original GMT documentation can be found at https://docs.generic-mapping-tools.org/6.1/grdfilter.html. Aliased distance (D), filter (F), outgrid (G), spacing (I), nans (N), region (R), toggle (T), verbose (V). Also added two usage examples in the doctest. Co-authored-by: Wei Ji <[email protected]> Co-authored-by: Dongdong Tian <[email protected]>
1 parent d313015 commit 2291371

File tree

3 files changed

+143
-1
lines changed

3 files changed

+143
-1
lines changed

doc/api/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ Operations on grids:
7171
:toctree: generated
7272

7373
grdcut
74+
grdfilter
7475
grdtrack
7576

7677
Crossover analysis with x2sys:

pygmt/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from .sampling import grdtrack
2020
from .mathops import makecpt
2121
from .modules import GMTDataArrayAccessor, config, info, grdinfo, which
22-
from .gridops import grdcut
22+
from .gridops import grdcut, grdfilter
2323
from .x2sys import x2sys_init, x2sys_cross
2424
from . import datasets
2525

pygmt/gridops.py

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,144 @@ def grdcut(grid, **kwargs):
116116
result = None # if user sets an outgrid, return None
117117

118118
return result
119+
120+
121+
@fmt_docstring
122+
@use_alias(
123+
D="distance",
124+
F="filter",
125+
G="outgrid",
126+
I="spacing",
127+
N="nans",
128+
R="region",
129+
T="toggle",
130+
V="verbose",
131+
)
132+
@kwargs_to_strings(R="sequence")
133+
def grdfilter(grid, **kwargs):
134+
"""
135+
Filter a grid in the space (or time) domain.
136+
137+
Filter a grid file in the time domain using one of the selected convolution
138+
or non-convolution isotropic or rectangular filters and compute distances
139+
using Cartesian or Spherical geometries. The output grid file can
140+
optionally be generated as a sub-region of the input (via *region*) and/or
141+
with new increment (via *spacing*) or registration (via *toggle*). In this
142+
way, one may have "extra space" in the input data so that the edges will
143+
not be used and the output can be within one half-width of the input edges.
144+
If the filter is low-pass, then the output may be less frequently sampled
145+
than the input.
146+
147+
Full option list at :gmt-docs:`grdfilter.html`
148+
149+
{aliases}
150+
151+
Parameters
152+
----------
153+
grid : str or xarray.DataArray
154+
The file name of the input grid or the grid loaded as a DataArray.
155+
outgrid : str or None
156+
The name of the output netCDF file with extension .nc to store the grid
157+
in.
158+
filter : str
159+
``xwidth[/width2][modifiers]``.
160+
Name of filter type you which to apply, followed by the width
161+
b: Box Car; c: Cosine Arch; g: Gaussian; o: Operator; m: Median;
162+
p: Maximum Likelihood probability; h: histogram
163+
Example: F='m600' for a median filter with width of 600
164+
distance : str
165+
Distance *flag* tells how grid (x,y) relates to filter width as
166+
follows:
167+
168+
p: grid (px,py) with *width* an odd number of pixels; Cartesian
169+
distances.
170+
171+
0: grid (x,y) same units as *width*, Cartesian distances.
172+
173+
1: grid (x,y) in degrees, *width* in kilometers, Cartesian distances.
174+
175+
2: grid (x,y) in degrees, *width* in km, dx scaled by cos(middle y),
176+
Cartesian distances.
177+
178+
The above options are fastest because they allow weight matrix to be
179+
computed only once. The next three options are slower because they
180+
recompute weights for each latitude.
181+
182+
3: grid (x,y) in degrees, *width* in km, dx scaled by cosine(y),
183+
Cartesian distance calculation.
184+
185+
4: grid (x,y) in degrees, *width* in km, Spherical distance
186+
calculation.
187+
188+
5: grid (x,y) in Mercator ``projection='m1'`` img units, *width* in km,
189+
Spherical distance calculation.
190+
191+
spacing : str
192+
``xinc[+e|n][/yinc[+e|n]]``.
193+
x_inc [and optionally y_inc] is the grid spacing.
194+
nans : str or float
195+
``i|p|r``.
196+
Determine how NaN-values in the input grid affects the filtered output.
197+
{R}
198+
toggle : bool
199+
Toggle the node registration for the output grid so as to become the
200+
opposite of the input grid. [Default gives the same registration as the
201+
input grid].
202+
{V}
203+
204+
Returns
205+
-------
206+
ret: xarray.DataArray or None
207+
Return type depends on whether the *outgrid* parameter is set:
208+
- xarray.DataArray if *outgrid* is not set
209+
- None if *outgrid* is set (grid output will be stored in *outgrid*)
210+
211+
Examples
212+
--------
213+
>>> import os
214+
>>> import pygmt
215+
216+
>>> # Apply a filter of 600km (full width) to the @earth_relief_30m file
217+
>>> # and return a filtered field (saved as netcdf)
218+
>>> pygmt.grdfilter(
219+
... grid="@earth_relief_30m",
220+
... filter="m600",
221+
... distance="4",
222+
... region=[150, 250, 10, 40],
223+
... spacing=0.5,
224+
... outgrid="filtered_pacific.nc",
225+
... )
226+
>>> os.remove("filtered_pacific.nc") # cleanup file
227+
228+
>>> # Apply a gaussian smoothing filter of 600 km in the input data array,
229+
>>> # and returns a filtered data array with the smoothed field.
230+
>>> grid = pygmt.datasets.load_earth_relief()
231+
>>> smooth_field = pygmt.grdfilter(grid=grid, filter="g600", distance="4")
232+
233+
"""
234+
kind = data_kind(grid)
235+
236+
with GMTTempFile(suffix=".nc") as tmpfile:
237+
with Session() as lib:
238+
if kind == "file":
239+
file_context = dummy_context(grid)
240+
elif kind == "grid":
241+
file_context = lib.virtualfile_from_grid(grid)
242+
else:
243+
raise GMTInvalidInput("Unrecognized data type: {}".format(type(grid)))
244+
245+
with file_context as infile:
246+
if "G" not in kwargs.keys(): # if outgrid is unset, output to tempfile
247+
kwargs.update({"G": tmpfile.name})
248+
outgrid = kwargs["G"]
249+
arg_str = " ".join([infile, build_arg_string(kwargs)])
250+
lib.call_module("grdfilter", arg_str)
251+
252+
if outgrid == tmpfile.name: # if user did not set outgrid, return DataArray
253+
with xr.open_dataarray(outgrid) as dataarray:
254+
result = dataarray.load()
255+
_ = result.gmt # load GMTDataArray accessor information
256+
else:
257+
result = None # if user sets an outgrid, return None
258+
259+
return result

0 commit comments

Comments
 (0)