Skip to content

Commit 2d78563

Browse files
authored
clib.Session: Wrap the GMT API function GMT_Read_VirtualFile (#2993)
1 parent 823676f commit 2d78563

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
@@ -313,5 +313,6 @@ Low level access (these are mostly used by the :mod:`pygmt.clib` package):
313313
clib.Session.put_vector
314314
clib.Session.write_data
315315
clib.Session.open_virtualfile
316+
clib.Session.read_virtualfile
316317
clib.Session.extract_region
317318
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,
@@ -1607,6 +1609,72 @@ def virtualfile_from_data( # noqa: PLR0912
16071609

16081610
return file_context
16091611

1612+
def read_virtualfile(
1613+
self, vfname: str, kind: Literal["dataset", "grid", None] = None
1614+
):
1615+
"""
1616+
Read data from a virtual file and optionally cast into a GMT data container.
1617+
1618+
Parameters
1619+
----------
1620+
vfname
1621+
Name of the virtual file to read.
1622+
kind
1623+
Cast the data into a GMT data container. Valid values are ``"dataset"``,
1624+
``"grid"`` and ``None``. If ``None``, will return a ctypes void pointer.
1625+
1626+
Examples
1627+
--------
1628+
>>> from pygmt.clib import Session
1629+
>>> from pygmt.helpers import GMTTempFile
1630+
>>>
1631+
>>> # Read dataset from a virtual file
1632+
>>> with Session() as lib:
1633+
... with GMTTempFile(suffix=".txt") as tmpfile:
1634+
... with open(tmpfile.name, mode="w") as fp:
1635+
... print("1.0 2.0 3.0 TEXT", file=fp)
1636+
... with lib.open_virtualfile(
1637+
... "GMT_IS_DATASET", "GMT_IS_PLP", "GMT_OUT", None
1638+
... ) as vfile:
1639+
... lib.call_module("read", f"{tmpfile.name} {vfile} -Td")
1640+
... # Read the virtual file as a void pointer
1641+
... void_pointer = lib.read_virtualfile(vfile)
1642+
... assert isinstance(void_pointer, int) # void pointer is an int
1643+
... # Read the virtual file as a dataset
1644+
... data_pointer = lib.read_virtualfile(vfile, kind="dataset")
1645+
... assert isinstance(data_pointer, ctp.POINTER(_GMT_DATASET))
1646+
>>>
1647+
>>> # Read grid from a virtual file
1648+
>>> with Session() as lib:
1649+
... with lib.open_virtualfile(
1650+
... "GMT_IS_GRID", "GMT_IS_SURFACE", "GMT_OUT", None
1651+
... ) as vfile:
1652+
... lib.call_module("read", f"@earth_relief_01d_g {vfile} -Tg")
1653+
... # Read the virtual file as a void pointer
1654+
... void_pointer = lib.read_virtualfile(vfile)
1655+
... assert isinstance(void_pointer, int) # void pointer is an int
1656+
... data_pointer = lib.read_virtualfile(vfile, kind="grid")
1657+
... assert isinstance(data_pointer, ctp.POINTER(_GMT_GRID))
1658+
1659+
Returns
1660+
-------
1661+
Pointer to the GMT data container. If ``kind`` is None, returns a ctypes void
1662+
pointer instead.
1663+
"""
1664+
c_read_virtualfile = self.get_libgmt_func(
1665+
"GMT_Read_VirtualFile",
1666+
argtypes=[ctp.c_void_p, ctp.c_char_p],
1667+
restype=ctp.c_void_p,
1668+
)
1669+
pointer = c_read_virtualfile(self.session_pointer, vfname.encode())
1670+
# The GMT C API function GMT_Read_VirtualFile returns a void pointer. It usually
1671+
# needs to be cast into a pointer to a GMT data container (e.g., _GMT_GRID or
1672+
# _GMT_DATASET).
1673+
if kind is None: # Return the ctypes void pointer
1674+
return pointer
1675+
dtype = {"dataset": _GMT_DATASET, "grid": _GMT_GRID}[kind]
1676+
return ctp.cast(pointer, ctp.POINTER(dtype))
1677+
16101678
def extract_region(self):
16111679
"""
16121680
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)