Skip to content

Commit cef4cdf

Browse files
committed
Add pygmt.read to read a dataset/grid/image into pandas.DataFrame/xarray.DataArray
1 parent a92d9d0 commit cef4cdf

File tree

7 files changed

+101
-21
lines changed

7 files changed

+101
-21
lines changed

doc/api/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ Input/output
172172
:toctree: generated
173173

174174
load_dataarray
175+
read
175176

176177
GMT Defaults
177178
------------

pygmt/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
makecpt,
5555
nearneighbor,
5656
project,
57+
read,
5758
select,
5859
sph2grd,
5960
sphdistance,

pygmt/datasets/load_remote_dataset.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@
66
from typing import Any, Literal, NamedTuple
77

88
import xarray as xr
9-
from pygmt.clib import Session
109
from pygmt.exceptions import GMTInvalidInput
11-
from pygmt.helpers import build_arg_list, kwargs_to_strings
12-
from pygmt.src import which
10+
from pygmt.helpers import kwargs_to_strings
11+
from pygmt.src import read, which
1312

1413

1514
class Resolution(NamedTuple):
@@ -443,14 +442,7 @@ def _load_remote_dataset(
443442

444443
fname = f"@{prefix}_{resolution}_{reg}"
445444
kind = "image" if name in {"earth_day", "earth_night"} else "grid"
446-
kwdict = {"R": region, "T": {"grid": "g", "image": "i"}[kind]}
447-
with Session() as lib:
448-
with lib.virtualfile_out(kind=kind) as voutgrd:
449-
lib.call_module(
450-
module="read",
451-
args=[fname, voutgrd, *build_arg_list(kwdict)],
452-
)
453-
grid = lib.virtualfile_to_raster(kind=kind, outgrid=None, vfname=voutgrd)
445+
grid = read(fname, kind=kind, region=region)
454446

455447
# Full path to the grid if not tiled grids.
456448
source = which(fname, download="a") if not resinfo.tiled else None

pygmt/datasets/samples.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
import pandas as pd
99
import xarray as xr
1010
from pygmt.exceptions import GMTInvalidInput
11-
from pygmt.io import load_dataarray
12-
from pygmt.src import which
11+
from pygmt.src import read, which
1312

1413

1514
def _load_japan_quakes() -> pd.DataFrame:
@@ -203,8 +202,7 @@ def _load_earth_relief_holes() -> xr.DataArray:
203202
The Earth relief grid. Coordinates are latitude and longitude in degrees. Relief
204203
is in meters.
205204
"""
206-
fname = which("@earth_relief_20m_holes.grd", download="c")
207-
return load_dataarray(fname, engine="netcdf4")
205+
return read("@earth_relief_20m_holes.grd", kind="grid")
208206

209207

210208
class GMTSampleData(NamedTuple):

pygmt/helpers/testing.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
import string
88
from pathlib import Path
99

10+
import xarray as xr
1011
from pygmt.exceptions import GMTImageComparisonFailure
11-
from pygmt.io import load_dataarray
12-
from pygmt.src import which
12+
from pygmt.src import read
1313

1414

1515
def check_figures_equal(*, extensions=("png",), tol=0.0, result_dir="result_images"):
@@ -144,17 +144,16 @@ def wrapper(*args, ext="png", request=None, **kwargs):
144144
return decorator
145145

146146

147-
def load_static_earth_relief():
147+
def load_static_earth_relief() -> xr.DataArray:
148148
"""
149149
Load the static_earth_relief file for internal testing.
150150
151151
Returns
152152
-------
153-
data : xarray.DataArray
153+
data
154154
A grid of Earth relief for internal tests.
155155
"""
156-
fname = which("@static_earth_relief.nc", download="c")
157-
return load_dataarray(fname)
156+
return read("@static_earth_relief.nc", kind="grid") # type: ignore[return-value]
158157

159158

160159
def skip_if_no(package):

pygmt/src/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
from pygmt.src.plot3d import plot3d
4242
from pygmt.src.project import project
4343
from pygmt.src.psconvert import psconvert
44+
from pygmt.src.read import read
4445
from pygmt.src.rose import rose
4546
from pygmt.src.select import select
4647
from pygmt.src.shift_origin import shift_origin

pygmt/src/read.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
"""
2+
Read data from files
3+
"""
4+
5+
from typing import Literal
6+
7+
import pandas as pd
8+
import xarray as xr
9+
from pygmt.clib import Session
10+
from pygmt.helpers import build_arg_list, fmt_docstring, kwargs_to_strings, use_alias
11+
12+
13+
@fmt_docstring
14+
@use_alias(R="region")
15+
@kwargs_to_strings(R="sequence")
16+
def read(
17+
file,
18+
kind: Literal["dataset", "grid", "image"],
19+
**kwargs,
20+
) -> pd.DataFrame | xr.DataArray:
21+
"""
22+
Read a dataset, grid, or image from a file and return the appropriate object.
23+
24+
For datasets, it returns a :class:`pandas.DataFrame`. For grids and images, it
25+
returns a :class:`xarray.DataArray`.
26+
27+
Parameters
28+
----------
29+
file
30+
The file name to read.
31+
kind
32+
The kind of data to read. Valid values are ``"dataset"``, ``"grid"``, and
33+
``"image"``.
34+
{region}
35+
36+
For datasets, the following keyword arguments are supported:
37+
38+
column_names
39+
A list of column names.
40+
header
41+
Row number containing column names. ``header=None`` means not to parse the
42+
column names from table header. Ignored if the row number is larger than the
43+
number of headers in the table.
44+
dtype
45+
Data type. Can be a single type for all columns or a dictionary mapping column
46+
names to types.
47+
index_col
48+
Column to set as index.
49+
50+
Returns
51+
-------
52+
Return type depends on the ``kind`` argument:
53+
54+
- ``"dataset"``: :class:`pandas.DataFrame`
55+
- ``"grid"`` or ``"image"``: :class:`xarray.DataArray`
56+
57+
58+
Examples
59+
--------
60+
61+
Read a dataset into a :class:`pandas.DataFrame` object:
62+
63+
>>> from pygmt import read
64+
>>> df = read("@hotspots.txt", kind="dataset")
65+
>>> type(df)
66+
<class 'pandas.core.frame.DataFrame'>
67+
68+
Read a grid into an :class:`xarray.DataArray` object:
69+
>>> dataarray = read("@earth_relief_01d", kind="grid")
70+
>>> type(dataarray)
71+
<class 'xarray.core.dataarray.DataArray'>
72+
"""
73+
code = {"dataset": "d", "grid": "g", "image": "i"}[kind]
74+
75+
kwdict = {
76+
"R": kwargs["R"],
77+
"T": code,
78+
}
79+
80+
with Session() as lib:
81+
with lib.virtualfile_out(kind=kind) as voutfile:
82+
lib.call_module("read", args=[file, voutfile, *build_arg_list(kwdict)])
83+
84+
match kind:
85+
case "dataset":
86+
return lib.virtualfile_to_dataset(vfname=voutfile, **kwargs)
87+
case "grid" | "image":
88+
return lib.virtualfile_to_raster(vfname=voutfile, kind=kind)

0 commit comments

Comments
 (0)