diff --git a/pygmt/clib/session.py b/pygmt/clib/session.py index c8d97fa459b..1dd04a42907 100644 --- a/pygmt/clib/session.py +++ b/pygmt/clib/session.py @@ -10,7 +10,6 @@ import warnings from contextlib import contextmanager, nullcontext -from pygmt.datatypes import GMT_GRID import numpy as np import pandas as pd from packaging.version import Version @@ -22,6 +21,7 @@ vectors_to_arrays, ) from pygmt.clib.loading import load_libgmt +from pygmt.datatypes import GMT_GRID from pygmt.exceptions import ( GMTCLibError, GMTCLibNoSessionError, @@ -1627,7 +1627,8 @@ def virtualfile_from_data( def read_virtualfile(self, vfname, kind=None): """ - Read data from a virtual file and cast it into a GMT data container if requested. + Read data from a virtual file and cast it into a GMT data container if + requested. Parameters ---------- @@ -1665,27 +1666,37 @@ def read_virtualfile(self, vfname, kind=None): return ctp.cast(pointer, ctp.POINTER(type)) @contextmanager - def virtualfile_to_data(self, kind): + def virtualfile_to_data(self, kind, fname=None): """ - Create a virtual file for writing a GMT data container. + Create a virtual file for writing a GMT data container or yield the + output file name. Parameters ---------- kind : str The kind of data container to create. Choose from "grid" or - "dataset". + "dataset". It has no effect if ``fname`` is given. + + fname : str or None + If given, yield the output file name instead of the virtual file. Yields ------ vfile : str - Name of the virtual file. + Name of the virtual file or the output file name. """ - family, geometry = { - "grid": ("GMT_IS_GRID", "GMT_IS_SURFACE"), - "dataset": ("GMT_IS_DATASET", "GMT_IS_PLP"), - }[kind] - with self.open_virtual_file(family, geometry, "GMT_OUT", None) as vfile: - yield vfile + # If fname is given, yield the output file name. + if fname is not None: + yield fname + # Otherwise, create a virtual file for writing a GMT data container. + else: + # Determine the family and geometry of the data container based on 'kind'. + family, geometry = { + "grid": ("GMT_IS_GRID", "GMT_IS_SURFACE"), + "dataset": ("GMT_IS_DATASET", "GMT_IS_PLP"), + }[kind] + with self.open_virtual_file(family, geometry, "GMT_OUT", None) as vfile: + yield vfile @contextmanager def virtualfile_from_gmtgrid(self, grid_pointer): diff --git a/pygmt/datatypes.py b/pygmt/datatypes.py index 03af5d84db5..07e2d5308cc 100644 --- a/pygmt/datatypes.py +++ b/pygmt/datatypes.py @@ -33,7 +33,8 @@ class GMT_GRID_HEADER(ctp.Structure): """ Structure for GMT grid header. - See https://docs.generic-mapping-tools.org/dev/devdocs/api.html#gmt-grid + See + https://docs.generic-mapping-tools.org/dev/devdocs/api.html#gmt-grid for definition. """ diff --git a/pygmt/src/grdcut.py b/pygmt/src/grdcut.py index de0f8a36bdd..088d84d3510 100644 --- a/pygmt/src/grdcut.py +++ b/pygmt/src/grdcut.py @@ -100,15 +100,14 @@ def grdcut(grid, outgrid=None, **kwargs): with Session() as lib: with lib.virtualfile_from_data( check_kind="raster", data=grid - ) as infile, lib.virtualfile_to_data(kind="grid") as outfile: - kwargs["G"] = f"{outfile}" + ) as invfile, lib.virtualfile_to_data(kind="grid", fname=outgrid) as outvfile: + kwargs["G"] = f"{outvfile}" lib.call_module( - module="grdcut", args=build_arg_string(kwargs, infile=infile) + module="grdcut", args=build_arg_string(kwargs, infile=invfile) ) + # Output to a file or return an xarray.DataArray object if outgrid is not None: - lib.call_module("write", f"{outfile} {outgrid} -Tg") return None - - gmtgrid = lib.read_virtualfile_to_data(outfile, kind="grid") + gmtgrid = lib.read_virtualfile(outvfile, kind="grid") return gmtgrid.contents.to_dataarray()