Repository: GenericMappingTools/pygmt

Issue:
Rename outfile parameter in surface to be outgrid
**Description of the desired feature**

As mentioned at https://github.com/GenericMappingTools/pygmt/pull/1439#discussion_r687251597, most PyGMT functions which return a grid output have a parameter called `outgrid`, but the `surface` function uses `outfile`. It would be best to standardize the name to be `outgrid` instead.

https://github.com/GenericMappingTools/pygmt/blob/ebbb0cc0045454f05db5abdfb3bcb5e1f18e96a7/pygmt/src/surface.py#L23

<!-- Please be as detailed as you can in your description. If possible, include an example of how you would like to use this feature (even better if it's a code example). -->

Should we deprecate the `outfile` parameter in 2 minor versions (at PyGMT v0.7.0) or 4 minor versions (at PyGMT v0.9.0)? Vote :eyes: for 2 and :tada: for 4.

**Are you willing to help implement and maintain this feature?** Someone can follow our deprecation policy steps at https://www.pygmt.org/v0.4.1/maintenance.html#backwards-compatibility-and-deprecation-policy to resolve this issue.

<!-- Every feature we add is code that we will have to maintain and keep updated. This takes a lot of effort. If you are willing to be involved in the project and help maintain your feature, it will make it easier for us to accept it. -->


Discussion:
seisman: Ping @obaney.
obaney: Merged in @meghanrjones 's helpful test suggestion, it appears that I am failing some checks however
seisman: /format


Patch:
diff --git a/pygmt/src/surface.py b/pygmt/src/surface.py
index 1d24a438..857f8602 100644
--- a/pygmt/src/surface.py
+++ b/pygmt/src/surface.py
@@ -9,6 +9,7 @@ from pygmt.helpers import (
     GMTTempFile,
     build_arg_string,
     data_kind,
+    deprecate_parameter,
     dummy_context,
     fmt_docstring,
     kwargs_to_strings,
@@ -17,10 +18,11 @@ from pygmt.helpers import (
 
 
 @fmt_docstring
+@deprecate_parameter("outfile", "outgrid", "v0.5.0", remove_version="v0.7.0")
 @use_alias(
     I="spacing",
     R="region",
-    G="outfile",
+    G="outgrid",
     V="verbose",
     a="aspatial",
     f="coltypes",
@@ -60,7 +62,7 @@ def surface(x=None, y=None, z=None, data=None, **kwargs):
         *xmin/xmax/ymin/ymax*\[**+r**][**+u**\ *unit*].
         Specify the region of interest.
 
-    outfile : str
+    outgrid : str
         Optional. The file name for the output netcdf file with extension .nc
         to store the grid in.
 
@@ -72,11 +74,11 @@ def surface(x=None, y=None, z=None, data=None, **kwargs):
     Returns
     -------
     ret: xarray.DataArray or None
-        Return type depends on whether the ``outfile`` parameter is set:
+        Return type depends on whether the ``outgrid`` parameter is set:
 
-        - :class:`xarray.DataArray`: if ``outfile`` is not set
-        - None if ``outfile`` is set (grid output will be stored in file set by
-          ``outfile``)
+        - :class:`xarray.DataArray`: if ``outgrid`` is not set
+        - None if ``outgrid`` is set (grid output will be stored in file set by
+          ``outgrid``)
     """
     kind = data_kind(data, x, y, z)
     if kind == "vectors" and z is None:
@@ -93,17 +95,17 @@ def surface(x=None, y=None, z=None, data=None, **kwargs):
             else:
                 raise GMTInvalidInput("Unrecognized data type: {}".format(type(data)))
             with file_context as infile:
-                if "G" not in kwargs.keys():  # if outfile is unset, output to tmpfile
+                if "G" not in kwargs.keys():  # if outgrid is unset, output to tmpfile
                     kwargs.update({"G": tmpfile.name})
-                outfile = kwargs["G"]
+                outgrid = kwargs["G"]
                 arg_str = " ".join([infile, build_arg_string(kwargs)])
                 lib.call_module(module="surface", args=arg_str)
 
-        if outfile == tmpfile.name:  # if user did not set outfile, return DataArray
-            with xr.open_dataarray(outfile) as dataarray:
+        if outgrid == tmpfile.name:  # if user did not set outgrid, return DataArray
+            with xr.open_dataarray(outgrid) as dataarray:
                 result = dataarray.load()
                 _ = result.gmt  # load GMTDataArray accessor information
-        elif outfile != tmpfile.name:  # if user sets an outfile, return None
+        elif outgrid != tmpfile.name:  # if user sets an outgrid, return None
             result = None
 
     return result


Test patch:
diff --git a/pygmt/tests/test_surface.py b/pygmt/tests/test_surface.py
index 0b27d569..8d9d84bc 100644
--- a/pygmt/tests/test_surface.py
+++ b/pygmt/tests/test_surface.py
@@ -82,17 +82,17 @@ def test_surface_wrong_kind_of_input(ship_data):
         surface(data=data, spacing="5m", region=[245, 255, 20, 30])
 
 
-def test_surface_with_outfile_param(ship_data):
+def test_surface_with_outgrid_param(ship_data):
     """
     Run surface with the -Goutputfile.nc parameter.
     """
     data = ship_data.values  # convert pandas.DataFrame to numpy.ndarray
     try:
         output = surface(
-            data=data, spacing="5m", region=[245, 255, 20, 30], outfile=TEMP_GRID
+            data=data, spacing="5m", region=[245, 255, 20, 30], outgrid=TEMP_GRID
         )
-        assert output is None  # check that output is None since outfile is set
-        assert os.path.exists(path=TEMP_GRID)  # check that outfile exists at path
+        assert output is None  # check that output is None since outgrid is set
+        assert os.path.exists(path=TEMP_GRID)  # check that outgrid exists at path
         with xr.open_dataarray(TEMP_GRID) as grid:
             assert isinstance(grid, xr.DataArray)  # ensure netcdf grid loads ok
     finally:
@@ -100,16 +100,37 @@ def test_surface_with_outfile_param(ship_data):
     return output
 
 
+def test_surface_deprecate_outfile_to_outgrid(ship_data):
+    """
+    Make sure that the old parameter "outfile" is supported and it reports a
+    warning.
+    """
+    with pytest.warns(expected_warning=FutureWarning) as record:
+        data = ship_data.values  # convert pandas.DataFrame to numpy.ndarray
+        try:
+            output = surface(
+                data=data, spacing="5m", region=[245, 255, 20, 30], outfile=TEMP_GRID
+            )
+            assert output is None  # check that output is None since outfile is set
+            assert os.path.exists(path=TEMP_GRID)  # check that file exists at path
+
+            with xr.open_dataarray(TEMP_GRID) as grid:
+                assert isinstance(grid, xr.DataArray)  # ensure netcdf grid loads ok
+        finally:
+            os.remove(path=TEMP_GRID)
+        assert len(record) == 1  # check that only one warning was raised
+
+
 def test_surface_short_aliases(ship_data):
     """
     Run surface using short aliases -I for spacing, -R for region, -G for
-    outfile.
+    outgrid.
     """
     data = ship_data.values  # convert pandas.DataFrame to numpy.ndarray
     try:
         output = surface(data=data, I="5m", R=[245, 255, 20, 30], G=TEMP_GRID)
-        assert output is None  # check that output is None since outfile is set
-        assert os.path.exists(path=TEMP_GRID)  # check that outfile exists at path
+        assert output is None  # check that output is None since outgrid is set
+        assert os.path.exists(path=TEMP_GRID)  # check that outgrid exists at path
         with xr.open_dataarray(TEMP_GRID) as grid:
             assert isinstance(grid, xr.DataArray)  # ensure netcdf grid loads ok
     finally: