Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions gmt/clib/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ def __init__(self, libname='libgmt'):
self._c_write_data = None
self._c_open_virtualfile = None
self._c_close_virtualfile = None
self._c_read_virtualfile = None
self._bind_clib_functions(libname)

@property
Expand Down Expand Up @@ -206,6 +207,10 @@ def _bind_clib_functions(self, libname):
self._c_close_virtualfile.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
self._c_close_virtualfile.restype = ctypes.c_int

self._c_read_virtualfile = self._libgmt.GMT_Read_VirtualFile
self._c_read_virtualfile.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
self._c_read_virtualfile.restype = ctypes.c_void_p

def __enter__(self):
"""
Start the GMT session and keep the session argument.
Expand Down Expand Up @@ -880,6 +885,31 @@ def open_virtual_file(self, family, geometry, direction, data):
raise GMTCLibError(
"Failed to close virtual file '{}'.".format(vfname))

def read_virtual_file(self, vfname):
"""
Read a GMT data container from an open virtual file.

If the virtual file was created using a data container allocated in
Python, then reading will return a pointer to that container.
Otherwise, GMT will allocate the container and will also destroy it
when the file is closed and the session ends. To retain that container,
copy it to Python-owned memory.

Parameters
----------
vfname : str
The name of the virtual file (created using
:meth:`~gmt.clib.LibGMT.open_virtual_file`)

Returns
-------
container_pointer : ctypes.c_void_p
A void pointer to the data container stored in the virtual file.
"""
container_pointer = self._c_read_virtualfile(self.current_session,
vfname.encode())
return container_pointer

@contextmanager
def vectors_to_vfile(self, *vectors):
"""
Expand Down
95 changes: 95 additions & 0 deletions gmt/clib/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# pylint: disable=too-few-public-methods
"""
Wrappers for GMT data structures.

Useful if you need to access the internal values of a GMT data structure or
pass it along as something other than a void pointer.
"""
import ctypes


class LUT(ctypes.Structure):
"""
Wrapper for GMT_LUT (look up table).
Required for Palette.
"""

_fields_ = [
('z_low', ctypes.c_double),
('z_high', ctypes.c_double),
('i_dz', ctypes.c_double),
('rgb_low', ctypes.c_double*4),
('rgb_high', ctypes.c_double*4),
('rgb_diff', ctypes.c_double*4),
('hsv_low', ctypes.c_double*4),
('hsv_high', ctypes.c_double*4),
('hsv_diff', ctypes.c_double*4),
('annot', ctypes.c_uint), # 1 for Lower, 2 for Upper, 3 for Both
('skip', ctypes.c_uint), # true means skip this slice
# Used as void pointer so we don't have to wrap GMT_FILL as well
('fill', ctypes.c_void_p), # For patterns instead of color
('label', ctypes.c_char_p), # For non-number labels
]


class BFN(ctypes.Structure):
"""
Wrapper for GMT_BFN (back-, fore-, and nan-colors).
Required for Palette.
"""

_fields_ = [
('rgb', ctypes.c_double*4), # Red, green, blue, and alpha
('hsv', ctypes.c_double*4), # Hue, saturation, value, alpha
('skip', ctypes.c_uint), # true means skip this slice
# Used as void pointer so we don't have to wrap GMT_FILL as well
('fill', ctypes.c_void_p), # For patterns instead of color
]


class Palette(ctypes.Structure):
"""
Wrapper for GMT_PALETTE (stores a color palette table, or CPT).
Holds all pen, color, and fill-related parameters.
"""

_fields_ = [
# CPT lookup table read by gmtlib_read_cpt
('data', ctypes.POINTER(LUT)),
# Structures with back/fore/nan colors
('bfn', BFN*3),
# Number of CPT header records (0 if no header)
('n_headers', ctypes.c_uint),
# Number of colors in CPT lookup table
('n_colors', ctypes.c_uint),
# Flags controlling use of BFN colors
('mode', ctypes.c_uint),
# RGB, HSV, CMYK
('model', ctypes.c_uint),
# If 1 then we must wrap around to find color - can never be F or B
('is_wrapping', ctypes.c_uint),
# true if only grayshades are needed
('is_gray', ctypes.c_uint),
# true if only black and white are needed
('is_bw', ctypes.c_uint),
# true if continuous color tables have been given
('is_continuous', ctypes.c_uint),
# true if CPT contains any patterns
('has_pattern', ctypes.c_uint),
# true if CPT is hinged at hinge (below)
('has_hinge', ctypes.c_uint),
# true if CPT has a natural range (minmax below)
('has_range', ctypes.c_uint),
# true if CPT applies to categorical data
('categorical', ctypes.c_uint),
# Min/max z-value for a default range, if given
('minmax', ctypes.c_double*2),
# z-value for hinged CPTs
('hinge', ctypes.c_double),
# z-length of active CPT
('wrap_length', ctypes.c_double),
# Array with all CPT header records, if any)
('header', ctypes.POINTER(ctypes.c_char_p)),
# Book-keeping variables "hidden" from the API
('hidden', ctypes.c_void_p),
]