From 700fb2d428c9f149e6311741206991859c4dc3c1 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Mon, 21 Mar 2022 14:09:03 +0800 Subject: [PATCH 1/5] Refractor build_arg_string to also deal with infile and outfile --- pygmt/helpers/utils.py | 6 +++++- pygmt/src/contour.py | 3 +-- pygmt/src/grdinfo.py | 6 +++--- pygmt/src/which.py | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/pygmt/helpers/utils.py b/pygmt/helpers/utils.py index ea7a89873e7..54ec746a3e1 100644 --- a/pygmt/helpers/utils.py +++ b/pygmt/helpers/utils.py @@ -119,7 +119,7 @@ def dummy_context(arg): yield arg -def build_arg_string(kwargs): +def build_arg_string(kwargs, infile=None, outfile=None): r""" Transform keyword arguments into a GMT argument string. @@ -213,6 +213,10 @@ def build_arg_string(kwargs): # remove any spaces in PROJ4 string _value = str(kwargs[key]).replace(" ", "") gmt_args.append(rf"-{key}{_value}") + if infile: + gmt_args.append(str(infile)) + if outfile: + gmt_args.append("->" + str(outfile)) return " ".join(sorted(gmt_args)) diff --git a/pygmt/src/contour.py b/pygmt/src/contour.py index f64cd5e0c15..17e275e6b70 100644 --- a/pygmt/src/contour.py +++ b/pygmt/src/contour.py @@ -132,5 +132,4 @@ def contour(self, data=None, x=None, y=None, z=None, **kwargs): check_kind="vector", data=data, x=x, y=y, z=z, required_z=True ) with file_context as fname: - arg_str = " ".join([fname, build_arg_string(kwargs)]) - lib.call_module("contour", arg_str) + lib.call_module("contour", build_arg_string(kwargs, infile=fname)) diff --git a/pygmt/src/grdinfo.py b/pygmt/src/grdinfo.py index 8e5dbd22e3e..8057f21c74c 100644 --- a/pygmt/src/grdinfo.py +++ b/pygmt/src/grdinfo.py @@ -114,9 +114,9 @@ def grdinfo(grid, **kwargs): with Session() as lib: file_context = lib.virtualfile_from_data(check_kind="raster", data=grid) with file_context as infile: - arg_str = " ".join( - [infile, build_arg_string(kwargs), "->" + outfile.name] + lib.call_module( + "grdinfo", + build_arg_string(kwargs, infile=infile, outfile=outfile.name), ) - lib.call_module("grdinfo", arg_str) result = outfile.read() return result diff --git a/pygmt/src/which.py b/pygmt/src/which.py index 3a5afb3da1e..7e08a742c95 100644 --- a/pygmt/src/which.py +++ b/pygmt/src/which.py @@ -60,9 +60,10 @@ def which(fname, **kwargs): If the file is not found. """ with GMTTempFile() as tmpfile: - arg_str = " ".join([fname, build_arg_string(kwargs), "->" + tmpfile.name]) with Session() as lib: - lib.call_module("which", arg_str) + lib.call_module( + "which", build_arg_string(kwargs, infile=fname, outfile=tmpfile.name) + ) path = tmpfile.read().strip() if not path: _fname = fname.replace(" ", "', '") From 6c6dc3e17eb0a8f120a3ef48cee1cbb9368f5f9a Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Wed, 30 Mar 2022 16:00:12 +0800 Subject: [PATCH 2/5] Refactor more functions --- pygmt/helpers/utils.py | 4 ++++ pygmt/src/blockm.py | 6 ++++-- pygmt/src/grd2cpt.py | 8 +++----- pygmt/src/grd2xyz.py | 5 +++-- pygmt/src/grdclip.py | 3 +-- pygmt/src/grdcontour.py | 3 +-- pygmt/src/grdcut.py | 3 +-- pygmt/src/grdfill.py | 3 +-- pygmt/src/grdfilter.py | 3 +-- pygmt/src/grdgradient.py | 3 +-- pygmt/src/grdhisteq.py | 3 +-- pygmt/src/grdimage.py | 3 +-- pygmt/src/grdlandmask.py | 3 +-- pygmt/src/grdproject.py | 3 +-- pygmt/src/grdsample.py | 3 +-- pygmt/src/grdtrack.py | 6 +++--- pygmt/src/grdview.py | 3 +-- pygmt/src/grdvolume.py | 6 ++++-- pygmt/src/histogram.py | 3 +-- pygmt/src/image.py | 3 +-- pygmt/src/info.py | 5 ++--- pygmt/src/legend.py | 3 +-- pygmt/src/makecpt.py | 4 ++-- pygmt/src/meca.py | 3 +-- pygmt/src/nearneighbor.py | 5 +++-- pygmt/src/plot.py | 3 +-- pygmt/src/plot3d.py | 3 +-- pygmt/src/project.py | 6 ++---- pygmt/src/rose.py | 4 +--- pygmt/src/select.py | 6 ++++-- pygmt/src/sph2grd.py | 3 +-- pygmt/src/sphdistance.py | 4 +--- pygmt/src/sphinterpolate.py | 5 +++-- pygmt/src/surface.py | 5 +++-- pygmt/src/text.py | 3 +-- pygmt/src/triangulate.py | 5 +++-- pygmt/src/velo.py | 3 +-- pygmt/src/wiggle.py | 3 +-- pygmt/src/x2sys_cross.py | 8 ++++++-- pygmt/src/x2sys_init.py | 3 +-- pygmt/src/xyz2grd.py | 3 +-- 41 files changed, 75 insertions(+), 89 deletions(-) diff --git a/pygmt/helpers/utils.py b/pygmt/helpers/utils.py index 54ec746a3e1..2b130773d73 100644 --- a/pygmt/helpers/utils.py +++ b/pygmt/helpers/utils.py @@ -140,6 +140,10 @@ def build_arg_string(kwargs, infile=None, outfile=None): ---------- kwargs : dict Parsed keyword arguments. + infile : str or pathlib.Path + The input file. + outfile : str or pathlib.Path + The output file. Returns ------- diff --git a/pygmt/src/blockm.py b/pygmt/src/blockm.py index 75693524d6c..f55f1bf36c7 100644 --- a/pygmt/src/blockm.py +++ b/pygmt/src/blockm.py @@ -51,8 +51,10 @@ def _blockm(block_method, data, x, y, z, outfile, **kwargs): with table_context as infile: if outfile is None: outfile = tmpfile.name - arg_str = " ".join([infile, build_arg_string(kwargs), "->" + outfile]) - lib.call_module(module=block_method, args=arg_str) + lib.call_module( + module=block_method, + args=build_arg_string(kwargs, infile=infile, outfile=outfile), + ) # Read temporary csv output to a pandas table if outfile == tmpfile.name: # if user did not set outfile, return pd.DataFrame diff --git a/pygmt/src/grd2cpt.py b/pygmt/src/grd2cpt.py index 2173fe30bc7..8e81fa4a14c 100644 --- a/pygmt/src/grd2cpt.py +++ b/pygmt/src/grd2cpt.py @@ -166,12 +166,10 @@ def grd2cpt(grid, **kwargs): file_context = lib.virtualfile_from_data(check_kind="raster", data=grid) with file_context as infile: if "H" not in kwargs: # if no output is set - arg_str = " ".join([infile, build_arg_string(kwargs)]) + arg_str = build_arg_string(kwargs, infile=infile) if "H" in kwargs: # if output is set - outfile = kwargs.pop("H") + outfile, kwargs["H"] = kwargs["H"], True if not outfile or not isinstance(outfile, str): raise GMTInvalidInput("'output' should be a proper file name.") - arg_str = " ".join( - [infile, build_arg_string(kwargs), f"-H > {outfile}"] - ) + arg_str = build_arg_string(kwargs, infile=infile, outfile=outfile) lib.call_module("grd2cpt", arg_str) diff --git a/pygmt/src/grd2xyz.py b/pygmt/src/grd2xyz.py index 46797022abf..54f03fdc5ae 100644 --- a/pygmt/src/grd2xyz.py +++ b/pygmt/src/grd2xyz.py @@ -178,8 +178,9 @@ def grd2xyz(grid, output_type="pandas", outfile=None, **kwargs): with file_context as infile: if outfile is None: outfile = tmpfile.name - arg_str = " ".join([infile, build_arg_string(kwargs), "->" + outfile]) - lib.call_module("grd2xyz", arg_str) + lib.call_module( + "grd2xyz", build_arg_string(kwargs, infile=infile, outfile=outfile) + ) # Read temporary csv output to a pandas table if outfile == tmpfile.name: # if user did not set outfile, return pd.DataFrame diff --git a/pygmt/src/grdclip.py b/pygmt/src/grdclip.py index cd98e3a709b..f7c4d951d31 100644 --- a/pygmt/src/grdclip.py +++ b/pygmt/src/grdclip.py @@ -107,7 +107,6 @@ def grdclip(grid, **kwargs): if "G" not in kwargs: # if outgrid is unset, output to tempfile kwargs.update({"G": tmpfile.name}) outgrid = kwargs["G"] - arg_str = " ".join([infile, build_arg_string(kwargs)]) - lib.call_module("grdclip", arg_str) + lib.call_module("grdclip", build_arg_string(kwargs, infile=infile)) return load_dataarray(outgrid) if outgrid == tmpfile.name else None diff --git a/pygmt/src/grdcontour.py b/pygmt/src/grdcontour.py index c3b63fbaefb..98a214a2fd3 100644 --- a/pygmt/src/grdcontour.py +++ b/pygmt/src/grdcontour.py @@ -100,5 +100,4 @@ def grdcontour(self, grid, **kwargs): with Session() as lib: file_context = lib.virtualfile_from_data(check_kind="raster", data=grid) with file_context as fname: - arg_str = " ".join([fname, build_arg_string(kwargs)]) - lib.call_module("grdcontour", arg_str) + lib.call_module("grdcontour", build_arg_string(kwargs, infile=fname)) diff --git a/pygmt/src/grdcut.py b/pygmt/src/grdcut.py index 86334ca5ed9..5c4f34efe19 100644 --- a/pygmt/src/grdcut.py +++ b/pygmt/src/grdcut.py @@ -109,7 +109,6 @@ def grdcut(grid, **kwargs): if "G" not in kwargs: # if outgrid is unset, output to tempfile kwargs.update({"G": tmpfile.name}) outgrid = kwargs["G"] - arg_str = " ".join([infile, build_arg_string(kwargs)]) - lib.call_module("grdcut", arg_str) + lib.call_module("grdcut", build_arg_string(kwargs, infile=infile)) return load_dataarray(outgrid) if outgrid == tmpfile.name else None diff --git a/pygmt/src/grdfill.py b/pygmt/src/grdfill.py index 0f44144e237..aa7623b9d5b 100644 --- a/pygmt/src/grdfill.py +++ b/pygmt/src/grdfill.py @@ -72,7 +72,6 @@ def grdfill(grid, **kwargs): if "G" not in kwargs: # if outgrid is unset, output to tempfile kwargs.update({"G": tmpfile.name}) outgrid = kwargs["G"] - arg_str = " ".join([infile, build_arg_string(kwargs)]) - lib.call_module("grdfill", arg_str) + lib.call_module("grdfill", build_arg_string(kwargs, infile=infile)) return load_dataarray(outgrid) if outgrid == tmpfile.name else None diff --git a/pygmt/src/grdfilter.py b/pygmt/src/grdfilter.py index 0c8116ac708..6492f42fbbc 100644 --- a/pygmt/src/grdfilter.py +++ b/pygmt/src/grdfilter.py @@ -148,7 +148,6 @@ def grdfilter(grid, **kwargs): if "G" not in kwargs: # if outgrid is unset, output to tempfile kwargs.update({"G": tmpfile.name}) outgrid = kwargs["G"] - arg_str = " ".join([infile, build_arg_string(kwargs)]) - lib.call_module("grdfilter", arg_str) + lib.call_module("grdfilter", build_arg_string(kwargs, infile=infile)) return load_dataarray(outgrid) if outgrid == tmpfile.name else None diff --git a/pygmt/src/grdgradient.py b/pygmt/src/grdgradient.py index b70c2cbf980..70200d9bc25 100644 --- a/pygmt/src/grdgradient.py +++ b/pygmt/src/grdgradient.py @@ -177,7 +177,6 @@ def grdgradient(grid, **kwargs): if "G" not in kwargs: # if outgrid is unset, output to tempfile kwargs.update({"G": tmpfile.name}) outgrid = kwargs["G"] - arg_str = " ".join([infile, build_arg_string(kwargs)]) - lib.call_module("grdgradient", arg_str) + lib.call_module("grdgradient", build_arg_string(kwargs, infile=infile)) return load_dataarray(outgrid) if outgrid == tmpfile.name else None diff --git a/pygmt/src/grdhisteq.py b/pygmt/src/grdhisteq.py index 09555d05e94..c2d26a4ab56 100644 --- a/pygmt/src/grdhisteq.py +++ b/pygmt/src/grdhisteq.py @@ -112,8 +112,7 @@ def _grdhisteq(grid, output_type, **kwargs): with Session() as lib: file_context = lib.virtualfile_from_data(check_kind="raster", data=grid) with file_context as infile: - arg_str = " ".join([infile, build_arg_string(kwargs)]) - lib.call_module("grdhisteq", arg_str) + lib.call_module("grdhisteq", build_arg_string(kwargs, infile=infile)) if output_type == "file": return None diff --git a/pygmt/src/grdimage.py b/pygmt/src/grdimage.py index 52cb637e32a..c50057cd640 100644 --- a/pygmt/src/grdimage.py +++ b/pygmt/src/grdimage.py @@ -171,5 +171,4 @@ def grdimage(self, grid, **kwargs): kwargs["I"] = stack.enter_context(shading_context) fname = stack.enter_context(file_context) - arg_str = " ".join([fname, build_arg_string(kwargs)]) - lib.call_module("grdimage", arg_str) + lib.call_module("grdimage", build_arg_string(kwargs, infile=fname)) diff --git a/pygmt/src/grdlandmask.py b/pygmt/src/grdlandmask.py index 93a9c369582..e6a39657bc2 100644 --- a/pygmt/src/grdlandmask.py +++ b/pygmt/src/grdlandmask.py @@ -109,7 +109,6 @@ def grdlandmask(**kwargs): if "G" not in kwargs: # if outgrid is unset, output to tempfile kwargs.update({"G": tmpfile.name}) outgrid = kwargs["G"] - arg_str = build_arg_string(kwargs) - lib.call_module("grdlandmask", arg_str) + lib.call_module("grdlandmask", build_arg_string(kwargs)) return load_dataarray(outgrid) if outgrid == tmpfile.name else None diff --git a/pygmt/src/grdproject.py b/pygmt/src/grdproject.py index 399d112b828..e27832876fb 100644 --- a/pygmt/src/grdproject.py +++ b/pygmt/src/grdproject.py @@ -121,7 +121,6 @@ def grdproject(grid, **kwargs): if "G" not in kwargs: # if outgrid is unset, output to tempfile kwargs.update({"G": tmpfile.name}) outgrid = kwargs["G"] - arg_str = " ".join([infile, build_arg_string(kwargs)]) - lib.call_module("grdproject", arg_str) + lib.call_module("grdproject", build_arg_string(kwargs, infile=infile)) return load_dataarray(outgrid) if outgrid == tmpfile.name else None diff --git a/pygmt/src/grdsample.py b/pygmt/src/grdsample.py index f7b76cc469e..4e84e0827ee 100644 --- a/pygmt/src/grdsample.py +++ b/pygmt/src/grdsample.py @@ -99,7 +99,6 @@ def grdsample(grid, **kwargs): if "G" not in kwargs: # if outgrid is unset, output to tempfile kwargs.update({"G": tmpfile.name}) outgrid = kwargs["G"] - arg_str = " ".join([infile, build_arg_string(kwargs)]) - lib.call_module("grdsample", arg_str) + lib.call_module("grdsample", build_arg_string(kwargs, infile=infile)) return load_dataarray(outgrid) if outgrid == tmpfile.name else None diff --git a/pygmt/src/grdtrack.py b/pygmt/src/grdtrack.py index 1f15161b99c..f0b9306ce6f 100644 --- a/pygmt/src/grdtrack.py +++ b/pygmt/src/grdtrack.py @@ -300,10 +300,10 @@ def grdtrack(points, grid, newcolname=None, outfile=None, **kwargs): kwargs.update({"G": grdfile}) if outfile is None: # Output to tmpfile if outfile is not set outfile = tmpfile.name - arg_str = " ".join( - [csvfile, build_arg_string(kwargs), "->" + outfile] + lib.call_module( + module="grdtrack", + args=build_arg_string(kwargs, infile=csvfile, outfile=outfile), ) - lib.call_module(module="grdtrack", args=arg_str) # Read temporary csv output to a pandas table if outfile == tmpfile.name: # if user did not set outfile, return pd.DataFrame diff --git a/pygmt/src/grdview.py b/pygmt/src/grdview.py index 404fc490cc0..fca45686abd 100644 --- a/pygmt/src/grdview.py +++ b/pygmt/src/grdview.py @@ -137,5 +137,4 @@ def grdview(self, grid, **kwargs): f"Unrecognized data type for drapegrid: {type(drapegrid)}" ) fname = stack.enter_context(file_context) - arg_str = " ".join([fname, build_arg_string(kwargs)]) - lib.call_module("grdview", arg_str) + lib.call_module("grdview", build_arg_string(kwargs, infile=fname)) diff --git a/pygmt/src/grdvolume.py b/pygmt/src/grdvolume.py index 0beb3d4523f..6d088671382 100644 --- a/pygmt/src/grdvolume.py +++ b/pygmt/src/grdvolume.py @@ -114,8 +114,10 @@ def grdvolume(grid, output_type="pandas", outfile=None, **kwargs): with file_context as infile: if outfile is None: outfile = tmpfile.name - arg_str = " ".join([infile, build_arg_string(kwargs), "->" + outfile]) - lib.call_module("grdvolume", arg_str) + lib.call_module( + "grdvolume", + build_arg_string(kwargs, infile=infile, outfile=outfile), + ) # Read temporary csv output to a pandas table if outfile == tmpfile.name: # if user did not set outfile, return pd.DataFrame diff --git a/pygmt/src/histogram.py b/pygmt/src/histogram.py index 93bf9e6721c..7e8af4057d3 100644 --- a/pygmt/src/histogram.py +++ b/pygmt/src/histogram.py @@ -148,5 +148,4 @@ def histogram(self, data, **kwargs): with Session() as lib: file_context = lib.virtualfile_from_data(check_kind="vector", data=data) with file_context as infile: - arg_str = " ".join([infile, build_arg_string(kwargs)]) - lib.call_module("histogram", arg_str) + lib.call_module("histogram", build_arg_string(kwargs, infile=infile)) diff --git a/pygmt/src/image.py b/pygmt/src/image.py index 5b883722887..c0da5898861 100644 --- a/pygmt/src/image.py +++ b/pygmt/src/image.py @@ -64,5 +64,4 @@ def image(self, imagefile, **kwargs): """ kwargs = self._preprocess(**kwargs) # pylint: disable=protected-access with Session() as lib: - arg_str = " ".join([imagefile, build_arg_string(kwargs)]) - lib.call_module("image", arg_str) + lib.call_module("image", build_arg_string(kwargs, infile=imagefile)) diff --git a/pygmt/src/info.py b/pygmt/src/info.py index 510723c95e2..00f8f7ed66e 100644 --- a/pygmt/src/info.py +++ b/pygmt/src/info.py @@ -85,10 +85,9 @@ def info(data, **kwargs): file_context = lib.virtualfile_from_data(check_kind="vector", data=data) with GMTTempFile() as tmpfile: with file_context as fname: - arg_str = " ".join( - [fname, build_arg_string(kwargs), "->" + tmpfile.name] + lib.call_module( + "info", build_arg_string(kwargs, infile=fname, outfile=tmpfile.name) ) - lib.call_module("info", arg_str) result = tmpfile.read() if any(arg in kwargs for arg in ["C", "I", "T"]): diff --git a/pygmt/src/legend.py b/pygmt/src/legend.py index 168f826ee68..6379b65e417 100644 --- a/pygmt/src/legend.py +++ b/pygmt/src/legend.py @@ -87,5 +87,4 @@ def legend(self, spec=None, position="JTR+jTR+o0.2c", box="+gwhite+p1p", **kwarg specfile = spec else: raise GMTInvalidInput(f"Unrecognized data type: {type(spec)}") - arg_str = " ".join([specfile, build_arg_string(kwargs)]) - lib.call_module("legend", arg_str) + lib.call_module("legend", build_arg_string(kwargs, infile=specfile)) diff --git a/pygmt/src/makecpt.py b/pygmt/src/makecpt.py index bf52be37f80..ad0dc442a76 100644 --- a/pygmt/src/makecpt.py +++ b/pygmt/src/makecpt.py @@ -152,8 +152,8 @@ def makecpt(**kwargs): if "H" not in kwargs: # if no output is set arg_str = build_arg_string(kwargs) elif "H" in kwargs: # if output is set - outfile = kwargs.pop("H") + outfile, kwargs["H"] = kwargs.pop("H"), True if not outfile or not isinstance(outfile, str): raise GMTInvalidInput("'output' should be a proper file name.") - arg_str = " ".join([build_arg_string(kwargs), f"-H > {outfile}"]) + arg_str = build_arg_string(kwargs, outfile=outfile) lib.call_module(module="makecpt", args=arg_str) diff --git a/pygmt/src/meca.py b/pygmt/src/meca.py index 85bf48d97b7..c4b2ee9bfc3 100644 --- a/pygmt/src/meca.py +++ b/pygmt/src/meca.py @@ -464,5 +464,4 @@ def update_pointers(data_pointers): else: raise GMTInvalidInput(f"Unrecognized data type: {type(spec)}") with file_context as fname: - arg_str = " ".join([fname, build_arg_string(kwargs)]) - lib.call_module("meca", arg_str) + lib.call_module("meca", build_arg_string(kwargs, infile=fname)) diff --git a/pygmt/src/nearneighbor.py b/pygmt/src/nearneighbor.py index 1fe7e24bab8..641b5861703 100644 --- a/pygmt/src/nearneighbor.py +++ b/pygmt/src/nearneighbor.py @@ -142,7 +142,8 @@ def nearneighbor(data=None, x=None, y=None, z=None, **kwargs): if "G" not in kwargs: # if outgrid is unset, output to tmpfile kwargs.update({"G": tmpfile.name}) outgrid = kwargs["G"] - arg_str = " ".join([infile, build_arg_string(kwargs)]) - lib.call_module(module="nearneighbor", args=arg_str) + lib.call_module( + module="nearneighbor", args=build_arg_string(kwargs, infile=infile) + ) return load_dataarray(outgrid) if outgrid == tmpfile.name else None diff --git a/pygmt/src/plot.py b/pygmt/src/plot.py index adff9682295..82fd018760d 100644 --- a/pygmt/src/plot.py +++ b/pygmt/src/plot.py @@ -266,5 +266,4 @@ def plot(self, data=None, x=None, y=None, size=None, direction=None, **kwargs): ) with file_context as fname: - arg_str = " ".join([fname, build_arg_string(kwargs)]) - lib.call_module("plot", arg_str) + lib.call_module("plot", build_arg_string(kwargs, infile=fname)) diff --git a/pygmt/src/plot3d.py b/pygmt/src/plot3d.py index faabf34395d..504daf6be04 100644 --- a/pygmt/src/plot3d.py +++ b/pygmt/src/plot3d.py @@ -242,5 +242,4 @@ def plot3d( ) with file_context as fname: - arg_str = " ".join([fname, build_arg_string(kwargs)]) - lib.call_module("plot3d", arg_str) + lib.call_module("plot3d", build_arg_string(kwargs, infile=fname)) diff --git a/pygmt/src/project.py b/pygmt/src/project.py index 1c3f422e638..21a0d8580db 100644 --- a/pygmt/src/project.py +++ b/pygmt/src/project.py @@ -233,11 +233,9 @@ def project(data=None, x=None, y=None, z=None, outfile=None, **kwargs): # Run project on the temporary (csv) data table with table_context as infile: - arg_str = " ".join( - [infile, build_arg_string(kwargs), "->" + outfile] - ) + arg_str = build_arg_string(kwargs, infile=infile, outfile=outfile) else: - arg_str = " ".join([build_arg_string(kwargs), "->" + outfile]) + arg_str = build_arg_string(kwargs, outfile=outfile) lib.call_module(module="project", args=arg_str) # if user did not set outfile, return pd.DataFrame diff --git a/pygmt/src/rose.py b/pygmt/src/rose.py index 842421067e7..02b03851aba 100644 --- a/pygmt/src/rose.py +++ b/pygmt/src/rose.py @@ -211,6 +211,4 @@ def rose(self, data=None, length=None, azimuth=None, **kwargs): ) with file_context as fname: - arg_str = " ".join([fname, build_arg_string(kwargs)]) - - lib.call_module("rose", arg_str) + lib.call_module("rose", build_arg_string(kwargs, infile=fname)) diff --git a/pygmt/src/select.py b/pygmt/src/select.py index c01560ae7d2..34d26850db8 100644 --- a/pygmt/src/select.py +++ b/pygmt/src/select.py @@ -167,8 +167,10 @@ def select(data=None, outfile=None, **kwargs): with table_context as infile: if outfile is None: outfile = tmpfile.name - arg_str = " ".join([infile, build_arg_string(kwargs), "->" + outfile]) - lib.call_module(module="gmtselect", args=arg_str) + lib.call_module( + module="gmtselect", + args=build_arg_string(kwargs, infile=infile, outfile=outfile), + ) # Read temporary csv output to a pandas table if outfile == tmpfile.name: # if user did not set outfile, return pd.DataFrame diff --git a/pygmt/src/sph2grd.py b/pygmt/src/sph2grd.py index 0ca0eaf8c58..e16a368ee9a 100644 --- a/pygmt/src/sph2grd.py +++ b/pygmt/src/sph2grd.py @@ -82,7 +82,6 @@ def sph2grd(data, **kwargs): if "G" not in kwargs: # if outgrid is unset, output to tempfile kwargs.update({"G": tmpfile.name}) outgrid = kwargs["G"] - arg_str = " ".join([infile, build_arg_string(kwargs)]) - lib.call_module("sph2grd", arg_str) + lib.call_module("sph2grd", build_arg_string(kwargs, infile=infile)) return load_dataarray(outgrid) if outgrid == tmpfile.name else None diff --git a/pygmt/src/sphdistance.py b/pygmt/src/sphdistance.py index 63abe94e6e6..c8ac83035b5 100644 --- a/pygmt/src/sphdistance.py +++ b/pygmt/src/sphdistance.py @@ -111,8 +111,6 @@ def sphdistance(data=None, x=None, y=None, **kwargs): if "G" not in kwargs: # if outgrid is unset, output to tempfile kwargs.update({"G": tmpfile.name}) outgrid = kwargs["G"] - arg_str = build_arg_string(kwargs) - arg_str = " ".join([infile, arg_str]) - lib.call_module("sphdistance", arg_str) + lib.call_module("sphdistance", build_arg_string(kwargs, infile=infile)) return load_dataarray(outgrid) if outgrid == tmpfile.name else None diff --git a/pygmt/src/sphinterpolate.py b/pygmt/src/sphinterpolate.py index 15f49904aaa..bf585440a02 100644 --- a/pygmt/src/sphinterpolate.py +++ b/pygmt/src/sphinterpolate.py @@ -63,7 +63,8 @@ def sphinterpolate(data, **kwargs): if "G" not in kwargs: # if outgrid is unset, output to tempfile kwargs.update({"G": tmpfile.name}) outgrid = kwargs["G"] - arg_str = " ".join([infile, build_arg_string(kwargs)]) - lib.call_module("sphinterpolate", arg_str) + lib.call_module( + "sphinterpolate", build_arg_string(kwargs, infile=infile) + ) return load_dataarray(outgrid) if outgrid == tmpfile.name else None diff --git a/pygmt/src/surface.py b/pygmt/src/surface.py index c86ebc41e04..25273e1f2b7 100644 --- a/pygmt/src/surface.py +++ b/pygmt/src/surface.py @@ -101,7 +101,8 @@ def surface(data=None, x=None, y=None, z=None, **kwargs): if "G" not in kwargs: # if outgrid is unset, output to tmpfile kwargs.update({"G": tmpfile.name}) outgrid = kwargs["G"] - arg_str = " ".join([infile, build_arg_string(kwargs)]) - lib.call_module(module="surface", args=arg_str) + lib.call_module( + module="surface", args=build_arg_string(kwargs, infile=infile) + ) return load_dataarray(outgrid) if outgrid == tmpfile.name else None diff --git a/pygmt/src/text.py b/pygmt/src/text.py index e7eac023cbd..2e81596c5aa 100644 --- a/pygmt/src/text.py +++ b/pygmt/src/text.py @@ -233,5 +233,4 @@ def text_( np.atleast_1d(text).astype(str), ) with file_context as fname: - arg_str = " ".join([fname, build_arg_string(kwargs)]) - lib.call_module("text", arg_str) + lib.call_module("text", build_arg_string(kwargs, infile=fname)) diff --git a/pygmt/src/triangulate.py b/pygmt/src/triangulate.py index e50eb086269..3b540080033 100644 --- a/pygmt/src/triangulate.py +++ b/pygmt/src/triangulate.py @@ -134,8 +134,9 @@ def _triangulate( # table output if outgrid is unset, else output to outgrid if (outgrid := kwargs.get("G")) is None: kwargs.update({">": outfile}) - arg_str = " ".join([infile, build_arg_string(kwargs)]) - lib.call_module(module="triangulate", args=arg_str) + lib.call_module( + module="triangulate", args=build_arg_string(kwargs, infile=infile) + ) if output_type == "file": return None diff --git a/pygmt/src/velo.py b/pygmt/src/velo.py index c27128ee270..77d7115b974 100644 --- a/pygmt/src/velo.py +++ b/pygmt/src/velo.py @@ -252,5 +252,4 @@ def velo(self, data=None, **kwargs): file_context = lib.virtualfile_from_data(check_kind="vector", data=data) with file_context as fname: - arg_str = " ".join([fname, build_arg_string(kwargs)]) - lib.call_module("velo", arg_str) + lib.call_module("velo", build_arg_string(kwargs, infile=fname)) diff --git a/pygmt/src/wiggle.py b/pygmt/src/wiggle.py index 5d7dbe6dea0..d3481e22276 100644 --- a/pygmt/src/wiggle.py +++ b/pygmt/src/wiggle.py @@ -113,5 +113,4 @@ def wiggle(self, data=None, x=None, y=None, z=None, **kwargs): ) with file_context as fname: - arg_str = " ".join([fname, build_arg_string(kwargs)]) - lib.call_module("wiggle", arg_str) + lib.call_module("wiggle", build_arg_string(kwargs, infile=fname)) diff --git a/pygmt/src/x2sys_cross.py b/pygmt/src/x2sys_cross.py index de2cdcd2d19..24503ad49e8 100644 --- a/pygmt/src/x2sys_cross.py +++ b/pygmt/src/x2sys_cross.py @@ -220,8 +220,12 @@ def x2sys_cross(tracks=None, outfile=None, **kwargs): fnames = [stack.enter_context(c) for c in file_contexts] if outfile is None: outfile = tmpfile.name - arg_str = " ".join([*fnames, build_arg_string(kwargs), "->" + outfile]) - lib.call_module(module="x2sys_cross", args=arg_str) + lib.call_module( + module="x2sys_cross", + args=build_arg_string( + kwargs, infile=" ".join(fname), outfile=outfile + ), + ) # Read temporary csv output to a pandas table if outfile == tmpfile.name: # if outfile isn't set, return pd.DataFrame diff --git a/pygmt/src/x2sys_init.py b/pygmt/src/x2sys_init.py index 150188eef1c..cab1d4a9020 100644 --- a/pygmt/src/x2sys_init.py +++ b/pygmt/src/x2sys_init.py @@ -110,5 +110,4 @@ def x2sys_init(tag, **kwargs): {j} """ with Session() as lib: - arg_str = " ".join([tag, build_arg_string(kwargs)]) - lib.call_module(module="x2sys_init", args=arg_str) + lib.call_module(module="x2sys_init", args=build_arg_string(kwargs, infile=tag)) diff --git a/pygmt/src/xyz2grd.py b/pygmt/src/xyz2grd.py index 7deb42778ab..4e0d9b7a220 100644 --- a/pygmt/src/xyz2grd.py +++ b/pygmt/src/xyz2grd.py @@ -160,7 +160,6 @@ def xyz2grd(data=None, x=None, y=None, z=None, **kwargs): if "G" not in kwargs: # if outgrid is unset, output to tempfile kwargs.update({"G": tmpfile.name}) outgrid = kwargs["G"] - arg_str = " ".join([infile, build_arg_string(kwargs)]) - lib.call_module("xyz2grd", arg_str) + lib.call_module("xyz2grd", build_arg_string(kwargs, infile=infile)) return load_dataarray(outgrid) if outgrid == tmpfile.name else None From 80ab6690ea28abf1795103db0421caa47ae23bf4 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Wed, 30 Mar 2022 16:13:04 +0800 Subject: [PATCH 3/5] Fix a typo in x2sys_cross.py --- pygmt/src/x2sys_cross.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygmt/src/x2sys_cross.py b/pygmt/src/x2sys_cross.py index 24503ad49e8..5950be733a1 100644 --- a/pygmt/src/x2sys_cross.py +++ b/pygmt/src/x2sys_cross.py @@ -223,7 +223,7 @@ def x2sys_cross(tracks=None, outfile=None, **kwargs): lib.call_module( module="x2sys_cross", args=build_arg_string( - kwargs, infile=" ".join(fname), outfile=outfile + kwargs, infile=" ".join(fnames), outfile=outfile ), ) From 074eee6e18e0e000e2391398cc23d08ff06fe65b Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Sat, 2 Apr 2022 12:54:30 +0800 Subject: [PATCH 4/5] Change kwargs to kwdict --- pygmt/helpers/utils.py | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/pygmt/helpers/utils.py b/pygmt/helpers/utils.py index 2b130773d73..c1da0a7ff5f 100644 --- a/pygmt/helpers/utils.py +++ b/pygmt/helpers/utils.py @@ -119,12 +119,12 @@ def dummy_context(arg): yield arg -def build_arg_string(kwargs, infile=None, outfile=None): +def build_arg_string(kwdict, infile=None, outfile=None): r""" - Transform keyword arguments into a GMT argument string. + Convert a dict and optional input/output files into a GMT argument string. - Make sure all arguments have been previously converted to a string - representation using the ``kwargs_to_strings`` decorator. The only + Make sure all values in ``kwdict`` have been previously converted to a + string representation using the ``kwargs_to_strings`` decorator. The only exceptions are True, False and None. Any lists or tuples left will be interpreted as multiple entries for the @@ -138,8 +138,8 @@ def build_arg_string(kwargs, infile=None, outfile=None): Parameters ---------- - kwargs : dict - Parsed keyword arguments. + kwdict : dict + A dict containing parsed keyword arguments. infile : str or pathlib.Path The input file. outfile : str or pathlib.Path @@ -149,7 +149,8 @@ def build_arg_string(kwargs, infile=None, outfile=None): ------- args : str The space-delimited argument string with '-' inserted before each - keyword. The arguments are sorted alphabetically. + keyword. The arguments are sorted alphabetically, with optional input + file at the begining and optioanl output file at the end. Examples -------- @@ -195,33 +196,42 @@ def build_arg_string(kwargs, infile=None, outfile=None): ... ) ... ) -BWSne+tBlank\040Space -Baf -F+t"Empty\040\040Spaces" -l'Void\040Space' + >>> print( + ... build_arg_string( + ... dict(A="0", B=True, C="rainbow"), + ... infile="input.txt", + ... output="output.txt", + ... ) + ... ) + input.txt -A0 -B -Crainbow ->output.txt """ gmt_args = [] - for key in kwargs: + for key in kwdict: if len(key) > 2: # raise an exception for unrecognized options raise GMTInvalidInput(f"Unrecognized parameter '{key}'.") - if kwargs[key] is None or kwargs[key] is False: + if kwdict[key] is None or kwdict[key] is False: pass # Exclude arguments that are None and False - elif is_nonstr_iter(kwargs[key]): - for value in kwargs[key]: + elif is_nonstr_iter(kwdict[key]): + for value in kwdict[key]: _value = str(value).replace(" ", r"\040") gmt_args.append(rf"-{key}{_value}") - elif kwargs[key] is True: + elif kwdict[key] is True: gmt_args.append(f"-{key}") else: if key != "J": # non-projection parameters - _value = str(kwargs[key]).replace(" ", r"\040") + _value = str(kwdict[key]).replace(" ", r"\040") else: # special handling if key == "J" (projection) # remove any spaces in PROJ4 string - _value = str(kwargs[key]).replace(" ", "") + _value = str(kwdict[key]).replace(" ", "") gmt_args.append(rf"-{key}{_value}") + gmt_args = sorted(gmt_args) if infile: - gmt_args.append(str(infile)) + gmt_args = [str(infile)] + gmt_args if outfile: gmt_args.append("->" + str(outfile)) - return " ".join(sorted(gmt_args)) + return " ".join(gmt_args) def is_nonstr_iter(value): From c4ee94f33874d32e867a022edd1554c6e6484976 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Sat, 2 Apr 2022 23:15:08 +0800 Subject: [PATCH 5/5] Fix a typo --- pygmt/helpers/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygmt/helpers/utils.py b/pygmt/helpers/utils.py index c1da0a7ff5f..0bd6aa60176 100644 --- a/pygmt/helpers/utils.py +++ b/pygmt/helpers/utils.py @@ -200,7 +200,7 @@ def build_arg_string(kwdict, infile=None, outfile=None): ... build_arg_string( ... dict(A="0", B=True, C="rainbow"), ... infile="input.txt", - ... output="output.txt", + ... outfile="output.txt", ... ) ... ) input.txt -A0 -B -Crainbow ->output.txt