@@ -116,3 +116,144 @@ def grdcut(grid, **kwargs):
116
116
result = None # if user sets an outgrid, return None
117
117
118
118
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