Skip to content

Commit 29702a6

Browse files
committed
Wrap GMT_Read_VirtualFile
1 parent 89a51c0 commit 29702a6

File tree

5 files changed

+90
-0
lines changed

5 files changed

+90
-0
lines changed

doc/api/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -308,5 +308,6 @@ Low level access (these are mostly used by the :mod:`pygmt.clib` package):
308308
clib.Session.put_vector
309309
clib.Session.write_data
310310
clib.Session.open_virtual_file
311+
clib.Session.read_virtualfile
311312
clib.Session.extract_region
312313
clib.Session.get_libgmt_func

pygmt/clib/session.py

+68
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import pathlib
1010
import sys
1111
import warnings
12+
from typing import Literal
1213

1314
import numpy as np
1415
import pandas as pd
@@ -21,6 +22,7 @@
2122
vectors_to_arrays,
2223
)
2324
from pygmt.clib.loading import load_libgmt
25+
from pygmt.datatypes import _GMT_DATASET, _GMT_GRID
2426
from pygmt.exceptions import (
2527
GMTCLibError,
2628
GMTCLibNoSessionError,
@@ -1588,6 +1590,72 @@ def virtualfile_from_data( # noqa: PLR0912
15881590

15891591
return file_context
15901592

1593+
def read_virtualfile(
1594+
self, vfname: str, kind: Literal["dataset", "grid", None] = None
1595+
):
1596+
"""
1597+
Read data from a virtual file and optionally cast into a GMT data container.
1598+
1599+
Parameters
1600+
----------
1601+
vfname
1602+
Name of the virtual file to read.
1603+
kind
1604+
Cast the data into a GMT data container. Valid values are ``"dataset"``,
1605+
``"grid"`` and ``None``. If ``None``, will return a ctypes void pointer.
1606+
1607+
Examples
1608+
--------
1609+
>>> from pygmt.helpers import GMTTempFile
1610+
>>> from pygmt.clib import Session
1611+
>>>
1612+
>>> # Read dataset from a virtual file
1613+
>>> with GMTTempFile(suffix=".txt") as tmpfile:
1614+
... with open(tmpfile.name, mode="w") as fp:
1615+
... print("1.0 2.0 3.0 TEXT", file=fp)
1616+
... with Session() as lib:
1617+
... with lib.open_virtual_file(
1618+
... "GMT_IS_DATASET", "GMT_IS_PLP", "GMT_OUT", None
1619+
... ) as vfile:
1620+
... lib.call_module("read", f"{tmpfile.name} {vfile} -Td")
1621+
... # Read the virtual file as a void pointer
1622+
... void_pointer = lib.read_virtualfile(vfile)
1623+
... assert isinstance(void_pointer, int) # void pointer is an int
1624+
... # Read the virtual file as a dataset
1625+
... data_pointer = lib.read_virtualfile(vfile, kind="dataset")
1626+
... assert isinstance(data_pointer, ctp.POINTER(_GMT_DATASET))
1627+
>>>
1628+
>>> # Read grid from a virtual file
1629+
>>> with Session() as lib:
1630+
... with lib.open_virtual_file(
1631+
... "GMT_IS_GRID", "GMT_IS_SURFACE", "GMT_OUT", None
1632+
... ) as vfile:
1633+
... lib.call_module("read", f"@earth_relief_01d_g {vfile} -Tg")
1634+
... # Read the virtual file as a void pointer
1635+
... void_pointer = lib.read_virtualfile(vfile)
1636+
... assert isinstance(void_pointer, int) # void pointer is an int
1637+
... data_pointer = lib.read_virtualfile(vfile, kind="grid")
1638+
... assert isinstance(data_pointer, ctp.POINTER(_GMT_GRID))
1639+
1640+
Returns
1641+
-------
1642+
Pointer to the GMT data container. If ``kind`` is None, returns a ctypes void
1643+
pointer instead.
1644+
"""
1645+
c_read_virtualfile = self.get_libgmt_func(
1646+
"GMT_Read_VirtualFile",
1647+
argtypes=[ctp.c_void_p, ctp.c_char_p],
1648+
restype=ctp.c_void_p,
1649+
)
1650+
pointer = c_read_virtualfile(self.session_pointer, vfname.encode())
1651+
# The GMT C API function GMT_Read_VirtualFile returns a void pointer. It usually
1652+
# needs to be cast into a pointer to a GMT data container (e.g., _GMT_GRID or
1653+
# _GMT_DATASET).
1654+
if kind is None: # Return the ctypes void pointer
1655+
return pointer
1656+
dtype = {"dataset": _GMT_DATASET, "grid": _GMT_GRID}[kind]
1657+
return ctp.cast(pointer, ctp.POINTER(dtype))
1658+
15911659
def extract_region(self):
15921660
"""
15931661
Extract the WESN bounding box of the currently active figure.

pygmt/datatypes/__init__.py

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""
2+
Wrappers for GMT data types.
3+
"""
4+
from pygmt.datatypes.dataset import _GMT_DATASET
5+
from pygmt.datatypes.grid import _GMT_GRID

pygmt/datatypes/dataset.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"""
2+
Wrapper for the GMT_DATASET data type.
3+
"""
4+
import ctypes as ctp
5+
6+
7+
class _GMT_DATASET(ctp.Structure): # noqa: N801
8+
pass

pygmt/datatypes/grid.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"""
2+
Wrapper for the GMT_GRID data type.
3+
"""
4+
import ctypes as ctp
5+
6+
7+
class _GMT_GRID(ctp.Structure): # noqa: N801
8+
pass

0 commit comments

Comments
 (0)