diff --git a/pygmt/src/blockm.py b/pygmt/src/blockm.py index c863f32f3b0..970acf8bcd1 100644 --- a/pygmt/src/blockm.py +++ b/pygmt/src/blockm.py @@ -6,17 +6,17 @@ import pandas as pd from pygmt.clib import Session from pygmt.helpers import ( - GMTTempFile, build_arg_string, fmt_docstring, kwargs_to_strings, use_alias, + validate_output_table_type, ) __doctest_skip__ = ["blockmean", "blockmedian", "blockmode"] -def _blockm(block_method, data, x, y, z, outfile, **kwargs): +def _blockm(block_method, data, x, y, z, output_type, outfile, **kwargs): r""" Block average (x, y, z) data tables by mean, median, or mode estimation. @@ -42,30 +42,28 @@ def _blockm(block_method, data, x, y, z, outfile, **kwargs): - None if ``outfile`` is set (filtered output will be stored in file set by ``outfile``) """ - with GMTTempFile(suffix=".csv") as tmpfile: - with Session() as lib: - with lib.virtualfile_in( + output_type = validate_output_table_type(output_type, outfile=outfile) + + column_names = None + if output_type == "pandas" and isinstance(data, pd.DataFrame): + column_names = data.columns.to_list() + + with Session() as lib: + with ( + lib.virtualfile_in( check_kind="vector", data=data, x=x, y=y, z=z, required_z=True - ) as vintbl: - # Run blockm* on data table - if outfile is None: - outfile = tmpfile.name - lib.call_module( - module=block_method, - args=build_arg_string(kwargs, infile=vintbl, outfile=outfile), - ) - - # Read temporary csv output to a pandas table - if outfile == tmpfile.name: # if user did not set outfile, return pd.DataFrame - try: - column_names = data.columns.to_list() - result = pd.read_csv(tmpfile.name, sep="\t", names=column_names) - except AttributeError: # 'str' object has no attribute 'columns' - result = pd.read_csv(tmpfile.name, sep="\t", header=None, comment=">") - elif outfile != tmpfile.name: # return None if outfile set, output in outfile - result = None - - return result + ) as vintbl, + lib.virtualfile_out(kind="dataset", fname=outfile) as vouttbl, + ): + lib.call_module( + module=block_method, + args=build_arg_string(kwargs, infile=vintbl, outfile=vouttbl), + ) + return lib.virtualfile_to_dataset( + output_type=output_type, + vfile=vouttbl, + column_names=column_names, + ) @fmt_docstring @@ -86,7 +84,9 @@ def _blockm(block_method, data, x, y, z, outfile, **kwargs): w="wrap", ) @kwargs_to_strings(I="sequence", R="sequence", i="sequence_comma", o="sequence_comma") -def blockmean(data=None, x=None, y=None, z=None, outfile=None, **kwargs): +def blockmean( + data=None, x=None, y=None, z=None, output_type="pandas", outfile=None, **kwargs +): r""" Block average (x, y, z) data tables by mean estimation. @@ -159,7 +159,14 @@ def blockmean(data=None, x=None, y=None, z=None, outfile=None, **kwargs): >>> data_bmean = pygmt.blockmean(data=data, region=[245, 255, 20, 30], spacing="5m") """ return _blockm( - block_method="blockmean", data=data, x=x, y=y, z=z, outfile=outfile, **kwargs + block_method="blockmean", + data=data, + x=x, + y=y, + z=z, + output_type=output_type, + outfile=outfile, + **kwargs, ) @@ -180,7 +187,9 @@ def blockmean(data=None, x=None, y=None, z=None, outfile=None, **kwargs): w="wrap", ) @kwargs_to_strings(I="sequence", R="sequence", i="sequence_comma", o="sequence_comma") -def blockmedian(data=None, x=None, y=None, z=None, outfile=None, **kwargs): +def blockmedian( + data=None, x=None, y=None, z=None, output_type="pandas", outfile=None, **kwargs +): r""" Block average (x, y, z) data tables by median estimation. @@ -246,7 +255,14 @@ def blockmedian(data=None, x=None, y=None, z=None, outfile=None, **kwargs): ... ) """ return _blockm( - block_method="blockmedian", data=data, x=x, y=y, z=z, outfile=outfile, **kwargs + block_method="blockmedian", + data=data, + x=x, + y=y, + z=z, + output_type=output_type, + outfile=outfile, + **kwargs, ) @@ -267,7 +283,9 @@ def blockmedian(data=None, x=None, y=None, z=None, outfile=None, **kwargs): w="wrap", ) @kwargs_to_strings(I="sequence", R="sequence", i="sequence_comma", o="sequence_comma") -def blockmode(data=None, x=None, y=None, z=None, outfile=None, **kwargs): +def blockmode( + data=None, x=None, y=None, z=None, output_type="pandas", outfile=None, **kwargs +): r""" Block average (x, y, z) data tables by mode estimation. @@ -331,5 +349,12 @@ def blockmode(data=None, x=None, y=None, z=None, outfile=None, **kwargs): >>> data_bmode = pygmt.blockmode(data=data, region=[245, 255, 20, 30], spacing="5m") """ return _blockm( - block_method="blockmode", data=data, x=x, y=y, z=z, outfile=outfile, **kwargs + block_method="blockmode", + data=data, + x=x, + y=y, + z=z, + output_type=output_type, + outfile=outfile, + **kwargs, ) diff --git a/pygmt/src/grdhisteq.py b/pygmt/src/grdhisteq.py index 0e2c8c9ea60..9232f0ede8c 100644 --- a/pygmt/src/grdhisteq.py +++ b/pygmt/src/grdhisteq.py @@ -3,7 +3,6 @@ """ import numpy as np -import pandas as pd from pygmt.clib import Session from pygmt.exceptions import GMTInvalidInput from pygmt.helpers import ( @@ -231,33 +230,28 @@ def compute_bins(grid, output_type="pandas", **kwargs): if kwargs.get("h") is not None and output_type != "file": raise GMTInvalidInput("'header' is only allowed with output_type='file'.") - with GMTTempFile(suffix=".txt") as tmpfile: - with Session() as lib: - with lib.virtualfile_in(check_kind="raster", data=grid) as vingrd: - if outfile is None: - kwargs["D"] = outfile = tmpfile.name # output to tmpfile - lib.call_module( - module="grdhisteq", args=build_arg_string(kwargs, infile=vingrd) - ) + with Session() as lib: + with ( + lib.virtualfile_in(check_kind="raster", data=grid) as vingrd, + lib.virtualfile_out(kind="dataset", fname=outfile) as vouttbl, + ): + kwargs["D"] = vouttbl # -D for output file name + lib.call_module( + module="grdhisteq", args=build_arg_string(kwargs, infile=vingrd) + ) - if outfile == tmpfile.name: - # if user did not set outfile, return pd.DataFrame - result = pd.read_csv( - filepath_or_buffer=outfile, - sep="\t", - header=None, - names=["start", "stop", "bin_id"], - dtype={ + result = lib.virtualfile_to_dataset( + output_type=output_type, + vfile=vouttbl, + column_names=["start", "stop", "bin_id"], + ) + if output_type == "pandas": + result = result.astype( + { "start": np.float32, "stop": np.float32, "bin_id": np.uint32, - }, + } ) - elif outfile != tmpfile.name: - # return None if outfile set, output in outfile - return None - - if output_type == "numpy": - return result.to_numpy() - - return result.set_index("bin_id") + return result.set_index("bin_id") + return result diff --git a/pygmt/src/grdtrack.py b/pygmt/src/grdtrack.py index 1e5df5ffbda..5b9b2865b3d 100644 --- a/pygmt/src/grdtrack.py +++ b/pygmt/src/grdtrack.py @@ -6,11 +6,11 @@ from pygmt.clib import Session from pygmt.exceptions import GMTInvalidInput from pygmt.helpers import ( - GMTTempFile, build_arg_string, fmt_docstring, kwargs_to_strings, use_alias, + validate_output_table_type, ) __doctest_skip__ = ["grdtrack"] @@ -44,7 +44,9 @@ w="wrap", ) @kwargs_to_strings(R="sequence", S="sequence", i="sequence_comma", o="sequence_comma") -def grdtrack(grid, points=None, newcolname=None, outfile=None, **kwargs): +def grdtrack( + grid, points=None, output_type="pandas", outfile=None, newcolname=None, **kwargs +): r""" Sample grids at specified (x,y) locations. @@ -291,30 +293,27 @@ def grdtrack(grid, points=None, newcolname=None, outfile=None, **kwargs): if hasattr(points, "columns") and newcolname is None: raise GMTInvalidInput("Please pass in a str to 'newcolname'") - with GMTTempFile(suffix=".csv") as tmpfile: - with Session() as lib: - with ( - lib.virtualfile_in(check_kind="raster", data=grid) as vingrd, - lib.virtualfile_in( - check_kind="vector", data=points, required_data=False - ) as vintbl, - ): - kwargs["G"] = vingrd - if outfile is None: # Output to tmpfile if outfile is not set - outfile = tmpfile.name - lib.call_module( - module="grdtrack", - args=build_arg_string(kwargs, infile=vintbl, outfile=outfile), - ) + output_type = validate_output_table_type(output_type, outfile=outfile) - # Read temporary csv output to a pandas table - if outfile == tmpfile.name: # if user did not set outfile, return pd.DataFrame - try: - column_names = [*points.columns.to_list(), newcolname] - result = pd.read_csv(tmpfile.name, sep="\t", names=column_names) - except AttributeError: # 'str' object has no attribute 'columns' - result = pd.read_csv(tmpfile.name, sep="\t", header=None, comment=">") - elif outfile != tmpfile.name: # return None if outfile set, output in outfile - result = None + column_names = None + if output_type == "pandas" and isinstance(points, pd.DataFrame): + column_names = [*points.columns.to_list(), newcolname] - return result + with Session() as lib: + with ( + lib.virtualfile_in(check_kind="raster", data=grid) as vingrd, + lib.virtualfile_in( + check_kind="vector", data=points, required_data=False + ) as vintbl, + lib.virtualfile_out(kind="dataset", fname=outfile) as vouttbl, + ): + kwargs["G"] = vingrd + lib.call_module( + module="grdtrack", + args=build_arg_string(kwargs, infile=vintbl, outfile=vouttbl), + ) + return lib.virtualfile_to_dataset( + output_type=output_type, + vfile=vouttbl, + column_names=column_names, + ) diff --git a/pygmt/src/grdvolume.py b/pygmt/src/grdvolume.py index 1bb696e9e04..7b48e63c046 100644 --- a/pygmt/src/grdvolume.py +++ b/pygmt/src/grdvolume.py @@ -2,10 +2,8 @@ grdvolume - Calculate grid volume and area constrained by a contour. """ -import pandas as pd from pygmt.clib import Session from pygmt.helpers import ( - GMTTempFile, build_arg_string, fmt_docstring, kwargs_to_strings, @@ -103,22 +101,13 @@ def grdvolume(grid, output_type="pandas", outfile=None, **kwargs): """ output_type = validate_output_table_type(output_type, outfile=outfile) - with GMTTempFile() as tmpfile: - with Session() as lib: - with lib.virtualfile_in(check_kind="raster", data=grid) as vingrd: - if outfile is None: - outfile = tmpfile.name - lib.call_module( - module="grdvolume", - args=build_arg_string(kwargs, infile=vingrd, outfile=outfile), - ) - - # Read temporary csv output to a pandas table - if outfile == tmpfile.name: # if user did not set outfile, return pd.DataFrame - result = pd.read_csv(tmpfile.name, sep="\t", header=None, comment=">") - elif outfile != tmpfile.name: # return None if outfile set, output in outfile - result = None - - if output_type == "numpy": - result = result.to_numpy() - return result + with Session() as lib: + with ( + lib.virtualfile_in(check_kind="raster", data=grid) as vingrid, + lib.virtualfile_out(kind="dataset", fname=outfile) as vouttbl, + ): + lib.call_module( + module="grdvolume", + args=build_arg_string(kwargs, infile=vingrid, outfile=vouttbl), + ) + return lib.virtualfile_to_dataset(output_type=output_type, vfile=vouttbl) diff --git a/pygmt/src/project.py b/pygmt/src/project.py index 99738bfd9c8..79b3e6a2695 100644 --- a/pygmt/src/project.py +++ b/pygmt/src/project.py @@ -2,15 +2,14 @@ project - Project data onto lines or great circles, or generate tracks. """ -import pandas as pd from pygmt.clib import Session from pygmt.exceptions import GMTInvalidInput from pygmt.helpers import ( - GMTTempFile, build_arg_string, fmt_docstring, kwargs_to_strings, use_alias, + validate_output_table_type, ) @@ -32,7 +31,9 @@ f="coltypes", ) @kwargs_to_strings(E="sequence", L="sequence", T="sequence", W="sequence", C="sequence") -def project(data=None, x=None, y=None, z=None, outfile=None, **kwargs): +def project( + data=None, x=None, y=None, z=None, output_type="pandas", outfile=None, **kwargs +): r""" Project data onto lines or great circles, or generate tracks. @@ -223,29 +224,31 @@ def project(data=None, x=None, y=None, z=None, outfile=None, **kwargs): "The `convention` parameter is not allowed with `generate`." ) - with GMTTempFile(suffix=".csv") as tmpfile: - if outfile is None: # Output to tmpfile if outfile is not set - outfile = tmpfile.name - with Session() as lib: - if kwargs.get("G") is None: - with lib.virtualfile_in( - check_kind="vector", data=data, x=x, y=y, z=z, required_z=False - ) as vintbl: - # Run project on the temporary (csv) data table - arg_str = build_arg_string(kwargs, infile=vintbl, outfile=outfile) - else: - arg_str = build_arg_string(kwargs, outfile=outfile) - lib.call_module(module="project", args=arg_str) - - # if user did not set outfile, return pd.DataFrame - if outfile == tmpfile.name: - if kwargs.get("G") is not None: - column_names = list("rsp") - result = pd.read_csv(tmpfile.name, sep="\t", names=column_names) - else: - result = pd.read_csv(tmpfile.name, sep="\t", header=None, comment=">") - # return None if outfile set, output in outfile - elif outfile != tmpfile.name: - result = None - - return result + output_type = validate_output_table_type(output_type, outfile=outfile) + + column_names = None + if output_type == "pandas" and kwargs.get("G") is not None: + column_names = list("rsp") + + with Session() as lib: + with ( + lib.virtualfile_in( + check_kind="vector", + data=data, + x=x, + y=y, + z=z, + required_z=False, + required_data=False, + ) as vintbl, + lib.virtualfile_out(kind="dataset", fname=outfile) as vouttbl, + ): + lib.call_module( + module="project", + args=build_arg_string(kwargs, infile=vintbl, outfile=vouttbl), + ) + return lib.virtualfile_to_dataset( + output_type=output_type, + vfile=vouttbl, + column_names=column_names, + ) diff --git a/pygmt/src/select.py b/pygmt/src/select.py index fe132b356f9..633f967e85c 100644 --- a/pygmt/src/select.py +++ b/pygmt/src/select.py @@ -5,11 +5,11 @@ import pandas as pd from pygmt.clib import Session from pygmt.helpers import ( - GMTTempFile, build_arg_string, fmt_docstring, kwargs_to_strings, use_alias, + validate_output_table_type, ) __doctest_skip__ = ["select"] @@ -41,7 +41,7 @@ w="wrap", ) @kwargs_to_strings(M="sequence", R="sequence", i="sequence_comma", o="sequence_comma") -def select(data=None, outfile=None, **kwargs): +def select(data=None, output_type="pandas", outfile=None, **kwargs): r""" Select data table subsets based on multiple spatial criteria. @@ -196,25 +196,23 @@ def select(data=None, outfile=None, **kwargs): >>> # longitudes 246 and 247 and latitudes 20 and 21 >>> out = pygmt.select(data=ship_data, region=[246, 247, 20, 21]) """ - - with GMTTempFile(suffix=".csv") as tmpfile: - with Session() as lib: - with lib.virtualfile_in(check_kind="vector", data=data) as vintbl: - if outfile is None: - outfile = tmpfile.name - lib.call_module( - module="select", - args=build_arg_string(kwargs, infile=vintbl, outfile=outfile), - ) - - # Read temporary csv output to a pandas table - if outfile == tmpfile.name: # if user did not set outfile, return pd.DataFrame - try: - column_names = data.columns.to_list() - result = pd.read_csv(tmpfile.name, sep="\t", names=column_names) - except AttributeError: # 'str' object has no attribute 'columns' - result = pd.read_csv(tmpfile.name, sep="\t", header=None, comment=">") - elif outfile != tmpfile.name: # return None if outfile set, output in outfile - result = None - - return result + output_type = validate_output_table_type(output_type, outfile=outfile) + + column_names = None + if output_type == "pandas" and isinstance(data, pd.DataFrame): + column_names = data.columns.to_list() + + with Session() as lib: + with ( + lib.virtualfile_in(check_kind="vector", data=data) as vintbl, + lib.virtualfile_out(kind="dataset", fname=outfile) as vouttbl, + ): + lib.call_module( + module="select", + args=build_arg_string(kwargs, infile=vintbl, outfile=vouttbl), + ) + return lib.virtualfile_to_dataset( + output_type=output_type, + vfile=vouttbl, + column_names=column_names, + ) diff --git a/pygmt/src/triangulate.py b/pygmt/src/triangulate.py index e73ab92fe5e..e0f517b20c4 100644 --- a/pygmt/src/triangulate.py +++ b/pygmt/src/triangulate.py @@ -3,7 +3,6 @@ Cartesian data. """ -import pandas as pd from pygmt.clib import Session from pygmt.helpers import ( GMTTempFile, @@ -243,25 +242,15 @@ def delaunay_triples( """ output_type = validate_output_table_type(output_type, outfile) - with GMTTempFile(suffix=".txt") as tmpfile: - with Session() as lib: - with lib.virtualfile_in( + with Session() as lib: + with ( + lib.virtualfile_in( 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 + ) as vintbl, + lib.virtualfile_out(kind="dataset", fname=outfile) as vouttbl, + ): + lib.call_module( + module="triangulate", + args=build_arg_string(kwargs, infile=vintbl, outfile=vouttbl), + ) + return lib.virtualfile_to_dataset(output_type=output_type, vfile=vouttbl) diff --git a/pygmt/tests/test_triangulate.py b/pygmt/tests/test_triangulate.py index 154bc82b09f..75cccbf17ab 100644 --- a/pygmt/tests/test_triangulate.py +++ b/pygmt/tests/test_triangulate.py @@ -44,7 +44,8 @@ def fixture_expected_dataframe(): [4, 6, 1], [3, 4, 2], [9, 3, 8], - ] + ], + dtype=float, ) @@ -116,7 +117,9 @@ def test_delaunay_triples_outfile(dataframe, expected_dataframe): assert len(record) == 1 # check that only one warning was raised assert result is None # return value is None assert Path(tmpfile.name).stat().st_size > 0 - temp_df = pd.read_csv(filepath_or_buffer=tmpfile.name, sep="\t", header=None) + temp_df = pd.read_csv( + filepath_or_buffer=tmpfile.name, sep="\t", header=None, dtype=float + ) pd.testing.assert_frame_equal(left=temp_df, right=expected_dataframe)