Skip to content

Commit 759e266

Browse files
committed
Pass GMT_GRID virtual file to GMT C API
1 parent 9da3ea3 commit 759e266

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

doc/api/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,3 +319,4 @@ Low level access (these are mostly used by the :mod:`pygmt.clib` package):
319319
clib.Session.virtualfile_from_grid
320320
clib.Session.virtualfile_from_matrix
321321
clib.Session.virtualfile_from_vectors
322+
clib.Session.virtualfile_from_xrgrid

pygmt/clib/session.py

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
)
2727
from pygmt.clib.loading import load_libgmt
2828
from pygmt.datatypes import _GMT_DATASET, _GMT_GRID
29+
from pygmt.datatypes.header import gmt_grdfloat
2930
from pygmt.exceptions import (
3031
GMTCLibError,
3132
GMTCLibNoSessionError,
@@ -325,6 +326,22 @@ def get_libgmt_func(self, name, argtypes=None, restype=None):
325326
function.restype = restype
326327
return function
327328

329+
def set_allocmode(self, family, obj):
330+
"""
331+
Set allocation mode of object to external.
332+
"""
333+
c_set_allocmode = self.get_libgmt_func(
334+
"GMT_Set_AllocMode",
335+
argtypes=[ctp.c_void_p, ctp.c_uint, ctp.c_void_p],
336+
restype=ctp.c_void_p,
337+
)
338+
family_int = self._parse_constant(family, valid=FAMILIES, valid_modifiers=VIAS)
339+
status = c_set_allocmode(self.session_pointer, family_int, obj)
340+
if status:
341+
raise GMTCLibError(
342+
f"Failed to set allocation mode of object to external:\n{self._error_message}"
343+
)
344+
328345
def create(self, name):
329346
"""
330347
Create a new GMT C API session.
@@ -1597,7 +1614,7 @@ def virtualfile_in( # noqa: PLR0912
15971614
"file": contextlib.nullcontext,
15981615
"arg": contextlib.nullcontext,
15991616
"geojson": tempfile_from_geojson,
1600-
"grid": self.virtualfile_from_grid,
1617+
"grid": self.virtualfile_from_xrgrid,
16011618
"image": tempfile_from_image,
16021619
# Note: virtualfile_from_matrix is not used because a matrix can be
16031620
# converted to vectors instead, and using vectors allows for better
@@ -1806,6 +1823,45 @@ def read_virtualfile(
18061823
dtype = {"dataset": _GMT_DATASET, "grid": _GMT_GRID}[kind]
18071824
return ctp.cast(pointer, ctp.POINTER(dtype))
18081825

1826+
@contextlib.contextmanager
1827+
def virtualfile_from_xrgrid(self, xrgrid):
1828+
"""
1829+
Create a virtual file from an xarray.DataArray object.
1830+
"""
1831+
family = "GMT_IS_GRID"
1832+
geometry = "GMT_IS_SURFACE"
1833+
matrix, region, inc = dataarray_to_matrix(xrgrid)
1834+
1835+
_gtype = {0: "GMT_GRID_IS_CARTESIAN", 1: "GMT_GRID_IS_GEO"}[xrgrid.gmt.gtype]
1836+
_reg = {0: "GMT_GRID_NODE_REG", 1: "GMT_GRID_PIXEL_REG"}[
1837+
xrgrid.gmt.registration
1838+
]
1839+
1840+
data = self.create_data(
1841+
family,
1842+
geometry,
1843+
mode=f"GMT_CONTAINER_ONLY|{_gtype}",
1844+
ranges=region,
1845+
inc=inc,
1846+
registration=_reg,
1847+
pad=self["GMT_PAD_DEFAULT"],
1848+
)
1849+
if Version(self._info["version"]) < Version("6.5.0"):
1850+
# Upstream bug fixed in GMT>=6.5.0
1851+
self.set_allocmode(family, data)
1852+
1853+
gmtgrid = ctp.cast(data, ctp.POINTER(_GMT_GRID))
1854+
header = gmtgrid.contents.header.contents
1855+
header.z_min, header.z_max = matrix.min(), matrix.max()
1856+
1857+
matrix = np.pad(matrix, self["GMT_PAD_DEFAULT"]).astype(np.float32)
1858+
gmtgrid.contents.data = matrix.ctypes.data_as(ctp.POINTER(gmt_grdfloat))
1859+
1860+
with self.open_virtualfile(
1861+
family, geometry, "GMT_IN|GMT_IS_REFERENCE", gmtgrid
1862+
) as vfile:
1863+
yield vfile
1864+
18091865
def virtualfile_to_dataset(
18101866
self,
18111867
vfname: str,

0 commit comments

Comments
 (0)