Skip to content

Commit 855ebdd

Browse files
authored
pygmt.blockm*: Add 'output_type' parameter for output in pandas/numpy/file formats (#3103)
1 parent 8220180 commit 855ebdd

File tree

1 file changed

+108
-76
lines changed

1 file changed

+108
-76
lines changed

pygmt/src/blockm.py

Lines changed: 108 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
11
"""
2-
blockm - Block average (x, y, z) data tables by mean, median, or mode
3-
estimation.
2+
blockm - Block average (x, y, z) data tables by mean, median, or mode estimation.
43
"""
54

5+
from typing import Literal
6+
7+
import numpy as np
68
import pandas as pd
79
from pygmt.clib import Session
810
from pygmt.helpers import (
9-
GMTTempFile,
1011
build_arg_string,
1112
fmt_docstring,
1213
kwargs_to_strings,
1314
use_alias,
15+
validate_output_table_type,
1416
)
1517

1618
__doctest_skip__ = ["blockmean", "blockmedian", "blockmode"]
1719

1820

19-
def _blockm(block_method, data, x, y, z, outfile, **kwargs):
21+
def _blockm(
22+
block_method, data, x, y, z, output_type, outfile, **kwargs
23+
) -> pd.DataFrame | np.ndarray | None:
2024
r"""
2125
Block average (x, y, z) data tables by mean, median, or mode estimation.
2226
@@ -34,38 +38,34 @@ def _blockm(block_method, data, x, y, z, outfile, **kwargs):
3438
3539
Returns
3640
-------
37-
output : pandas.DataFrame or None
38-
Return type depends on whether the ``outfile`` parameter is set:
41+
ret
42+
Return type depends on ``outfile`` and ``output_type``:
3943
40-
- :class:`pandas.DataFrame` table with (x, y, z) columns if ``outfile``
41-
is not set
42-
- None if ``outfile`` is set (filtered output will be stored in file
43-
set by ``outfile``)
44+
- ``None`` if ``outfile`` is set (output will be stored in file set by
45+
``outfile``)
46+
- :class:`pandas.DataFrame` or :class:`numpy.ndarray` if ``outfile`` is not set
47+
(depends on ``output_type``)
4448
"""
45-
with GMTTempFile(suffix=".csv") as tmpfile:
46-
with Session() as lib:
47-
with lib.virtualfile_in(
49+
output_type = validate_output_table_type(output_type, outfile=outfile)
50+
51+
column_names = None
52+
if output_type == "pandas" and isinstance(data, pd.DataFrame):
53+
column_names = data.columns.to_list()
54+
55+
with Session() as lib:
56+
with (
57+
lib.virtualfile_in(
4858
check_kind="vector", data=data, x=x, y=y, z=z, required_z=True
49-
) as vintbl:
50-
# Run blockm* on data table
51-
if outfile is None:
52-
outfile = tmpfile.name
53-
lib.call_module(
54-
module=block_method,
55-
args=build_arg_string(kwargs, infile=vintbl, outfile=outfile),
56-
)
57-
58-
# Read temporary csv output to a pandas table
59-
if outfile == tmpfile.name: # if user did not set outfile, return pd.DataFrame
60-
try:
61-
column_names = data.columns.to_list()
62-
result = pd.read_csv(tmpfile.name, sep="\t", names=column_names)
63-
except AttributeError: # 'str' object has no attribute 'columns'
64-
result = pd.read_csv(tmpfile.name, sep="\t", header=None, comment=">")
65-
elif outfile != tmpfile.name: # return None if outfile set, output in outfile
66-
result = None
67-
68-
return result
59+
) as vintbl,
60+
lib.virtualfile_out(kind="dataset", fname=outfile) as vouttbl,
61+
):
62+
lib.call_module(
63+
module=block_method,
64+
args=build_arg_string(kwargs, infile=vintbl, outfile=vouttbl),
65+
)
66+
return lib.virtualfile_to_dataset(
67+
output_type=output_type, vfname=vouttbl, column_names=column_names
68+
)
6969

7070

7171
@fmt_docstring
@@ -86,7 +86,15 @@ def _blockm(block_method, data, x, y, z, outfile, **kwargs):
8686
w="wrap",
8787
)
8888
@kwargs_to_strings(I="sequence", R="sequence", i="sequence_comma", o="sequence_comma")
89-
def blockmean(data=None, x=None, y=None, z=None, outfile=None, **kwargs):
89+
def blockmean(
90+
data=None,
91+
x=None,
92+
y=None,
93+
z=None,
94+
output_type: Literal["pandas", "numpy", "file"] = "pandas",
95+
outfile: str | None = None,
96+
**kwargs,
97+
) -> pd.DataFrame | np.ndarray | None:
9098
r"""
9199
Block average (x, y, z) data tables by mean estimation.
92100
@@ -111,9 +119,9 @@ def blockmean(data=None, x=None, y=None, z=None, outfile=None, **kwargs):
111119
{table-classes}.
112120
x/y/z : 1-D arrays
113121
Arrays of x and y coordinates and values z of the data points.
114-
122+
{output_type}
123+
{outfile}
115124
{spacing}
116-
117125
summary : str
118126
[**m**\|\ **n**\|\ **s**\|\ **w**].
119127
Type of summary values calculated by blockmean.
@@ -122,12 +130,7 @@ def blockmean(data=None, x=None, y=None, z=None, outfile=None, **kwargs):
122130
- **n** - report the number of input points inside each block
123131
- **s** - report the sum of all z-values inside a block
124132
- **w** - report the sum of weights
125-
126133
{region}
127-
128-
outfile : str
129-
The file name for the output ASCII file.
130-
131134
{verbose}
132135
{aspatial}
133136
{binary}
@@ -142,13 +145,13 @@ def blockmean(data=None, x=None, y=None, z=None, outfile=None, **kwargs):
142145
143146
Returns
144147
-------
145-
output : pandas.DataFrame or None
146-
Return type depends on whether the ``outfile`` parameter is set:
148+
ret
149+
Return type depends on ``outfile`` and ``output_type``:
147150
148-
- :class:`pandas.DataFrame` table with (x, y, z) columns if ``outfile``
149-
is not set.
150-
- None if ``outfile`` is set (filtered output will be stored in file
151-
set by ``outfile``).
151+
- ``None`` if ``outfile`` is set (output will be stored in file set by
152+
``outfile``)
153+
- :class:`pandas.DataFrame` or :class:`numpy.ndarray` if ``outfile`` is not set
154+
(depends on ``output_type``)
152155
153156
Example
154157
-------
@@ -159,7 +162,14 @@ def blockmean(data=None, x=None, y=None, z=None, outfile=None, **kwargs):
159162
>>> data_bmean = pygmt.blockmean(data=data, region=[245, 255, 20, 30], spacing="5m")
160163
"""
161164
return _blockm(
162-
block_method="blockmean", data=data, x=x, y=y, z=z, outfile=outfile, **kwargs
165+
block_method="blockmean",
166+
data=data,
167+
x=x,
168+
y=y,
169+
z=z,
170+
output_type=output_type,
171+
outfile=outfile,
172+
**kwargs,
163173
)
164174

