Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pygmt.triangulate: Refactor to use codes consistent with other wrappers #3073

Merged
merged 3 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
227 changes: 57 additions & 170 deletions pygmt/src/triangulate.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import pandas as pd
from pygmt.clib import Session
from pygmt.exceptions import GMTInvalidInput
from pygmt.helpers import (
GMTTempFile,
build_arg_string,
Expand Down Expand Up @@ -64,109 +63,7 @@ class triangulate: # noqa: N801
w="wrap",
)
@kwargs_to_strings(I="sequence", R="sequence", i="sequence_comma")
def _triangulate(
data=None, x=None, y=None, z=None, *, output_type, outfile=None, **kwargs
):
"""
Delaunay triangulation or Voronoi partitioning and gridding of Cartesian data.

Must provide ``outfile`` or ``outgrid``.

Full option list at :gmt-docs:`triangulate.html`

{aliases}

Parameters
----------
x/y/z : np.ndarray
Arrays of x and y coordinates and values z of the data points.
data : str, {table-like}
Pass in (x, y, z) or (longitude, latitude, elevation) values by
providing a file name to an ASCII data table, a 2-D
{table-classes}.
{projection}
{region}
{spacing}
{outgrid}
The interpolation is performed in the original coordinates, so if
your triangles are close to the poles you are better off projecting
all data to a local coordinate system before using ``triangulate``
(this is true of all gridding routines) or instead select
:gmt-docs:`sphtriangulate <sphtriangulate.html>`.
outfile : str, bool or None
The name of the output ASCII file to store the results of the
histogram equalization in.
output_type: str
Determine the output type. Use "file", "xarray", "pandas", or
"numpy".
{verbose}
{binary}
{nodata}
{find}
{coltypes}
{header}
{incols}
{registration}
Only valid with ``outgrid``.
{skiprows}
{wrap}

Returns
-------
ret: numpy.ndarray or pandas.DataFrame or xarray.DataArray or None
Return type depends on the ``output_type`` parameter:

- numpy.ndarray if ``output_type`` is "numpy"
- pandas.DataFrame if ``output_type`` is "pandas"
- xarray.DataArray if ``output_type`` is "xarray""
- None if ``output_type`` is "file" (output is stored in
``outgrid`` or ``outfile``)
"""
with Session() as lib:
table_context = lib.virtualfile_from_data(
check_kind="vector", data=data, x=x, y=y, z=z, required_z=False
)
with table_context as infile:
# table output if outgrid is unset, else output to outgrid
if (outgrid := kwargs.get("G")) is None:
kwargs.update({">": outfile})
lib.call_module(
module="triangulate", args=build_arg_string(kwargs, infile=infile)
)

if output_type == "file":
return None
if output_type == "xarray":
return load_dataarray(outgrid)

result = pd.read_csv(outfile, sep="\t", header=None)
if output_type == "numpy":
return result.to_numpy()
return result

@staticmethod
@fmt_docstring
def regular_grid( # noqa: PLR0913
data=None,
x=None,
y=None,
z=None,
outgrid=None,
spacing=None,
projection=None,
region=None,
verbose=None,
binary=None,
nodata=None,
find=None,
coltypes=None,
header=None,
incols=None,
registration=None,
skiprows=None,
wrap=None,
**kwargs,
):
def regular_grid(data=None, x=None, y=None, z=None, **kwargs):
"""
Delaunay triangle based gridding of Cartesian data.

Expand All @@ -190,6 +87,8 @@ def regular_grid( # noqa: PLR0913

Full option list at :gmt-docs:`triangulate.html`

{aliases}

Parameters
----------
x/y/z : np.ndarray
Expand Down Expand Up @@ -236,58 +135,45 @@ def regular_grid( # noqa: PLR0913
"""
# Return an xarray.DataArray if ``outgrid`` is not set
with GMTTempFile(suffix=".nc") as tmpfile:
if isinstance(outgrid, str):
output_type = "file"
elif outgrid is None:
output_type = "xarray"
outgrid = tmpfile.name
else:
raise GMTInvalidInput(
"'outgrid' should be a proper file name or `None`"
)

