From 884bde7b0d5da4f94263b173afe48eea80b2116b Mon Sep 17 00:00:00 2001 From: carocamargo Date: Thu, 17 Sep 2020 21:36:20 +0200 Subject: [PATCH 01/23] added gridfilter function --- pygmt/gridops.py | 92 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 85 insertions(+), 7 deletions(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index 122aa42340e..74823ab717f 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -20,13 +20,15 @@ @fmt_docstring @use_alias( - G="outgrid", - R="region", - J="projection", - N="extend", - S="circ_subregion", - Z="z_subregion", -) + G="outgrid", + R="region", + J="projection", + N="extend", + S="circ_subregion", + Z="z_subregion", + F="filter", + D="distance" + ) @kwargs_to_strings(R="sequence") def grdcut(grid, **kwargs): """ @@ -113,3 +115,79 @@ def grdcut(grid, **kwargs): result = None # if user sets an outgrid, return None return result + + +def grdfilter(grid, **kwargs): + """ + + filter a grid file in the time domain using one of the selected convolution + or non-convolution isotropic or rectangular filters and compute distances + using Cartesian or Spherical geometries. The output grid file can optionally + be generated as a sub-region of the input (via -R) and/or with new increment + (via -I) or registration (via -T). In this way, one may have “extra space” in + the input data so that the edges will not be used and the output can be within + one half-width of the input edges. If the filter is low-pass, then the output + may be less frequently sampled than the input. + + Parameters + ---------- + grid : str or xarray.DataArray + The file name of the input grid or the grid loaded as a DataArray. + outgrid : str or None + The name of the output netCDF file with extension .nc to store the grid + in. + {F} : str + Name of filter type you which to apply, followed by the width + b: Box Car; c: Cosine Arch; g: Gaussian; o: Operator; m: Median; p: Maximum Likelihood probability; h: histogram + {D}: str + Distance flag, that tells how grid (x,y) rrlated to the filter width as follows: + flag = p: grid (px,py) with width an odd number of pixels; Cartesian distances. + + flag = 0: grid (x,y) same units as width, Cartesian distances. + + flag = 1: grid (x,y) in degrees, width in kilometers, Cartesian distances. + + flag = 2: grid (x,y) in degrees, width in km, dx scaled by cos(middle y), Cartesian distances. + + The above options are fastest because they allow weight matrix to be computed only once. The next three options are slower because they recompute weights for each latitude. + + flag = 3: grid (x,y) in degrees, width in km, dx scaled by cosine(y), Cartesian distance calculation. + + flag = 4: grid (x,y) in degrees, width in km, Spherical distance calculation. + + flag = 5: grid (x,y) in Mercator -Jm1 img units, width in km, Spherical distance calculation. + + Returns + ------- + ret: xarray.DataArray or None + Return type depends on whether the *outgrid* parameter is set: + - xarray.DataArray if *outgrid* is not set + - None if *outgrid* is set (grid output will be stored in *outgrid*) + """ + kind = data_kind(grid) + + with GMTTempFile(suffix=".nc") as tmpfile: + with Session() as lib: + if kind == "file": + file_context = dummy_context(grid) + elif kind == "grid": + file_context = lib.virtualfile_from_grid(grid) + else: + raise GMTInvalidInput("Unrecognized data type: {}".format(type(grid))) + + with file_context as infile: + if "G" not in kwargs.keys(): # 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) + + 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 + else: + result = None # if user sets an outgrid, return None + + return result + From c2a7d3ed188ccc4e94f493c54d676ec9a56222f5 Mon Sep 17 00:00:00 2001 From: carocamargo Date: Thu, 17 Sep 2020 21:37:10 +0200 Subject: [PATCH 02/23] added to call gridfilter from grdops.py --- pygmt/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygmt/__init__.py b/pygmt/__init__.py index 512865264b0..d031c76ab5a 100644 --- a/pygmt/__init__.py +++ b/pygmt/__init__.py @@ -19,7 +19,7 @@ from .sampling import grdtrack from .mathops import makecpt from .modules import GMTDataArrayAccessor, config, info, grdinfo, which -from .gridops import grdcut +from .gridops import grdcut, gridfilter from .x2sys import x2sys_init, x2sys_cross from . import datasets From 2cb715db3dd1d242cfb41a64d70f338a09b0f868 Mon Sep 17 00:00:00 2001 From: carocamargo Date: Fri, 18 Sep 2020 09:44:10 +0200 Subject: [PATCH 03/23] added grdfilter caller --- pygmt/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygmt/__init__.py b/pygmt/__init__.py index d031c76ab5a..4a38fe40ad6 100644 --- a/pygmt/__init__.py +++ b/pygmt/__init__.py @@ -19,7 +19,7 @@ from .sampling import grdtrack from .mathops import makecpt from .modules import GMTDataArrayAccessor, config, info, grdinfo, which -from .gridops import grdcut, gridfilter +from .gridops import grdcut, grdfilter from .x2sys import x2sys_init, x2sys_cross from . import datasets From 6139c1735cff7f7d615d243145c21b1efef3f2c6 Mon Sep 17 00:00:00 2001 From: carocamargo Date: Fri, 18 Sep 2020 09:53:45 +0200 Subject: [PATCH 04/23] corrected indentation in grdfilter docstring, and made each function with each owns decorators --- pygmt/gridops.py | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index 74823ab717f..4adca2f6e6b 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -25,9 +25,7 @@ J="projection", N="extend", S="circ_subregion", - Z="z_subregion", - F="filter", - D="distance" + Z="z_subregion" ) @kwargs_to_strings(R="sequence") def grdcut(grid, **kwargs): @@ -116,30 +114,36 @@ def grdcut(grid, **kwargs): return result +@fmt_docstring +@use_alias( + G="outgrid", + F="filter", + D="distance" + ) +@kwargs_to_strings(R="sequence") def grdfilter(grid, **kwargs): """ + filter a grid file in the time domain using one of the selected convolution + or non-convolution isotropic or rectangular filters and compute distances + using Cartesian or Spherical geometries. The output grid file can optionally + be generated as a sub-region of the input (via -R) and/or with new increment + (via -I) or registration (via -T). In this way, one may have “extra space” in + the input data so that the edges will not be used and the output can be within + one half-width of the input edges. If the filter is low-pass, then the output + may be less frequently sampled than the input. - filter a grid file in the time domain using one of the selected convolution - or non-convolution isotropic or rectangular filters and compute distances - using Cartesian or Spherical geometries. The output grid file can optionally - be generated as a sub-region of the input (via -R) and/or with new increment - (via -I) or registration (via -T). In this way, one may have “extra space” in - the input data so that the edges will not be used and the output can be within - one half-width of the input edges. If the filter is low-pass, then the output - may be less frequently sampled than the input. - - Parameters - ---------- - grid : str or xarray.DataArray + Parameters + ---------- + grid : str or xarray.DataArray The file name of the input grid or the grid loaded as a DataArray. outgrid : str or None The name of the output netCDF file with extension .nc to store the grid in. - {F} : str + {F} : str Name of filter type you which to apply, followed by the width b: Box Car; c: Cosine Arch; g: Gaussian; o: Operator; m: Median; p: Maximum Likelihood probability; h: histogram - {D}: str + {D}: str Distance flag, that tells how grid (x,y) rrlated to the filter width as follows: flag = p: grid (px,py) with width an odd number of pixels; Cartesian distances. @@ -157,13 +161,13 @@ def grdfilter(grid, **kwargs): flag = 5: grid (x,y) in Mercator -Jm1 img units, width in km, Spherical distance calculation. - Returns - ------- - ret: xarray.DataArray or None + Returns + ------- + ret: xarray.DataArray or None Return type depends on whether the *outgrid* parameter is set: - xarray.DataArray if *outgrid* is not set - None if *outgrid* is set (grid output will be stored in *outgrid*) - """ + """ kind = data_kind(grid) with GMTTempFile(suffix=".nc") as tmpfile: From d2e0aee6be71955db622be77e7729150e3a9ff9a Mon Sep 17 00:00:00 2001 From: carocamargo Date: Fri, 18 Sep 2020 10:12:03 +0200 Subject: [PATCH 05/23] added usage example to grdfilter --- pygmt/gridops.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index 4adca2f6e6b..6e5042205f2 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -143,6 +143,7 @@ def grdfilter(grid, **kwargs): {F} : str Name of filter type you which to apply, followed by the width b: Box Car; c: Cosine Arch; g: Gaussian; o: Operator; m: Median; p: Maximum Likelihood probability; h: histogram + Example: 'm600' for a median filter with width of 600 {D}: str Distance flag, that tells how grid (x,y) rrlated to the filter width as follows: flag = p: grid (px,py) with width an odd number of pixels; Cartesian distances. @@ -167,6 +168,14 @@ def grdfilter(grid, **kwargs): Return type depends on whether the *outgrid* parameter is set: - xarray.DataArray if *outgrid* is not set - None if *outgrid* is set (grid output will be stored in *outgrid*) + + Usage + ------- + pygmt.grdfilter('/Users/Desktop/input.nc',F='m1600',D='4', G='/Users/Desktop/filtered_output.nc') + Applies a filter of 1600km (full width) in the input.nc and returns a a filtered filed (saved as netcdf) + + out=pygmt.grdfiler(dataarray,F='g600',D='4') + Applies a gaussian smoothing filter of 600 km in the input data array, and returns a filtered data array """ kind = data_kind(grid) From db2cdc7a388a42ccc4cffe2a9a73969921db7a5d Mon Sep 17 00:00:00 2001 From: carocamargo <47150926+carocamargo@users.noreply.github.com> Date: Fri, 18 Sep 2020 14:32:48 +0200 Subject: [PATCH 06/23] Update pygmt/gridops.py Co-authored-by: Wei Ji <23487320+weiji14@users.noreply.github.com> --- pygmt/gridops.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index 6e5042205f2..c64be746036 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -20,13 +20,13 @@ @fmt_docstring @use_alias( - G="outgrid", - R="region", - J="projection", - N="extend", - S="circ_subregion", - Z="z_subregion" - ) + G="outgrid", + R="region", + J="projection", + N="extend", + S="circ_subregion", + Z="z_subregion", +) @kwargs_to_strings(R="sequence") def grdcut(grid, **kwargs): """ @@ -203,4 +203,3 @@ def grdfilter(grid, **kwargs): result = None # if user sets an outgrid, return None return result - From 8b8403967589584bebd1b618afb717d3360dc123 Mon Sep 17 00:00:00 2001 From: carocamargo <47150926+carocamargo@users.noreply.github.com> Date: Fri, 18 Sep 2020 14:41:53 +0200 Subject: [PATCH 07/23] Update pygmt/gridops.py Co-authored-by: Wei Ji <23487320+weiji14@users.noreply.github.com> --- pygmt/gridops.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index c64be746036..14d9d5ddea2 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -127,8 +127,8 @@ def grdfilter(grid, **kwargs): filter a grid file in the time domain using one of the selected convolution or non-convolution isotropic or rectangular filters and compute distances using Cartesian or Spherical geometries. The output grid file can optionally - be generated as a sub-region of the input (via -R) and/or with new increment - (via -I) or registration (via -T). In this way, one may have “extra space” in + be generated as a sub-region of the input (via *region*) and/or with new increment + (via *spacing*) or registration (via *toggle*). In this way, one may have “extra space” in the input data so that the edges will not be used and the output can be within one half-width of the input edges. If the filter is low-pass, then the output may be less frequently sampled than the input. From a8dd55c71ba6101a79ae09ad874ab0770dc7b4a1 Mon Sep 17 00:00:00 2001 From: carocamargo Date: Mon, 28 Sep 2020 10:47:07 +0200 Subject: [PATCH 08/23] added more optional aliases --- pygmt/gridops.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index 6e5042205f2..9de0068519a 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -118,7 +118,13 @@ def grdcut(grid, **kwargs): @use_alias( G="outgrid", F="filter", - D="distance" + D="distance", + I="increment", + N="nans", + R="region", + T="toggle", + V="verbose", + f="colinfo" ) @kwargs_to_strings(R="sequence") @@ -161,6 +167,25 @@ def grdfilter(grid, **kwargs): flag = 4: grid (x,y) in degrees, width in km, Spherical distance calculation. flag = 5: grid (x,y) in Mercator -Jm1 img units, width in km, Spherical distance calculation. + + {I}: str + x_inc [and optionally y_inc] is the grid spacing. + (http://docs.generic-mapping-tools.org/latest/grdfilter.html#i) + {N}: Str or Number + Determine how NaN-values in the input grid affects the filtered output. + Values are i|p|r (http://docs.generic-mapping-tools.org/latest/grdfilter.html#n) + {R}: Str or list or GMTgrid + Specify the region of interest. Set to data minimum BoundinBox if not provided. + (http://docs.generic-mapping-tools.org/latest/gmt.html#r-full) + {T}: Bool + Toggle the node registration for the output grid so as to become the opposite of the input grid + (http://docs.generic-mapping-tools.org/latest/grdfilter.html#t) + {V}: Bool or Str + Select verbosity level, which will send progress reports to stderr. + (http://docs.generic-mapping-tools.org/latest/gmt.html#v-full) + {f}: Str + Specify the data types of input and/or output columns (time or geographical data). + (http://docs.generic-mapping-tools.org/latest/gmt.html#f-full) Returns ------- @@ -204,3 +229,4 @@ def grdfilter(grid, **kwargs): return result + From 9f47f01e97d1aab2ceb4b5ac8e88cd646a74a778 Mon Sep 17 00:00:00 2001 From: carocamargo Date: Mon, 28 Sep 2020 11:06:30 +0200 Subject: [PATCH 09/23] added more optional aliases --- pygmt/gridops.py | 235 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 pygmt/gridops.py diff --git a/pygmt/gridops.py b/pygmt/gridops.py new file mode 100644 index 00000000000..eba2278acdb --- /dev/null +++ b/pygmt/gridops.py @@ -0,0 +1,235 @@ +""" +GMT modules for grid operations +""" + +import xarray as xr + + +from .clib import Session +from .helpers import ( + build_arg_string, + fmt_docstring, + kwargs_to_strings, + GMTTempFile, + use_alias, + data_kind, + dummy_context, +) +from .exceptions import GMTInvalidInput + + +@fmt_docstring +@use_alias( + G="outgrid", + R="region", + J="projection", + N="extend", + S="circ_subregion", + Z="z_subregion", +) +@kwargs_to_strings(R="sequence") +def grdcut(grid, **kwargs): + """ + Extract subregion from a grid. + + Produce a new *outgrid* file which is a subregion of *grid*. The + subregion is specified with *region*; the specified range must not exceed + the range of *grid* (but see *extend*). If in doubt, run + :meth:`pygmt.grdinfo` to check range. Alternatively, define the subregion + indirectly via a range check on the node values or via distances from a + given point. Finally, you can give *projection* for oblique projections to + determine the corresponding rectangular *region* setting that will give a + grid that fully covers the oblique domain. + + Full option list at :gmt-docs:`grdcut.html` + + {aliases} + + Parameters + ---------- + grid : str or xarray.DataArray + The file name of the input grid or the grid loaded as a DataArray. + outgrid : str or None + The name of the output netCDF file with extension .nc to store the grid + in. + {J} + {R} + extend : bool or int or float + Allow grid to be extended if new *region* exceeds existing boundaries. + Give a value to initialize nodes outside current region. + circ_subregion : str + ``'lon/lat/radius[unit][+n]'``. + Specify an origin (*lon* and *lat*) and *radius*; append a distance + *unit* and we determine the corresponding rectangular region so that + all grid nodes on or inside the circle are contained in the subset. + If **+n** is appended we set all nodes outside the circle to NaN. + z_subregion : str + ``'[min/max][+n|N|r]'``. + Determine a new rectangular region so that all nodes outside this + region are also outside the given z-range [-inf/+inf]. To indicate no + limit on *min* or *max* only, specify a hyphen (-). Normally, any NaNs + encountered are simply skipped and not considered in the + range-decision. Append **+n** to consider a NaN to be outside the given + z-range. This means the new subset will be NaN-free. Alternatively, + append **+r** to consider NaNs to be within the data range. In this + case we stop shrinking the boundaries once a NaN is found [Default + simply skips NaNs when making the range decision]. Finally, if your + core subset grid is surrounded by rows and/or columns that are all + NaNs, append **+N** to strip off such columns before (optionally) + considering the range of the core subset for further reduction of the + area. + + Returns + ------- + ret: xarray.DataArray or None + Return type depends on whether the *outgrid* parameter is set: + + - xarray.DataArray if *outgrid* is not set + - None if *outgrid* is set (grid output will be stored in *outgrid*) + """ + kind = data_kind(grid) + + with GMTTempFile(suffix=".nc") as tmpfile: + with Session() as lib: + if kind == "file": + file_context = dummy_context(grid) + elif kind == "grid": + file_context = lib.virtualfile_from_grid(grid) + else: + raise GMTInvalidInput("Unrecognized data type: {}".format(type(grid))) + + with file_context as infile: + if "G" not in kwargs.keys(): # 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) + + 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 + else: + result = None # if user sets an outgrid, return None + + return result + +@fmt_docstring +@use_alias( + G="outgrid", + F="filter", + D="distance", + I="increment", + N="nans", + R="region", + T="toggle", + V="verbose", + f="colinfo" + ) +@kwargs_to_strings(R="sequence") + +def grdfilter(grid, **kwargs): + """ + filter a grid file in the time domain using one of the selected convolution + or non-convolution isotropic or rectangular filters and compute distances + using Cartesian or Spherical geometries. The output grid file can optionally + be generated as a sub-region of the input (via *region*) and/or with new increment + (via *spacing*) or registration (via *toggle*). In this way, one may have “extra space” in + the input data so that the edges will not be used and the output can be within + one half-width of the input edges. If the filter is low-pass, then the output + may be less frequently sampled than the input. + + Parameters + ---------- + grid : str or xarray.DataArray + The file name of the input grid or the grid loaded as a DataArray. + outgrid : str or None + The name of the output netCDF file with extension .nc to store the grid + in. + {F} : str + Name of filter type you which to apply, followed by the width + b: Box Car; c: Cosine Arch; g: Gaussian; o: Operator; m: Median; p: Maximum Likelihood probability; h: histogram + Example: 'm600' for a median filter with width of 600 + {D}: str + Distance flag, that tells how grid (x,y) rrlated to the filter width as follows: + flag = p: grid (px,py) with width an odd number of pixels; Cartesian distances. + + flag = 0: grid (x,y) same units as width, Cartesian distances. + + flag = 1: grid (x,y) in degrees, width in kilometers, Cartesian distances. + + flag = 2: grid (x,y) in degrees, width in km, dx scaled by cos(middle y), Cartesian distances. + + The above options are fastest because they allow weight matrix to be computed only once. The next three options are slower because they recompute weights for each latitude. + + flag = 3: grid (x,y) in degrees, width in km, dx scaled by cosine(y), Cartesian distance calculation. + + flag = 4: grid (x,y) in degrees, width in km, Spherical distance calculation. + + flag = 5: grid (x,y) in Mercator -Jm1 img units, width in km, Spherical distance calculation. + + {I}: str + x_inc [and optionally y_inc] is the grid spacing. + (http://docs.generic-mapping-tools.org/latest/grdfilter.html#i) + {N}: Str or Number + Determine how NaN-values in the input grid affects the filtered output. + Values are i|p|r (http://docs.generic-mapping-tools.org/latest/grdfilter.html#n) + {R}: Str or list or GMTgrid + Specify the region of interest. Set to data minimum BoundinBox if not provided. + (http://docs.generic-mapping-tools.org/latest/gmt.html#r-full) + {T}: Bool + Toggle the node registration for the output grid so as to become the opposite of the input grid + (http://docs.generic-mapping-tools.org/latest/grdfilter.html#t) + {V}: Bool or Str + Select verbosity level, which will send progress reports to stderr. + (http://docs.generic-mapping-tools.org/latest/gmt.html#v-full) + {f}: Str + Specify the data types of input and/or output columns (time or geographical data). + (http://docs.generic-mapping-tools.org/latest/gmt.html#f-full) + + Returns + ------- + ret: xarray.DataArray or None + Return type depends on whether the *outgrid* parameter is set: + - xarray.DataArray if *outgrid* is not set + - None if *outgrid* is set (grid output will be stored in *outgrid*) + + Usage + ------- + pygmt.grdfilter('/Users/Desktop/input.nc',F='m1600',D='4', G='/Users/Desktop/filtered_output.nc') + Applies a filter of 1600km (full width) in the input.nc and returns a a filtered filed (saved as netcdf) + + out=pygmt.grdfiler(dataarray,F='g600',D='4') + Applies a gaussian smoothing filter of 600 km in the input data array, and returns a filtered data array + """ + kind = data_kind(grid) + + with GMTTempFile(suffix=".nc") as tmpfile: + with Session() as lib: + if kind == "file": + file_context = dummy_context(grid) + elif kind == "grid": + file_context = lib.virtualfile_from_grid(grid) + else: + raise GMTInvalidInput("Unrecognized data type: {}".format(type(grid))) + + with file_context as infile: + if "G" not in kwargs.keys(): # 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) + + 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 + else: + result = None # if user sets an outgrid, return None + + return result +<<<<<<< HEAD + + +======= +>>>>>>> 8b8403967589584bebd1b618afb717d3360dc123 From 874bca4fdb85c665f2a39276089e63ed56d36c48 Mon Sep 17 00:00:00 2001 From: carocamargo <47150926+carocamargo@users.noreply.github.com> Date: Mon, 28 Sep 2020 11:11:45 +0200 Subject: [PATCH 10/23] Update gridops.py removed header from local conflict --- pygmt/gridops.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index eba2278acdb..43fe4608fe6 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -228,8 +228,4 @@ def grdfilter(grid, **kwargs): result = None # if user sets an outgrid, return None return result -<<<<<<< HEAD - -======= ->>>>>>> 8b8403967589584bebd1b618afb717d3360dc123 From 0373c3247da840d375ff60592f4862f9e01b48ae Mon Sep 17 00:00:00 2001 From: carocamargo <47150926+carocamargo@users.noreply.github.com> Date: Tue, 29 Sep 2020 09:55:19 +0200 Subject: [PATCH 11/23] Update pygmt/gridops.py Co-authored-by: Dongdong Tian --- pygmt/gridops.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index 43fe4608fe6..da4f70ad63c 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -127,7 +127,6 @@ def grdcut(grid, **kwargs): f="colinfo" ) @kwargs_to_strings(R="sequence") - def grdfilter(grid, **kwargs): """ filter a grid file in the time domain using one of the selected convolution @@ -228,4 +227,3 @@ def grdfilter(grid, **kwargs): result = None # if user sets an outgrid, return None return result - From fd64a4eb05acf7b26bbb9ef5545bf48e3c001f1b Mon Sep 17 00:00:00 2001 From: carocamargo <47150926+carocamargo@users.noreply.github.com> Date: Tue, 29 Sep 2020 09:55:27 +0200 Subject: [PATCH 12/23] Update pygmt/gridops.py Co-authored-by: Dongdong Tian --- pygmt/gridops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index da4f70ad63c..43ff913453d 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -145,7 +145,7 @@ def grdfilter(grid, **kwargs): outgrid : str or None The name of the output netCDF file with extension .nc to store the grid in. - {F} : str + filter : str Name of filter type you which to apply, followed by the width b: Box Car; c: Cosine Arch; g: Gaussian; o: Operator; m: Median; p: Maximum Likelihood probability; h: histogram Example: 'm600' for a median filter with width of 600 From df53508b85d3338bc64e10c253b399bc8bd6e4f6 Mon Sep 17 00:00:00 2001 From: carocamargo <47150926+carocamargo@users.noreply.github.com> Date: Tue, 29 Sep 2020 09:55:38 +0200 Subject: [PATCH 13/23] Update pygmt/gridops.py Co-authored-by: Dongdong Tian --- pygmt/gridops.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index 43ff913453d..4c841269dd4 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -173,9 +173,7 @@ def grdfilter(grid, **kwargs): {N}: Str or Number Determine how NaN-values in the input grid affects the filtered output. Values are i|p|r (http://docs.generic-mapping-tools.org/latest/grdfilter.html#n) - {R}: Str or list or GMTgrid - Specify the region of interest. Set to data minimum BoundinBox if not provided. - (http://docs.generic-mapping-tools.org/latest/gmt.html#r-full) + {R} {T}: Bool Toggle the node registration for the output grid so as to become the opposite of the input grid (http://docs.generic-mapping-tools.org/latest/grdfilter.html#t) From 6fae1036bc5c741d2eccf1f72da250904f0c8ddc Mon Sep 17 00:00:00 2001 From: carocamargo Date: Tue, 29 Sep 2020 10:22:49 +0200 Subject: [PATCH 14/23] formated code with black --- pygmt/gridops.py | 78 +++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index 4c841269dd4..d6eaf08ef76 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -114,18 +114,19 @@ def grdcut(grid, **kwargs): return result + @fmt_docstring @use_alias( - G="outgrid", - F="filter", - D="distance", - I="increment", - N="nans", - R="region", - T="toggle", - V="verbose", - f="colinfo" - ) + G="outgrid", + F="filter", + D="distance", + I="increment", + N="nans", + R="region", + T="toggle", + V="verbose", + f="colinfo", +) @kwargs_to_strings(R="sequence") def grdfilter(grid, **kwargs): """ @@ -133,11 +134,11 @@ def grdfilter(grid, **kwargs): or non-convolution isotropic or rectangular filters and compute distances using Cartesian or Spherical geometries. The output grid file can optionally be generated as a sub-region of the input (via *region*) and/or with new increment - (via *spacing*) or registration (via *toggle*). In this way, one may have “extra space” in - the input data so that the edges will not be used and the output can be within - one half-width of the input edges. If the filter is low-pass, then the output - may be less frequently sampled than the input. - + (via *spacing*) or registration (via *toggle*). + In this way, one may have “extra space” in the input data so that the edges + will not be used and the output can be within one half-width of the input edges. + If the filter is low-pass, then the output may be less frequently sampled than the input. + Parameters ---------- grid : str or xarray.DataArray @@ -147,26 +148,28 @@ def grdfilter(grid, **kwargs): in. filter : str Name of filter type you which to apply, followed by the width - b: Box Car; c: Cosine Arch; g: Gaussian; o: Operator; m: Median; p: Maximum Likelihood probability; h: histogram - Example: 'm600' for a median filter with width of 600 + b: Box Car; c: Cosine Arch; g: Gaussian; o: Operator; m: Median; + p: Maximum Likelihood probability; h: histogram + Example: F='m600' for a median filter with width of 600 {D}: str Distance flag, that tells how grid (x,y) rrlated to the filter width as follows: flag = p: grid (px,py) with width an odd number of pixels; Cartesian distances. - + flag = 0: grid (x,y) same units as width, Cartesian distances. - + flag = 1: grid (x,y) in degrees, width in kilometers, Cartesian distances. - + flag = 2: grid (x,y) in degrees, width in km, dx scaled by cos(middle y), Cartesian distances. - - The above options are fastest because they allow weight matrix to be computed only once. The next three options are slower because they recompute weights for each latitude. - + + The above options are fastest because they allow weight matrix to be computed only once. + The next three options are slower because they recompute weights for each latitude. + flag = 3: grid (x,y) in degrees, width in km, dx scaled by cosine(y), Cartesian distance calculation. - + flag = 4: grid (x,y) in degrees, width in km, Spherical distance calculation. - + flag = 5: grid (x,y) in Mercator -Jm1 img units, width in km, Spherical distance calculation. - + {I}: str x_inc [and optionally y_inc] is the grid spacing. (http://docs.generic-mapping-tools.org/latest/grdfilter.html#i) @@ -183,24 +186,25 @@ def grdfilter(grid, **kwargs): {f}: Str Specify the data types of input and/or output columns (time or geographical data). (http://docs.generic-mapping-tools.org/latest/gmt.html#f-full) - + Returns ------- ret: xarray.DataArray or None Return type depends on whether the *outgrid* parameter is set: - xarray.DataArray if *outgrid* is not set - None if *outgrid* is set (grid output will be stored in *outgrid*) - + Usage ------- - pygmt.grdfilter('/Users/Desktop/input.nc',F='m1600',D='4', G='/Users/Desktop/filtered_output.nc') - Applies a filter of 1600km (full width) in the input.nc and returns a a filtered filed (saved as netcdf) - - out=pygmt.grdfiler(dataarray,F='g600',D='4') - Applies a gaussian smoothing filter of 600 km in the input data array, and returns a filtered data array + pygmt.grdfilter('input.nc',F='m1600',D='4', G='filtered_output.nc') + Applies a filter of 1600km (full width) in the input.nc and returns a a filtered field (saved as netcdf) + + smooth_field=pygmt.grdfiler(dataarray,F='g600',D='4') + Applies a gaussian smoothing filter of 600 km in the input data array, + and returns a filtered data array withthe smoothed field. """ kind = data_kind(grid) - + with GMTTempFile(suffix=".nc") as tmpfile: with Session() as lib: if kind == "file": @@ -209,19 +213,19 @@ def grdfilter(grid, **kwargs): file_context = lib.virtualfile_from_grid(grid) else: raise GMTInvalidInput("Unrecognized data type: {}".format(type(grid))) - + with file_context as infile: if "G" not in kwargs.keys(): # 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) - + 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 else: result = None # if user sets an outgrid, return None - + return result From d2c8e99b8456e0baef0a0082643f1f2b7de57707 Mon Sep 17 00:00:00 2001 From: carocamargo <47150926+carocamargo@users.noreply.github.com> Date: Tue, 29 Sep 2020 16:56:52 +0200 Subject: [PATCH 15/23] Update pygmt/gridops.py Co-authored-by: Dongdong Tian --- pygmt/gridops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index d6eaf08ef76..35dd409ed51 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -151,7 +151,7 @@ def grdfilter(grid, **kwargs): b: Box Car; c: Cosine Arch; g: Gaussian; o: Operator; m: Median; p: Maximum Likelihood probability; h: histogram Example: F='m600' for a median filter with width of 600 - {D}: str + distance : str Distance flag, that tells how grid (x,y) rrlated to the filter width as follows: flag = p: grid (px,py) with width an odd number of pixels; Cartesian distances. From a820c84ad21d1a83343520c26c8518fd9c8f4dce Mon Sep 17 00:00:00 2001 From: carocamargo <47150926+carocamargo@users.noreply.github.com> Date: Tue, 29 Sep 2020 16:58:02 +0200 Subject: [PATCH 16/23] Apply suggestions from code review Co-authored-by: Dongdong Tian --- pygmt/gridops.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index 35dd409ed51..0828c4b9f55 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -170,22 +170,18 @@ def grdfilter(grid, **kwargs): flag = 5: grid (x,y) in Mercator -Jm1 img units, width in km, Spherical distance calculation. - {I}: str + increment : str x_inc [and optionally y_inc] is the grid spacing. (http://docs.generic-mapping-tools.org/latest/grdfilter.html#i) - {N}: Str or Number + nans : Str or Number Determine how NaN-values in the input grid affects the filtered output. Values are i|p|r (http://docs.generic-mapping-tools.org/latest/grdfilter.html#n) {R} - {T}: Bool + toggle : Bool Toggle the node registration for the output grid so as to become the opposite of the input grid (http://docs.generic-mapping-tools.org/latest/grdfilter.html#t) - {V}: Bool or Str - Select verbosity level, which will send progress reports to stderr. - (http://docs.generic-mapping-tools.org/latest/gmt.html#v-full) - {f}: Str - Specify the data types of input and/or output columns (time or geographical data). - (http://docs.generic-mapping-tools.org/latest/gmt.html#f-full) + {V} + {f} Returns ------- From f2e4d5451dba88e7060e2565ce2dc7bb520f63e4 Mon Sep 17 00:00:00 2001 From: carocamargo <47150926+carocamargo@users.noreply.github.com> Date: Fri, 2 Oct 2020 16:56:56 +0200 Subject: [PATCH 17/23] Update index.rst Added 'grdfilter' under Operations on grids --- doc/api/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/api/index.rst b/doc/api/index.rst index c4f199b3dbc..09e822bc87a 100644 --- a/doc/api/index.rst +++ b/doc/api/index.rst @@ -71,6 +71,7 @@ Operations on grids: :toctree: generated grdcut + grdfilter grdtrack Crossover analysis with x2sys: From d0db5f1977fdf3e26cdb2cdb3427a3a1cdf5ef5c Mon Sep 17 00:00:00 2001 From: carocamargo <47150926+carocamargo@users.noreply.github.com> Date: Fri, 2 Oct 2020 16:58:36 +0200 Subject: [PATCH 18/23] Apply suggestions from code review Co-authored-by: Wei Ji <23487320+weiji14@users.noreply.github.com> --- pygmt/gridops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index 0828c4b9f55..596019ad08c 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -143,7 +143,7 @@ def grdfilter(grid, **kwargs): ---------- grid : str or xarray.DataArray The file name of the input grid or the grid loaded as a DataArray. - outgrid : str or None + outgrid : str or None The name of the output netCDF file with extension .nc to store the grid in. filter : str From 206b8dc48cc42d79d6bebba2c423b1ed27d098db Mon Sep 17 00:00:00 2001 From: carocamargo <47150926+carocamargo@users.noreply.github.com> Date: Fri, 2 Oct 2020 16:59:39 +0200 Subject: [PATCH 19/23] Update pygmt/gridops.py Co-authored-by: Dongdong Tian --- pygmt/gridops.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index 596019ad08c..d55a1bbb2e4 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -181,7 +181,6 @@ def grdfilter(grid, **kwargs): Toggle the node registration for the output grid so as to become the opposite of the input grid (http://docs.generic-mapping-tools.org/latest/grdfilter.html#t) {V} - {f} Returns ------- From 981b0bf51cd7eb4fb2dd9386bb9ed9c39b4c03ce Mon Sep 17 00:00:00 2001 From: carocamargo <47150926+carocamargo@users.noreply.github.com> Date: Fri, 2 Oct 2020 17:00:00 +0200 Subject: [PATCH 20/23] Update pygmt/gridops.py Co-authored-by: Wei Ji <23487320+weiji14@users.noreply.github.com> --- pygmt/gridops.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index d55a1bbb2e4..231a14da519 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -117,15 +117,14 @@ def grdcut(grid, **kwargs): @fmt_docstring @use_alias( - G="outgrid", - F="filter", D="distance", - I="increment", + F="filter", + G="outgrid", + I="spacing", N="nans", R="region", T="toggle", V="verbose", - f="colinfo", ) @kwargs_to_strings(R="sequence") def grdfilter(grid, **kwargs): From 702404e1d2d011b71b99f3f002e990344e26b851 Mon Sep 17 00:00:00 2001 From: carocamargo <47150926+carocamargo@users.noreply.github.com> Date: Fri, 2 Oct 2020 17:01:43 +0200 Subject: [PATCH 21/23] Apply suggestions from code review Co-authored-by: Wei Ji <23487320+weiji14@users.noreply.github.com> --- pygmt/gridops.py | 80 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index 231a14da519..07e7f9d8dab 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -129,14 +129,21 @@ def grdcut(grid, **kwargs): @kwargs_to_strings(R="sequence") def grdfilter(grid, **kwargs): """ - filter a grid file in the time domain using one of the selected convolution + Filter a grid in the space (or time) domain. + + Filter a grid file in the time domain using one of the selected convolution or non-convolution isotropic or rectangular filters and compute distances - using Cartesian or Spherical geometries. The output grid file can optionally - be generated as a sub-region of the input (via *region*) and/or with new increment - (via *spacing*) or registration (via *toggle*). - In this way, one may have “extra space” in the input data so that the edges - will not be used and the output can be within one half-width of the input edges. - If the filter is low-pass, then the output may be less frequently sampled than the input. + using Cartesian or Spherical geometries. The output grid file can + optionally be generated as a sub-region of the input (via *region*) and/or + with new increment (via *spacing*) or registration (via *toggle*). In this + way, one may have "extra space" in the input data so that the edges will + not be used and the output can be within one half-width of the input edges. + If the filter is low-pass, then the output may be less frequently sampled + than the input. + + Full option list at :gmt-docs:`grdfilter.html` + + {aliases} Parameters ---------- @@ -146,28 +153,37 @@ def grdfilter(grid, **kwargs): The name of the output netCDF file with extension .nc to store the grid in. filter : str + ``xwidth[/width2][modifiers]``. Name of filter type you which to apply, followed by the width b: Box Car; c: Cosine Arch; g: Gaussian; o: Operator; m: Median; p: Maximum Likelihood probability; h: histogram Example: F='m600' for a median filter with width of 600 distance : str - Distance flag, that tells how grid (x,y) rrlated to the filter width as follows: - flag = p: grid (px,py) with width an odd number of pixels; Cartesian distances. + Distance *flag* tells how grid (x,y) relates to filter width as + follows: + + p: grid (px,py) with *width* an odd number of pixels; Cartesian + distances. - flag = 0: grid (x,y) same units as width, Cartesian distances. + 0: grid (x,y) same units as *width*, Cartesian distances. - flag = 1: grid (x,y) in degrees, width in kilometers, Cartesian distances. + 1: grid (x,y) in degrees, *width* in kilometers, Cartesian distances. - flag = 2: grid (x,y) in degrees, width in km, dx scaled by cos(middle y), Cartesian distances. + 2: grid (x,y) in degrees, *width* in km, dx scaled by cos(middle y), + Cartesian distances. - The above options are fastest because they allow weight matrix to be computed only once. - The next three options are slower because they recompute weights for each latitude. + The above options are fastest because they allow weight matrix to be + computed only once. The next three options are slower because they + recompute weights for each latitude. - flag = 3: grid (x,y) in degrees, width in km, dx scaled by cosine(y), Cartesian distance calculation. + 3: grid (x,y) in degrees, *width* in km, dx scaled by cosine(y), + Cartesian distance calculation. - flag = 4: grid (x,y) in degrees, width in km, Spherical distance calculation. + 4: grid (x,y) in degrees, *width* in km, Spherical distance + calculation. - flag = 5: grid (x,y) in Mercator -Jm1 img units, width in km, Spherical distance calculation. + 5: grid (x,y) in Mercator ``projection='m1'`` img units, *width* in km, + Spherical distance calculation. increment : str x_inc [and optionally y_inc] is the grid spacing. @@ -188,14 +204,30 @@ def grdfilter(grid, **kwargs): - xarray.DataArray if *outgrid* is not set - None if *outgrid* is set (grid output will be stored in *outgrid*) - Usage - ------- - pygmt.grdfilter('input.nc',F='m1600',D='4', G='filtered_output.nc') - Applies a filter of 1600km (full width) in the input.nc and returns a a filtered field (saved as netcdf) + Examples + -------- + >>> import os + >>> import pygmt + + >>> # Apply a filter of 600km (full width) to the @earth_relief_30m file + >>> # and return a filtered field (saved as netcdf) + >>> pygmt.grdfilter( + ... grid="@earth_relief_30m", + ... filter="m600", + ... distance="4", + ... region=[150, 250, 10, 40], + ... spacing=0.5, + ... outgrid="filtered_pacific.nc" + ... ) + >>> os.remove("filtered_pacific.nc") # cleanup file + + >>> # Apply a gaussian smoothing filter of 600 km in the input data array, + >>> # and returns a filtered data array with the smoothed field. + >>> grid = pygmt.datasets.load_earth_relief() + >>> smooth_field = pygmt.grdfilter( + ... grid=grid, filter="g600", distance="4" + ... ) - smooth_field=pygmt.grdfiler(dataarray,F='g600',D='4') - Applies a gaussian smoothing filter of 600 km in the input data array, - and returns a filtered data array withthe smoothed field. """ kind = data_kind(grid) From 5cb5dea6eed5d59d464f75bd1648d4ab6cf23cee Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Thu, 8 Oct 2020 22:34:50 -0400 Subject: [PATCH 22/23] Update pygmt/gridops.py Co-authored-by: Wei Ji <23487320+weiji14@users.noreply.github.com> --- pygmt/gridops.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index 07e7f9d8dab..e74f5eabde0 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -185,16 +185,17 @@ def grdfilter(grid, **kwargs): 5: grid (x,y) in Mercator ``projection='m1'`` img units, *width* in km, Spherical distance calculation. - increment : str + spacing : str + ``xinc[+e|n][/yinc[+e|n]]``. x_inc [and optionally y_inc] is the grid spacing. - (http://docs.generic-mapping-tools.org/latest/grdfilter.html#i) - nans : Str or Number + nans : str or float + ``i|p|r``. Determine how NaN-values in the input grid affects the filtered output. - Values are i|p|r (http://docs.generic-mapping-tools.org/latest/grdfilter.html#n) {R} - toggle : Bool - Toggle the node registration for the output grid so as to become the opposite of the input grid - (http://docs.generic-mapping-tools.org/latest/grdfilter.html#t) + toggle : bool + Toggle the node registration for the output grid so as to become the + opposite of the input grid. [Default gives the same registration as the + input grid]. {V} Returns From 2fb812a23d665a54197df74ed16e06d23d4bfd28 Mon Sep 17 00:00:00 2001 From: actions-bot <58130806+actions-bot@users.noreply.github.com> Date: Sat, 24 Oct 2020 03:03:14 +0000 Subject: [PATCH 23/23] [format-command] fixes --- pygmt/gridops.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pygmt/gridops.py b/pygmt/gridops.py index e74f5eabde0..fdcb6f9513f 100644 --- a/pygmt/gridops.py +++ b/pygmt/gridops.py @@ -218,16 +218,14 @@ def grdfilter(grid, **kwargs): ... distance="4", ... region=[150, 250, 10, 40], ... spacing=0.5, - ... outgrid="filtered_pacific.nc" + ... outgrid="filtered_pacific.nc", ... ) >>> os.remove("filtered_pacific.nc") # cleanup file >>> # Apply a gaussian smoothing filter of 600 km in the input data array, >>> # and returns a filtered data array with the smoothed field. >>> grid = pygmt.datasets.load_earth_relief() - >>> smooth_field = pygmt.grdfilter( - ... grid=grid, filter="g600", distance="4" - ... ) + >>> smooth_field = pygmt.grdfilter(grid=grid, filter="g600", distance="4") """ kind = data_kind(grid)