165175

@@ -180,7 +190,15 @@ def blockmean(data=None, x=None, y=None, z=None, outfile=None, **kwargs):
180190
w="wrap",
181191
)
182192
@kwargs_to_strings(I="sequence", R="sequence", i="sequence_comma", o="sequence_comma")
183-
def blockmedian(data=None, x=None, y=None, z=None, outfile=None, **kwargs):
193+
def blockmedian(
194+
data=None,
195+
x=None,
196+
y=None,
197+
z=None,
198+
output_type: Literal["pandas", "numpy", "file"] = "pandas",
199+
outfile: str | None = None,
200+
**kwargs,
201+
) -> pd.DataFrame | np.ndarray | None:
184202
r"""
185203
Block average (x, y, z) data tables by median estimation.
186204
@@ -205,14 +223,10 @@ def blockmedian(data=None, x=None, y=None, z=None, outfile=None, **kwargs):
205223
{table-classes}.
206224
x/y/z : 1-D arrays
207225
Arrays of x and y coordinates and values z of the data points.
208-
226+
{output_type}
227+
{outfile}
209228
{spacing}
210-
211229
{region}
212-
213-
outfile : str
214-
The file name for the output ASCII file.
215-
216230
{verbose}
217231
{aspatial}
218232
{binary}
@@ -227,13 +241,13 @@ def blockmedian(data=None, x=None, y=None, z=None, outfile=None, **kwargs):
227241
228242
Returns
229243
-------
230-
output : pandas.DataFrame or None
231-
Return type depends on whether the ``outfile`` parameter is set:
244+
ret
245+
Return type depends on ``outfile`` and ``output_type``:
232246
233-
- :class:`pandas.DataFrame` table with (x, y, z) columns if ``outfile``
234-
is not set.
235-
- None if ``outfile`` is set (filtered output will be stored in file
236-
set by ``outfile``).
247+
- ``None`` if ``outfile`` is set (output will be stored in file set by
248+
``outfile``)
249+
- :class:`pandas.DataFrame` or :class:`numpy.ndarray` if ``outfile`` is not set
250+
(depends on ``output_type``)
237251
238252
Example
239253
-------
@@ -246,7 +260,14 @@ def blockmedian(data=None, x=None, y=None, z=None, outfile=None, **kwargs):
246260
... )
247261
"""
248262
return _blockm(
249-
block_method="blockmedian", data=data, x=x, y=y, z=z, outfile=outfile, **kwargs
263+
block_method="blockmedian",
264+
data=data,
265+
x=x,
266+
y=y,
267+
z=z,
268+
output_type=output_type,
269+
outfile=outfile,
270+
**kwargs,
250271
)
251272