return triangulate._triangulate(
data=data,
x=x,
y=y,
z=z,
output_type=output_type,
outgrid=outgrid,
spacing=spacing,
projection=projection,
region=region,
verbose=verbose,
binary=binary,
nodata=nodata,
find=find,
coltypes=coltypes,
header=header,
incols=incols,
registration=registration,
skiprows=skiprows,
wrap=wrap,
**kwargs,
)
with Session() as lib:
with lib.virtualfile_from_data(
check_kind="vector", data=data, x=x, y=y, z=z, required_z=False
) as vintbl:
if (outgrid := kwargs.get("G")) is None:
kwargs["G"] = outgrid = tmpfile.name # output to tmpfile
lib.call_module(
module="triangulate",
args=build_arg_string(kwargs, infile=vintbl),
)

return load_dataarray(outgrid) if outgrid == tmpfile.name else None

@staticmethod
@fmt_docstring
def delaunay_triples( # noqa: PLR0913
@use_alias(
I="spacing",
J="projection",
R="region",
V="verbose",
b="binary",
d="nodata",
e="find",
f="coltypes",
h="header",
i="incols",
r="registration",
s="skiprows",
w="wrap",
)
@kwargs_to_strings(I="sequence", R="sequence", i="sequence_comma")
def delaunay_triples(
data=None,
x=None,
y=None,
z=None,
*,
output_type="pandas",
outfile=None,
projection=None,
verbose=None,
binary=None,
nodata=None,
find=None,
coltypes=None,
header=None,
incols=None,
skiprows=None,
wrap=None,
**kwargs,
):
"""
Expand All @@ -306,6 +192,8 @@ def delaunay_triples( # noqa: PLR0913

Full option list at :gmt-docs:`triangulate.html`

{aliases}

Parameters
----------
x/y/z : np.ndarray
Expand All @@ -316,7 +204,7 @@ def delaunay_triples( # noqa: PLR0913
{table-classes}.
{projection}
{region}
outfile : str or bool or None
outfile : str or None
The name of the output ASCII file to store the results of the
histogram equalization in.
output_type : str
Expand Down Expand Up @@ -355,26 +243,25 @@ def delaunay_triples( # noqa: PLR0913
"""
output_type = validate_output_table_type(output_type, outfile)

# Return a pandas.DataFrame if ``outfile`` is not set
with GMTTempFile(suffix=".txt") as tmpfile:
if output_type != "file":
outfile = tmpfile.name
return triangulate._triangulate(
data=data,
x=x,
y=y,
z=z,
output_type=output_type,
outfile=outfile,
projection=projection,
verbose=verbose,
binary=binary,
nodata=nodata,
find=find,
coltypes=coltypes,
header=header,
incols=incols,
skiprows=skiprows,
wrap=wrap,
**kwargs,
)
with Session() as lib:
with lib.virtualfile_from_data(
check_kind="vector", data=data, x=x, y=y, z=z, required_z=False
) as vintbl:
if outfile is None:
outfile = tmpfile.name
lib.call_module(
module="triangulate",
args=build_arg_string(kwargs, infile=vintbl, outfile=outfile),
)

if outfile == tmpfile.name:
# if user did not set outfile, return pd.DataFrame
result = pd.read_csv(outfile, sep="\t", header=None)
elif outfile != tmpfile.name:
# return None if outfile set, output in outfile
result = None

if output_type == "numpy":
result = result.to_numpy()
return result
9 changes: 0 additions & 9 deletions pygmt/tests/test_triangulate.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,3 @@ def test_regular_grid_with_outgrid_param(dataframe, expected_grid):
assert grid.gmt.registration == 0 # Gridline registration
assert grid.gmt.gtype == 0 # Cartesian type
xr.testing.assert_allclose(a=grid, b=expected_grid)


def test_regular_grid_invalid_format(dataframe):
"""
Test that triangulate.regular_grid fails with outgrid that is not None or a proper
file name.
"""
with pytest.raises(GMTInvalidInput):
triangulate.regular_grid(data=dataframe, outgrid=True)
Loading