Skip to content

Commit 2edaa63

Browse files
willschlitzerweiji14seisman
authored
Wrap sphdistance (#1383)
Co-authored-by: Wei Ji <[email protected]> Co-authored-by: Dongdong Tian <[email protected]>
1 parent d5e9704 commit 2edaa63

File tree

5 files changed

+124
-0
lines changed

5 files changed

+124
-0
lines changed

doc/api/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ Operations on grids:
9797
grdproject
9898
grdsample
9999
grdtrack
100+
sphdistance
100101
xyz2grd
101102

102103
Crossover analysis with x2sys:

pygmt/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
grdtrack,
4747
info,
4848
makecpt,
49+
sphdistance,
4950
surface,
5051
which,
5152
x2sys_cross,

pygmt/src/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from pygmt.src.plot3d import plot3d
3636
from pygmt.src.rose import rose
3737
from pygmt.src.solar import solar
38+
from pygmt.src.sphdistance import sphdistance
3839
from pygmt.src.subplot import set_panel, subplot
3940
from pygmt.src.surface import surface
4041
from pygmt.src.text import text_ as text # "text" is an argument within "text_"

pygmt/src/sphdistance.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""
2+
sphdistance - Create Voronoi distance, node,
3+
or natural nearest-neighbor grid on a sphere
4+
"""
5+
from pygmt.clib import Session
6+
from pygmt.exceptions import GMTInvalidInput
7+
from pygmt.helpers import (
8+
GMTTempFile,
9+
build_arg_string,
10+
fmt_docstring,
11+
kwargs_to_strings,
12+
use_alias,
13+
)
14+
from pygmt.io import load_dataarray
15+
16+
17+
@fmt_docstring
18+
@use_alias(
19+
G="outgrid",
20+
I="spacing",
21+
R="region",
22+
V="verbose",
23+
)
24+
@kwargs_to_strings(I="sequence", R="sequence")
25+
def sphdistance(table, **kwargs):
26+
r"""
27+
Create Voroni polygons from lat/lon coordinates.
28+
29+
Reads one or more ASCII [or binary] files (or standard
30+
input) containing lon, lat and performs the construction of Voronoi
31+
polygons. These polygons are then processed to calculate the nearest
32+
distance to each node of the lattice and written to the specified grid.
33+
34+
{aliases}
35+
36+
Parameters
37+
----------
38+
outgrid : str or None
39+
The name of the output netCDF file with extension .nc to store the grid
40+
in.
41+
{I}
42+
{R}
43+
{V}
44+
45+
Returns
46+
-------
47+
ret: xarray.DataArray or None
48+
Return type depends on whether the ``outgrid`` parameter is set:
49+
- :class:`xarray.DataArray` if ``outgrid`` is not set
50+
- None if ``outgrid`` is set (grid output will be stored in file set by
51+
``outgrid``)
52+
"""
53+
if "I" not in kwargs.keys() or "R" not in kwargs.keys():
54+
raise GMTInvalidInput("Both 'region' and 'spacing' must be specified.")
55+
with GMTTempFile(suffix=".nc") as tmpfile:
56+
with Session() as lib:
57+
file_context = lib.virtualfile_from_data(check_kind="vector", data=table)
58+
with file_context as infile:
59+
if "G" not in kwargs.keys(): # if outgrid is unset, output to tempfile
60+
kwargs.update({"G": tmpfile.name})
61+
outgrid = kwargs["G"]
62+
arg_str = build_arg_string(kwargs)
63+
arg_str = " ".join([infile, arg_str])
64+
lib.call_module("sphdistance", arg_str)
65+
66+
return load_dataarray(outgrid) if outgrid == tmpfile.name else None

pygmt/tests/test_sphdistance.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""
2+
Tests for sphdistance.
3+
"""
4+
import os
5+
6+
import numpy as np
7+
import numpy.testing as npt
8+
import pytest
9+
from pygmt import sphdistance
10+
from pygmt.exceptions import GMTInvalidInput
11+
from pygmt.helpers import GMTTempFile
12+
13+
14+
@pytest.fixture(scope="module", name="array")
15+
def fixture_table():
16+
"""
17+
Load the table data.
18+
"""
19+
coords_list = [[85.5, 22.3], [82.3, 22.6], [85.8, 22.4], [86.5, 23.3]]
20+
return np.array(coords_list)
21+
22+
23+
def test_sphdistance_outgrid(array):
24+
"""
25+
Test sphdistance with a set outgrid.
26+
"""
27+
with GMTTempFile(suffix=".nc") as tmpfile:
28+
result = sphdistance(
29+
table=array, outgrid=tmpfile.name, spacing=1, region=[82, 87, 22, 24]
30+
)
31+
assert result is None # return value is None
32+
assert os.path.exists(path=tmpfile.name) # check that outgrid exists
33+
34+
35+
def test_sphdistance_no_outgrid(array):
36+
"""
37+
Test sphdistance with no set outgrid.
38+
"""
39+
temp_grid = sphdistance(table=array, spacing=[1, 2], region=[82, 87, 22, 24])
40+
assert temp_grid.dims == ("lat", "lon")
41+
assert temp_grid.gmt.gtype == 1 # Geographic grid
42+
assert temp_grid.gmt.registration == 0 # Gridline registration
43+
npt.assert_allclose(temp_grid.max(), 232977.546875)
44+
npt.assert_allclose(temp_grid.min(), 0)
45+
npt.assert_allclose(temp_grid.median(), 0)
46+
npt.assert_allclose(temp_grid.mean(), 62469.17)
47+
48+
49+
def test_sphdistance_fails(array):
50+
"""
51+
Check that sphdistance fails correctly when neither increment nor region is
52+
given.
53+
"""
54+
with pytest.raises(GMTInvalidInput):
55+
sphdistance(table=array)

0 commit comments

Comments
 (0)