252273

@@ -267,7 +288,15 @@ def blockmedian(data=None, x=None, y=None, z=None, outfile=None, **kwargs):
267288
w="wrap",
268289
)
269290
@kwargs_to_strings(I="sequence", R="sequence", i="sequence_comma", o="sequence_comma")
270-
def blockmode(data=None, x=None, y=None, z=None, outfile=None, **kwargs):
291+
def blockmode(
292+
data=None,
293+
x=None,
294+
y=None,
295+
z=None,
296+
output_type: Literal["pandas", "numpy", "file"] = "pandas",
297+
outfile: str | None = None,
298+
**kwargs,
299+
) -> pd.DataFrame | np.ndarray | None:
271300
r"""
272301
Block average (x, y, z) data tables by mode estimation.
273302
@@ -292,14 +321,10 @@ def blockmode(data=None, x=None, y=None, z=None, outfile=None, **kwargs):
292321
{table-classes}.
293322
x/y/z : 1-D arrays
294323
Arrays of x and y coordinates and values z of the data points.
295-
324+
{output_type}
325+
{outfile}
296326
{spacing}
297-
298327
{region}
299-
300-
outfile : str
301-
The file name for the output ASCII file.
302-
303328
{verbose}
304329
{aspatial}
305330
{binary}
@@ -314,13 +339,13 @@ def blockmode(data=None, x=None, y=None, z=None, outfile=None, **kwargs):
314339
315340
Returns
316341
-------
317-
output : pandas.DataFrame or None
318-
Return type depends on whether the ``outfile`` parameter is set:
342+
ret
343+
Return type depends on ``outfile`` and ``output_type``:
319344
320-
- :class:`pandas.DataFrame` table with (x, y, z) columns if ``outfile``
321-
is not set.
322-
- None if ``outfile`` is set (filtered output will be stored in file
323-
set by ``outfile``).
345+
- ``None`` if ``outfile`` is set (output will be stored in file set by
346+
``outfile``)
347+
- :class:`pandas.DataFrame` or :class:`numpy.ndarray` if ``outfile`` is not set
348+
(depends on ``output_type``)
324349
325350
Example
326351
-------
@@ -331,5 +356,12 @@ def blockmode(data=None, x=None, y=None, z=None, outfile=None, **kwargs):
331356
>>> data_bmode = pygmt.blockmode(data=data, region=[245, 255, 20, 30], spacing="5m")
332357
"""
333358
return _blockm(
334-
block_method="blockmode", data=data, x=x, y=y, z=z, outfile=outfile, **kwargs
359+
block_method="blockmode",
360+
data=data,
361+
x=x,
362+
y=y,
363+
z=z,
364+
output_type=output_type,
365+
outfile=outfile,
366+
**kwargs,
335367
)

0 commit comments

Comments
 (0)