44
55import warnings
66
7+ import numpy as np
78import xarray as xr
89from pygmt .clib import Session
910from pygmt .exceptions import GMTInvalidInput
1819__doctest_skip__ = ["grdfill" ]
1920
2021
22+ def _validate_params (
23+ constantfill = None ,
24+ gridfill = None ,
25+ neighborfill = None ,
26+ splinefill = None ,
27+ inquire = False ,
28+ mode = None ,
29+ ):
30+ """
31+ Validate the fill/inquire parameters.
32+
33+ >>> _validate_params(constantfill=20.0)
34+ >>> _validate_params(inquire=True)
35+ >>> _validate_params(mode="c20.0")
36+ >>> _validate_params(constantfill=20.0, gridfill="bggrid.nc")
37+ Traceback (most recent call last):
38+ ...
39+ pygmt.exceptions.GMTInvalidInput: Parameters ... are mutually exclusive.
40+ >>> _validate_params(constantfill=20.0, inquire=True)
41+ Traceback (most recent call last):
42+ ...
43+ pygmt.exceptions.GMTInvalidInput: Parameters ... are mutually exclusive.
44+ >>> _validate_params()
45+ Traceback (most recent call last):
46+ ...
47+ pygmt.exceptions.GMTInvalidInput: Need to specify parameter ...
48+ """
49+ _fill_params = "'constantfill'/'gridfill'/'neighborfill'/'splinefill'"
50+ # The deprecated 'mode' parameter is given.
51+ if mode is not None :
52+ msg = (
53+ "The 'mode' parameter is deprecated since v0.15.0 and will be removed in "
54+ f"v0.19.0. Use { _fill_params } instead."
55+ )
56+ warnings .warn (msg , FutureWarning , stacklevel = 2 )
57+
58+ n_given = sum (
59+ param is not None and param is not False
60+ for param in [constantfill , gridfill , neighborfill , splinefill , inquire , mode ]
61+ )
62+ if n_given > 1 : # More than one mutually exclusive parameter is given.
63+ msg = f"Parameters { _fill_params } /'inquire'/'mode' are mutually exclusive."
64+ raise GMTInvalidInput (msg )
65+ if n_given == 0 : # No parameters are given.
66+ msg = (
67+ f"Need to specify parameter { _fill_params } for filling holes or "
68+ "'inquire' for inquiring the bounds of each hole."
69+ )
70+ raise GMTInvalidInput (msg )
71+
72+
2173def _parse_fill_mode (
2274 constantfill = None , gridfill = None , neighborfill = None , splinefill = None
2375) -> str | None :
@@ -40,19 +92,7 @@ def _parse_fill_mode(
4092 's0.5'
4193 >>> _parse_fill_mode(splinefill=True)
4294 's'
43- >>> _parse_fill_mode(constantfill=20, gridfill="bggrid.nc")
44- Traceback (most recent call last):
45- ...
46- pygmt.exceptions.GMTInvalidInput: The ... parameters are mutually exclusive.
4795 """
48- fill_params = [constantfill , gridfill , neighborfill , splinefill ]
49- if sum (param is not None for param in fill_params ) > 1 :
50- msg = (
51- "The 'constantfill', 'gridfill', 'neighborfill', and 'splinefill' "
52- "parameters are mutually exclusive."
53- )
54- raise GMTInvalidInput (msg )
55-
5696 if constantfill is not None :
5797 return f"c{ constantfill } "
5898 if gridfill is not None :
@@ -66,8 +106,9 @@ def _parse_fill_mode(
66106
67107@fmt_docstring
68108# TODO(PyGMT>=0.19.0): Remove the deprecated 'no_data' parameter.
109+ # TODO(PyGMT>=0.19.0): Remove the deprecated 'mode' parameter.
69110@deprecate_parameter ("no_data" , "hole" , "v0.15.0" , remove_version = "v0.19.0" )
70- @use_alias (A = "mode" , N = "hole" , R = "region" , V = "verbose" , f = "coltypes" )
111+ @use_alias (N = "hole" , R = "region" , V = "verbose" , f = "coltypes" )
71112@kwargs_to_strings (R = "sequence" )
72113def grdfill (
73114 grid : str | xr .DataArray ,
@@ -76,8 +117,10 @@ def grdfill(
76117 gridfill : str | xr .DataArray | None = None ,
77118 neighborfill : float | bool | None = None ,
78119 splinefill : float | bool | None = None ,
120+ inquire : bool = False ,
121+ mode : str | None = None ,
79122 ** kwargs ,
80- ) -> xr .DataArray | None :
123+ ) -> xr .DataArray | np . ndarray | None :
81124 r"""
82125 Interpolate across holes in a grid.
83126
@@ -111,7 +154,11 @@ def grdfill(
111154 hole : float
112155 Set the node value used to identify a point as a member of a hole [Default is
113156 NaN].
114- mode : str
157+ inquire
158+ Output the bounds of each hole. The bounds are returned as a 2-D numpy array in
159+ the form of (west, east, south, north). No grid fill takes place and ``outgrid``
160+ is ignored.
161+ mode
115162 Specify the hole-filling algorithm to use. Choose from **c** for constant fill
116163 and append the constant value, **n** for nearest neighbor (and optionally append
117164 a search radius in pixels [default radius is :math:`r^2 = \sqrt{{ X^2 + Y^2 }}`,
@@ -128,50 +175,62 @@ def grdfill(
128175 Returns
129176 -------
130177 ret
131- Return type depends on whether the ``outgrid`` parameter is set:
178+ If ``inquire`` is ``True``, return the bounds of each hole as a 2-D numpy array.
179+ Otherwise, the return type depends on whether the ``outgrid`` parameter is set:
132180
133181 - :class:`xarray.DataArray` if ``outgrid`` is not set
134182 - ``None`` if ``outgrid`` is set (grid output will be stored in the file set by
135183 ``outgrid``)
136184
137185 Example
138186 -------
187+ Fill holes in a bathymetric grid with a constant value of 20.
139188 >>> import pygmt
140189 >>> # Load a bathymetric grid with missing data
141190 >>> earth_relief_holes = pygmt.datasets.load_sample_data(name="earth_relief_holes")
142191 >>> # Fill the holes with a constant value of 20
143192 >>> filled_grid = pygmt.grdfill(grid=earth_relief_holes, constantfill=20)
193+
194+ Inquire the bounds of each hole.
195+ >>> pygmt.grdfill(grid=earth_relief_holes, inquire=True)
196+ array([[1.83333333, 6.16666667, 3.83333333, 8.16666667],
197+ [6.16666667, 7.83333333, 0.5 , 2.5 ]])
144198 """
145- # TODO(PyGMT>=0.19.0): Remove the deprecated 'mode' parameter.
146- if kwargs .get ("A" ) is not None : # The deprecated 'mode' parameter is given.
147- warnings .warn (
148- "The 'mode' parameter is deprecated since v0.15.0 and will be removed in "
149- "v0.19.0. Use 'constantfill'/'gridfill'/'neighborfill'/'splinefill' "
150- "instead." ,
151- FutureWarning ,
152- stacklevel = 1 ,
153- )
154- else :
155- # Determine the -A option from the fill parameters.
156- kwargs ["A" ] = _parse_fill_mode (constantfill , gridfill , neighborfill , splinefill )
199+ # Validate the fill/inquire parameters.
200+ _validate_params (constantfill , gridfill , neighborfill , splinefill , inquire , mode )
157201
158- if kwargs .get ("A" ) is None and kwargs .get ("L" ) is None :
159- msg = "At least parameter 'mode' or 'L' must be specified."
160- raise GMTInvalidInput (msg )
202+ # Parse the fill parameters and return the appropriate string for the -A option.
203+ kwargs ["A" ] = (
204+ _parse_fill_mode (constantfill , gridfill , neighborfill , splinefill )
205+ if mode is None
206+ else mode
207+ )
161208
162209 with Session () as lib :
163- with (
164- lib .virtualfile_in (check_kind = "raster" , data = grid ) as vingrd ,
165- lib .virtualfile_in (
166- check_kind = "raster" , data = gridfill , required_data = False
167- ) as vbggrd ,
168- lib .virtualfile_out (kind = "grid" , fname = outgrid ) as voutgrd ,
169- ):
170- if gridfill is not None :
171- # Fill by a grid. Append the actual or virtual grid file name.
172- kwargs ["A" ] = f"g{ vbggrd } "
173- kwargs ["G" ] = voutgrd
174- lib .call_module (
175- module = "grdfill" , args = build_arg_list (kwargs , infile = vingrd )
176- )
177- return lib .virtualfile_to_raster (vfname = voutgrd , outgrid = outgrid )
210+ with lib .virtualfile_in (check_kind = "raster" , data = grid ) as vingrd :
211+ if inquire : # Inquire mode.
212+ kwargs ["L" ] = True
213+ with lib .virtualfile_out (kind = "dataset" ) as vouttbl :
214+ lib .call_module (
215+ module = "grdfill" ,
216+ args = build_arg_list (kwargs , infile = vingrd , outfile = vouttbl ),
217+ )
218+ return lib .virtualfile_to_dataset (
219+ vfname = vouttbl , output_type = "numpy"
220+ )
221+
222+ # Fill mode.
223+ with (
224+ lib .virtualfile_in (
225+ check_kind = "raster" , data = gridfill , required_data = False
226+ ) as vbggrd ,
227+ lib .virtualfile_out (kind = "grid" , fname = outgrid ) as voutgrd ,
228+ ):
229+ if gridfill is not None :
230+ # Fill by a grid. Append the actual or virtual grid file name.
231+ kwargs ["A" ] = f"g{ vbggrd } "
232+ kwargs ["G" ] = voutgrd
233+ lib .call_module (
234+ module = "grdfill" , args = build_arg_list (kwargs , infile = vingrd )
235+ )
236+ return lib .virtualfile_to_raster (vfname = voutgrd , outgrid = outgrid )
0 commit comments