Skip to content

Commit 75c3a51

Browse files
Merge branch 'main' into wrap-grdsample
2 parents 09a43de + 097c807 commit 75c3a51

File tree

5 files changed

+146
-0
lines changed

5 files changed

+146
-0
lines changed

doc/api/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ Operations on grids:
9696
grdgradient
9797
grdsample
9898
grdtrack
99+
xyz2grd
99100

100101
Crossover analysis with x2sys:
101102

pygmt/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
which,
4949
x2sys_cross,
5050
x2sys_init,
51+
xyz2grd,
5152
)
5253

5354
# Get semantic version through setuptools-scm

pygmt/src/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,4 @@
4242
from pygmt.src.wiggle import wiggle
4343
from pygmt.src.x2sys_cross import x2sys_cross
4444
from pygmt.src.x2sys_init import x2sys_init
45+
from pygmt.src.xyz2grd import xyz2grd

pygmt/src/xyz2grd.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""
2+
xyz2grd - Convert data table to a grid.
3+
"""
4+
import xarray as xr
5+
from pygmt.clib import Session
6+
from pygmt.helpers import (
7+
GMTTempFile,
8+
build_arg_string,
9+
fmt_docstring,
10+
kwargs_to_strings,
11+
use_alias,
12+
)
13+
14+
15+
@fmt_docstring
16+
@use_alias(
17+
G="outgrid",
18+
I="spacing",
19+
R="region",
20+
V="verbose",
21+
)
22+
@kwargs_to_strings(R="sequence")
23+
def xyz2grd(table, **kwargs):
24+
"""
25+
Create a grid file from table data.
26+
27+
xyz2grd reads one or more z or xyz tables and creates a binary grid file.
28+
xyz2grd will report if some of the nodes are not filled in with data. Such
29+
unconstrained nodes are set to a value specified by the user [Default is
30+
NaN]. Nodes with more than one value will be set to the mean value.
31+
32+
Full option list at :gmt-docs:`xyz2grd.html`
33+
34+
Parameters
35+
----------
36+
table : str or {table-like}
37+
Pass in either a file name to an ASCII data table, a 1D/2D
38+
{table-classes}.
39+
40+
outgrid : str or None
41+
Optional. The name of the output netCDF file with extension .nc to
42+
store the grid in.
43+
{I}
44+
{R}
45+
{V}
46+
47+
Returns
48+
-------
49+
ret: xarray.DataArray or None
50+
Return type depends on whether the ``outgrid`` parameter is set:
51+
52+
- :class:`xarray.DataArray`: if ``outgrid`` is not set
53+
- None if ``outgrid`` is set (grid output will be stored in file set by
54+
``outgrid``)```
55+
"""
56+
with GMTTempFile(suffix=".nc") as tmpfile:
57+
with Session() as lib:
58+
file_context = lib.virtualfile_from_data(check_kind="vector", data=table)
59+
with file_context as infile:
60+
if "G" not in kwargs.keys(): # if outgrid is unset, output to tempfile
61+
kwargs.update({"G": tmpfile.name})
62+
outgrid = kwargs["G"]
63+
arg_str = build_arg_string(kwargs)
64+
arg_str = " ".join([infile, arg_str])
65+
lib.call_module("xyz2grd", arg_str)
66+
67+
if outgrid == tmpfile.name: # if user did not set outgrid, return DataArray
68+
with xr.open_dataarray(outgrid) as dataarray:
69+
result = dataarray.load()
70+
_ = result.gmt # load GMTDataArray accessor information
71+
else:
72+
result = None # if user sets an outgrid, return None
73+
74+
return result

pygmt/tests/test_xyz2grd.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""
2+
Tests for xyz2grd.
3+
"""
4+
import os
5+
6+
import numpy as np
7+
import pytest
8+
import xarray as xr
9+
from pygmt import grdinfo, xyz2grd
10+
from pygmt.datasets import load_sample_bathymetry
11+
from pygmt.helpers import GMTTempFile
12+
13+
14+
@pytest.fixture(scope="module", name="ship_data")
15+
def fixture_ship_data():
16+
"""
17+
Load the data from the sample bathymetry dataset.
18+
"""
19+
return load_sample_bathymetry()
20+
21+
22+
def test_xyz2grd_input_file():
23+
"""
24+
Run xyz2grd by passing in a filename.
25+
"""
26+
output = xyz2grd(table="@tut_ship.xyz", spacing=5, region=[245, 255, 20, 30])
27+
assert isinstance(output, xr.DataArray)
28+
assert output.gmt.registration == 0 # Gridline registration
29+
assert output.gmt.gtype == 0 # Cartesian type
30+
return output
31+
32+
33+
def test_xyz2grd_input_array(ship_data):
34+
"""
35+
Run xyz2grd by passing in a numpy array.
36+
"""
37+
output = xyz2grd(table=np.array(ship_data), spacing=5, region=[245, 255, 20, 30])
38+
assert isinstance(output, xr.DataArray)
39+
assert output.gmt.registration == 0 # Gridline registration
40+
assert output.gmt.gtype == 0 # Cartesian type
41+
return output
42+
43+
44+
def test_xyz2grd_input_df(ship_data):
45+
"""
46+
Run xyz2grd by passing in a data frame.
47+
"""
48+
output = xyz2grd(table=ship_data, spacing=5, region=[245, 255, 20, 30])
49+
assert isinstance(output, xr.DataArray)
50+
assert output.gmt.registration == 0 # Gridline registration
51+
assert output.gmt.gtype == 0 # Cartesian type
52+
return output
53+
54+
55+
def test_xyz2grd_input_array_file_out(ship_data):
56+
"""
57+
Run xyz2grd by passing in a numpy array and set an outgrid file.
58+
"""
59+
with GMTTempFile(suffix=".nc") as tmpfile:
60+
result = xyz2grd(
61+
table=np.array(ship_data),
62+
spacing=5,
63+
region=[245, 255, 20, 30],
64+
outgrid=tmpfile.name,
65+
)
66+
assert result is None # return value is None
67+
assert os.path.exists(path=tmpfile.name)
68+
result = grdinfo(tmpfile.name, per_column=True).strip()
69+
assert result == "245 255 20 30 -3651.06079102 -352.379486084 5 5 3 3 0 0"

0 commit comments

Comments
 (0)