Skip to content

Commit

Permalink
clib.Session: Wrap the GMT API function GMT_Read_VirtualFile (#2993)
Browse files Browse the repository at this point in the history
  • Loading branch information
seisman authored Feb 19, 2024
1 parent 823676f commit 2d78563
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 0 deletions.
1 change: 1 addition & 0 deletions doc/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -313,5 +313,6 @@ Low level access (these are mostly used by the :mod:`pygmt.clib` package):
clib.Session.put_vector
clib.Session.write_data
clib.Session.open_virtualfile
clib.Session.read_virtualfile
clib.Session.extract_region
clib.Session.get_libgmt_func
68 changes: 68 additions & 0 deletions pygmt/clib/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import pathlib
import sys
import warnings
from typing import Literal

import numpy as np
import pandas as pd
Expand All @@ -21,6 +22,7 @@
vectors_to_arrays,
)
from pygmt.clib.loading import load_libgmt
from pygmt.datatypes import _GMT_DATASET, _GMT_GRID
from pygmt.exceptions import (
GMTCLibError,
GMTCLibNoSessionError,
Expand Down Expand Up @@ -1607,6 +1609,72 @@ def virtualfile_from_data( # noqa: PLR0912

return file_context

def read_virtualfile(
self, vfname: str, kind: Literal["dataset", "grid", None] = None
):
"""
Read data from a virtual file and optionally cast into a GMT data container.
Parameters
----------
vfname
Name of the virtual file to read.
kind
Cast the data into a GMT data container. Valid values are ``"dataset"``,
``"grid"`` and ``None``. If ``None``, will return a ctypes void pointer.
Examples
--------
>>> from pygmt.clib import Session
>>> from pygmt.helpers import GMTTempFile
>>>
>>> # Read dataset from a virtual file
>>> with Session() as lib:
... with GMTTempFile(suffix=".txt") as tmpfile:
... with open(tmpfile.name, mode="w") as fp:
... print("1.0 2.0 3.0 TEXT", file=fp)
... with lib.open_virtualfile(
... "GMT_IS_DATASET", "GMT_IS_PLP", "GMT_OUT", None
... ) as vfile:
... lib.call_module("read", f"{tmpfile.name} {vfile} -Td")
... # Read the virtual file as a void pointer
... void_pointer = lib.read_virtualfile(vfile)
... assert isinstance(void_pointer, int) # void pointer is an int
... # Read the virtual file as a dataset
... data_pointer = lib.read_virtualfile(vfile, kind="dataset")
... assert isinstance(data_pointer, ctp.POINTER(_GMT_DATASET))
>>>
>>> # Read grid from a virtual file
>>> with Session() as lib:
... with lib.open_virtualfile(
... "GMT_IS_GRID", "GMT_IS_SURFACE", "GMT_OUT", None
... ) as vfile:
... lib.call_module("read", f"@earth_relief_01d_g {vfile} -Tg")
... # Read the virtual file as a void pointer
... void_pointer = lib.read_virtualfile(vfile)
... assert isinstance(void_pointer, int) # void pointer is an int
... data_pointer = lib.read_virtualfile(vfile, kind="grid")
... assert isinstance(data_pointer, ctp.POINTER(_GMT_GRID))
Returns
-------
Pointer to the GMT data container. If ``kind`` is None, returns a ctypes void
pointer instead.
"""
c_read_virtualfile = self.get_libgmt_func(
"GMT_Read_VirtualFile",
argtypes=[ctp.c_void_p, ctp.c_char_p],
restype=ctp.c_void_p,
)
pointer = c_read_virtualfile(self.session_pointer, vfname.encode())
# The GMT C API function GMT_Read_VirtualFile returns a void pointer. It usually
# needs to be cast into a pointer to a GMT data container (e.g., _GMT_GRID or
# _GMT_DATASET).
if kind is None: # Return the ctypes void pointer
return pointer
dtype = {"dataset": _GMT_DATASET, "grid": _GMT_GRID}[kind]
return ctp.cast(pointer, ctp.POINTER(dtype))

def extract_region(self):
"""
Extract the WESN bounding box of the currently active figure.
Expand Down
5 changes: 5 additions & 0 deletions pygmt/datatypes/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""
Wrappers for GMT data types.
"""
from pygmt.datatypes.dataset import _GMT_DATASET
from pygmt.datatypes.grid import _GMT_GRID
8 changes: 8 additions & 0 deletions pygmt/datatypes/dataset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""
Wrapper for the GMT_DATASET data type.
"""
import ctypes as ctp


class _GMT_DATASET(ctp.Structure): # noqa: N801
pass
8 changes: 8 additions & 0 deletions pygmt/datatypes/grid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""
Wrapper for the GMT_GRID data type.
"""
import ctypes as ctp


class _GMT_GRID(ctp.Structure): # noqa: N801
pass

0 comments on commit 2d78563

Please sign in to comment.