def surface(data=None, x=None, y=None, z=None, **kwargs): r""" Grids table data using adjustable tension continuous curvature splines. Surface reads randomly-spaced (x,y,z) triples and produces gridded values z(x,y) by solving: .. math:: (1 - t)\nabla^2(z)+t\nabla(z) = 0 where :math:`t` is a tension factor between 0 and 1, and :math:`\nabla` indicates the Laplacian operator. Takes a matrix, xyz triples, or a file name as input. Must provide either ``data`` or ``x``, ``y``, and ``z``. Full option list at :gmt-docs:`surface.html` {aliases} Parameters ---------- data : str or {table-like} Pass in (x, y, z) or (longitude, latitude, elevation) values by providing a file name to an ASCII data table, a 2D {table-classes}. x/y/z : 1d arrays Arrays of x and y coordinates and values z of the data points. {I} {R} outgrid : str Optional. The file name for the output netcdf file with extension .nc to store the grid in. {V} {a} {b} {d} {e} {f} {h} {i} {r} {w} Returns ------- ret: xarray.DataArray or None Return type depends on whether the ``outgrid`` parameter is set: - :class:`xarray.DataArray`: if ``outgrid`` is not set - None if ``outgrid`` is set (grid output will be stored in file set by ``outgrid``) """ with GMTTempFile(suffix=".nc") as tmpfile: with Session() as lib: # Choose how data will be passed into the module file_context = lib.virtualfile_from_data( check_kind="vector", data=data, x=x, y=y, z=z, required_z=True ) with file_context as infile: 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) return load_dataarray(outgrid) if outgrid == tmpfile.name else None
def grdproject(grid, **kwargs): r""" Change projection of gridded data between geographical and rectangular. This module will project a geographical gridded data set onto a rectangular grid. If ``inverse`` is ``True``, it will project a rectangular coordinate system to a geographic system. To obtain the value at each new node, its location is inversely projected back onto the input grid after which a value is interpolated between the surrounding input grid values. By default bi-cubic interpolation is used. Aliasing is avoided by also forward projecting the input grid nodes. If two or more nodes are projected onto the same new node, their average will dominate in the calculation of the new node value. Interpolation and aliasing is controlled with the ``interpolation`` option. The new node spacing may be determined in one of several ways by specifying the grid spacing, number of nodes, or resolution. Nodes not constrained by input data are set to NaN. The ``region`` parameter can be used to select a map region larger or smaller than that implied by the extent of the grid file. {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. inverse : bool When set to ``True`` transforms grid from rectangular to geographical [Default is False]. {J} {R} center : str or list [*dx*, *dy*]. Let projected coordinates be relative to projection center [Default is relative to lower left corner]. Optionally, add offsets in the projected units to be added (or subtracted when ``inverse`` is set) to (from) the projected coordinates, such as false eastings and northings for particular projection zones [0/0]. {I} dpi : int Set the resolution for the new grid in dots per inch. scaling : str [**c**\|\ **i**\|\ **p**\|\ **e**\|\ **f**\|\ **k**\|\ **M**\|\ **n**\|\ **u**]. Force 1:1 scaling, i.e., output or output data are in actual projected meters [**e**]. To specify other units, append **f** (foot), **k** (km), **M** (statute mile), **n** (nautical mile), **u** (US survey foot), **i** (inch), **c** (cm), or **p** (point). unit : str Append **c**, **i**, or **p** to indicate that cm, inch, or point should be the projected measure unit. Cannot be used with ``scaling``. {V} {n} {r} Returns ------- ret: xarray.DataArray or None Return type depends on whether the ``outgrid`` parameter is set: - :class:`xarray.DataArray` if ``outgrid`` is not set - None if ``outgrid`` is set (grid output will be stored in file set by ``outgrid``) """ if "J" not in kwargs: raise GMTInvalidInput("The projection must be specified.") with GMTTempFile(suffix=".nc") as tmpfile: with Session() as lib: file_context = lib.virtualfile_from_data(check_kind="raster", data=grid) with file_context as infile: 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) return load_dataarray(outgrid) if outgrid == tmpfile.name else None
def grdclip(grid, **kwargs): r""" Sets values in a grid that meet certain criteria to a new value. Produce a clipped ``outgrid`` or :class:`xarray.DataArray` version of the input ``grid`` file. The parameters ``above`` and ``below`` allow for a given value to be set for values above or below a set amount, respectively. This allows for extreme values in a grid, such as points below a certain depth when plotting Earth relief, to all be set to the same value. Full option list at :gmt-docs:`grdclip.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. {R} above : str or list or tuple [*high*, *above*]. Set all data[i] > *high* to *above*. below : str or list or tuple [*low*, *below*]. Set all data[i] < *low* to *below*. between : str or list or tuple [*low*, *high*, *between*]. Set all data[i] >= *low* and <= *high* to *between*. new : str or list or tuple [*old*, *new*]. Set all data[i] == *old* to *new*. This is mostly useful when your data are known to be integer values. {V} Returns ------- ret: xarray.DataArray or None Return type depends on whether the ``outgrid`` parameter is set: - :class:`xarray.DataArray` if ``outgrid`` is not set - None if ``outgrid`` is set (grid output will be stored in file set by ``outgrid``) Example ------- >>> import pygmt >>> # Load a grid of @earth_relief_30m data, with an x-range of 10 to 30, >>> # and a y-range of 15 to 25 >>> grid = pygmt.datasets.load_earth_relief( ... resolution="30m", region=[10, 30, 15, 25] ... ) >>> # Report the minimum and maximum data values >>> [grid.data.min(), grid.data.max()] [179.0, 2103.0] >>> # Create a new grid from an input grid. Set all values below 1,000 to >>> # 0 and all values above 1,500 to 10,000 >>> new_grid = pygmt.grdclip( ... grid=grid, below=[1000, 0], above=[1500, 10000] ... ) >>> # Report the minimum and maximum data values >>> [new_grid.data.min(), new_grid.data.max()] [0.0, 10000.0] """ with GMTTempFile(suffix=".nc") as tmpfile: with Session() as lib: file_context = lib.virtualfile_from_data(check_kind="raster", data=grid) with file_context as infile: if (outgrid := kwargs.get("G")) is None: kwargs["G"] = outgrid = tmpfile.name # output to tmpfile lib.call_module(module="grdclip", args=build_arg_string(kwargs, infile=infile)) return load_dataarray(outgrid) if outgrid == tmpfile.name else None
def grdlandmask(**kwargs): r""" Create a grid file with set values for land and water. Read the selected shoreline database and create a grid to specify which nodes in the specified grid are over land or over water. The nodes defined by the selected region and lattice spacing will be set according to one of two criteria: (1) land vs water, or (2) the more detailed (hierarchical) ocean vs land vs lake vs island vs pond. Full option list at :gmt-docs:`grdlandmask.html` {aliases} Parameters ---------- outgrid : str or None The name of the output netCDF file with extension .nc to store the grid in. {I} {R} {A} resolution : str *res*\[\ **+f**\]. Selects the resolution of the data set to use ((**f**)ull, (**h**)igh, (**i**)ntermediate, (**l**)ow, or (**c**)rude). The resolution drops off by ~80% between data sets. [Default is **l**]. Append **+f** to automatically select a lower resolution should the one requested not be available [abort if not found]. Alternatively, choose (**a**)uto to automatically select the best resolution given the chosen region. Note that because the coastlines differ in details a node in a mask file using one resolution is not guaranteed to remain inside [or outside] when a different resolution is selected. bordervalues : bool or str or float or list Nodes that fall exactly on a polygon boundary should be considered to be outside the polygon [Default considers them to be inside]. Alternatively, append either a list of four values [*cborder*, *lborder*, *iborder*, *pborder*] or just the single value *bordervalue* (for the case when they should all be the same value). This turns on the line-tracking mode. Now, after setting the mask values specified via ``maskvalues`` we trace the lines and change the node values for all cells traversed by a line to the corresponding border value. Here, *cborder* is used for cells traversed by the coastline, *lborder* for cells traversed by a lake outline, *iborder* for islands-in-lakes outlines, and *pborder* for ponds-in-islands-in-lakes outlines [Default is no line tracing]. maskvalues : str or list [*wet*, *dry*] or [*ocean*, *land*, *lake*, *island*, *pond*]. Sets the values that will be assigned to nodes. Values can be any number, including the textstring NaN [Default is [0, 1, 0, 1, 0] (i.e., [0, 1])]. Also select ``bordervalues`` to let nodes exactly on feature boundaries be considered outside [Default is inside]. {V} {r} Returns ------- ret: xarray.DataArray or None Return type depends on whether the ``outgrid`` parameter is set: - :class:`xarray.DataArray` if ``outgrid`` is not set - None if ``outgrid`` is set (grid output will be stored in file set by ``outgrid``) Example ------- >>> import pygmt # doctest: +SKIP >>> # Create a landmask grid with an x-range of 125 to 130, >>> # and a y-range of 30 to 35 >>> landmask = pygmt.grdlandmask( ... spacing=1, region=[125, 130, 30, 35] ... ) # doctest: +SKIP """ if "I" not in kwargs or "R" not in kwargs: raise GMTInvalidInput("Both 'region' and 'spacing' must be specified.") with GMTTempFile(suffix=".nc") as tmpfile: with Session() as lib: 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) return load_dataarray(outgrid) if outgrid == tmpfile.name else None
def grdfilter(grid, **kwargs): r""" 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. Full option list at :gmt-docs:`grdfilter.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. filter : str **b**\|\ **c**\|\ **g**\|\ **o**\|\ **m**\|\ **p**\|\ **h**\ *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 distance : str 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. 0: grid (x,y) same units as *width*, Cartesian distances. 1: grid (x,y) in degrees, *width* in kilometers, 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. 3: grid (x,y) in degrees, *width* in km, dx scaled by cosine(y), Cartesian distance calculation. 4: grid (x,y) in degrees, *width* in km, Spherical distance calculation. 5: grid (x,y) in Mercator ``projection='m1'`` img units, *width* in km, Spherical distance calculation. {I} nans : str or float **i**\|\ **p**\|\ **r**. Determine how NaN-values in the input grid affects the filtered output. {R} 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} {f} {r} Returns ------- ret: xarray.DataArray or None Return type depends on whether the ``outgrid`` parameter is set: - :class:`xarray.DataArray` if ``outgrid`` is not set - None if ``outgrid`` is set (grid output will be stored in file set by ``outgrid``) Example ------- >>> 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") """ with GMTTempFile(suffix=".nc") as tmpfile: with Session() as lib: file_context = lib.virtualfile_from_data(check_kind="raster", data=grid) with file_context as infile: 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) return load_dataarray(outgrid) if outgrid == tmpfile.name else None
def test_io_load_dataarray_cache(): """ Check that load_dataarray fails when the cache argument is used. """ with pytest.raises(TypeError): _ = load_dataarray("somefile.nc", cache=True)
def grdgradient(grid, **kwargs): r""" Compute the directional derivative of the vector gradient of the data. Can accept ``azimuth``, ``direction``, and ``radiance`` input to create the resulting gradient. Full option list at :gmt-docs:`grdgradient.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. azimuth : int or float or str or list *azim*\ [/*azim2*]. Azimuthal direction for a directional derivative; *azim* is the angle in the x,y plane measured in degrees positive clockwise from north (the +y direction) toward east (the +x direction). The negative of the directional derivative, :math:`-(\frac{{dz}}{{dx}}\sin(\mbox{{azim}}) + \ \frac{{dz}}{{dy}}\cos(\mbox{{azim}}))`, is found; negation yields positive values when the slope of :math:`z(x,y)` is downhill in the *azim* direction, the correct sense for shading the illumination of an image by a light source above the x,y plane shining from the *azim* direction. Optionally, supply two azimuths, *azim*/*azim2*, in which case the gradients in each of these directions are calculated and the one larger in magnitude is retained; this is useful for illuminating data with two directions of lineated structures, e.g., *0*/*270* illuminates from the north (top) and west (left). Finally, if *azim* is a file it must be a grid of the same domain, spacing and registration as *grid* that will update the azimuth at each output node when computing the directional derivatives. direction : str [**a**][**c**][**o**][**n**]. Find the direction of the positive (up-slope) gradient of the data. The following options are supported: - **a** - Find the aspect (i.e., the down-slope direction) - **c** - Use the conventional Cartesian angles measured counterclockwise from the positive x (east) direction. - **o** - Report orientations (0-180) rather than directions (0-360). - **n** - Add 90 degrees to all angles (e.g., to give local strikes of the surface). radiance : str or list [**m**\|\ **s**\|\ **p**]\ *azim/elev*\ [**+a**\ *ambient*][**+d**\ *diffuse*][**+p**\ *specular*][**+s**\ *shine*]. Compute Lambertian radiance appropriate to use with :doc:`pygmt.Figure.grdimage` and :doc:`pygmt.Figure.grdview`. The Lambertian Reflection assumes an ideal surface that reflects all the light that strikes it and the surface appears equally bright from all viewing directions. Here, *azim* and *elev* are the azimuth and elevation of the light vector. Optionally, supply *ambient* [0.55], *diffuse* [0.6], *specular* [0.4], or *shine* [10], which are parameters that control the reflectance properties of the surface. Default values are given in the brackets. Use **s** for a simpler Lambertian algorithm. Note that with this form you only have to provide azimuth and elevation. Alternatively, use **p** for the Peucker piecewise linear approximation (simpler but faster algorithm; in this case *azim* and *elev* are hardwired to 315 and 45 degrees. This means that even if you provide other values they will be ignored.). normalize : str or bool [**e**\|\ **t**][*amp*][**+a**\ *ambient*][**+s**\ *sigma*]\ [**+o**\ *offset*]. The actual gradients :math:`g` are offset and scaled to produce normalized gradients :math:`g_n` with a maximum output magnitude of *amp*. If *amp* is not given, default *amp* = 1. If *offset* is not given, it is set to the average of :math:`g`. The following forms are supported: - **True** - Normalize using :math:`g_n = \mbox{{amp}}\ (\frac{{g - \mbox{{offset}}}}{{max(|g - \mbox{{offset}}|)}})` - **e** - Normalize using a cumulative Laplace distribution yielding: :math:`g_n = \mbox{{amp}}(1 - \ \exp{{(\sqrt{{2}}\frac{{g - \mbox{{offset}}}}{{\sigma}}))}}`, where :math:`\sigma` is estimated using the L1 norm of :math:`(g - \mbox{{offset}})` if it is not given. - **t** - Normalize using a cumulative Cauchy distribution yielding: :math:`g_n = \ \frac{{2(\mbox{{amp}})}}{{\pi}}(\tan^{{-1}}(\frac{{g - \ \mbox{{offset}}}}{{\sigma}}))` where :math:`\sigma` is estimated using the L2 norm of :math:`(g - \mbox{{offset}})` if it is not given. As a final option, you may add **+a**\ *ambient* to add *ambient* to all nodes after gradient calculations are completed. tiles : str **c**\|\ **r**\|\ **R**. Controls how normalization via ``normalize`` is carried out. When multiple grids should be normalized the same way (i.e., with the same *offset* and/or *sigma*), we must pass these values via ``normalize``. However, this is inconvenient if we compute these values from a grid. Use **c** to save the results of *offset* and *sigma* to a statistics file; if grid output is not needed for this run then do not specify ``outgrid``. For subsequent runs, just use **r** to read these values. Using **R** will read then delete the statistics file. {R} slope_file : str Name of output grid file with scalar magnitudes of gradient vectors. Requires ``direction`` but makes ``outgrid`` optional. {V} {f} {n} Returns ------- ret: xarray.DataArray or None Return type depends on whether the ``outgrid`` parameter is set: - :class:`xarray.DataArray` if ``outgrid`` is not set - None if ``outgrid`` is set (grid output will be stored in file set by ``outgrid``) Example ------- >>> import pygmt >>> # Load a grid of @earth_relief_30m data, with an x-range of 10 to 30, >>> # and a y-range of 15 to 25 >>> grid = pygmt.datasets.load_earth_relief( ... resolution="30m", region=[10, 30, 15, 25] ... ) >>> # Create a new grid from an input grid, set the azimuth to 10 degrees, >>> new_grid = pygmt.grdgradient(grid=grid, azimuth=10) """ with GMTTempFile(suffix=".nc") as tmpfile: if kwargs.get("Q") is not None and kwargs.get("N") is None: raise GMTInvalidInput("""Must specify normalize if tiles is specified.""") if not args_in_kwargs(args=["A", "D", "E"], kwargs=kwargs): raise GMTInvalidInput( """At least one of the following parameters must be specified: azimuth, direction, or radiance""" ) with Session() as lib: file_context = lib.virtualfile_from_data(check_kind="raster", data=grid) with file_context as infile: if (outgrid := kwargs.get("G")) is None: kwargs["G"] = outgrid = tmpfile.name # output to tmpfile lib.call_module( module="grdgradient", args=build_arg_string(kwargs, infile=infile) ) return load_dataarray(outgrid) if outgrid == tmpfile.name else None
def _grdhisteq(grid, output_type, **kwargs): r""" Perform histogram equalization for a grid. Must provide ``outfile`` or ``outgrid``. Full option list at :gmt-docs:`grdhisteq.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 bool or None The name of the output netCDF file with extension .nc to store the grid in. outfile : str or bool or None The name of the output ASCII file to store the results of the histogram equalization in. output_type: str Determines the output type. Use "file", "xarray", "pandas", or "numpy". divisions : int Set the number of divisions of the data range [Default is 16]. {R} {V} {h} Returns ------- ret: pandas.DataFrame or xarray.DataArray or None Return type depends on whether the ``outgrid`` parameter is set: - xarray.DataArray if ``output_type`` is "xarray"" - numpy.ndarray if ``output_type`` is "numpy" - pandas.DataFrame if ``output_type`` is "pandas" - None if ``output_type`` is "file" (output is stored in ``outgrid`` or ``outfile``) See Also ------- :meth:`pygmt.grd2cpt` """ with Session() as lib: file_context = lib.virtualfile_from_data(check_kind="raster", data=grid) with file_context as infile: lib.call_module( module="grdhisteq", args=build_arg_string(kwargs, infile=infile) ) if output_type == "file": return None if output_type == "xarray": return load_dataarray(kwargs["G"]) result = pd.read_csv( filepath_or_buffer=kwargs["D"], sep="\t", header=None, names=["start", "stop", "bin_id"], dtype={ "start": np.float32, "stop": np.float32, "bin_id": np.uint32, }, ) if output_type == "numpy": return result.to_numpy() return result.set_index("bin_id")
def grdcut(grid, **kwargs): r""" 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`` 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. {V} {f} Returns ------- ret: xarray.DataArray or None Return type depends on whether the ``outgrid`` parameter is set: - :class:`xarray.DataArray` if ``outgrid`` is not set - None if ``outgrid`` is set (grid output will be stored in file set by ``outgrid``) """ with GMTTempFile(suffix=".nc") as tmpfile: with Session() as lib: file_context = lib.virtualfile_from_data(check_kind="raster", data=grid) with file_context as infile: 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) return load_dataarray(outgrid) if outgrid == tmpfile.name else None
def xyz2grd(data=None, x=None, y=None, z=None, **kwargs): r""" Create a grid file from table data. Reads one or more tables with *x, y, z* columns and creates a binary grid file. xyz2grd will report if some of the nodes are not filled in with data. Such unconstrained nodes are set to a value specified by the user [Default is NaN]. Nodes with more than one value will be set to the mean value. Full option list at :gmt-docs:`xyz2grd.html` {aliases} Parameters ---------- data : str or {table-like} Pass in (x, y, z) or (longitude, latitude, elevation) values by providing a file name to an ASCII data table, a 2D {table-classes}. x/y/z : 1d arrays The arrays of x and y coordinates and z data points. outgrid : str or None Optional. The name of the output netCDF file with extension .nc to store the grid in. duplicate : str [**d**\|\ **f**\|\ **l**\|\ **m**\|\ **n**\|\ **r**\|\ **S**\|\ **s**\|\ **u**\|\ **z**]. By default we will calculate mean values if multiple entries fall on the same node. Use **-A** to change this behavior, except it is ignored if **-Z** is given. Append **f** or **s** to simply keep the first or last data point that was assigned to each node. Append **l** or **u** or **d** to find the lowest (minimum) or upper (maximum) value or the difference between the maximum and miminum value at each node, respectively. Append **m** or **r** or **S** to compute mean or RMS value or standard deviation at each node, respectively. Append **n** to simply count the number of data points that were assigned to each node (this only requires two input columns *x* and *y* as *z* is not consulted). Append **z** to sum multiple values that belong to the same node. {I} {J} {R} {V} convention : str [*flags*]. Read a 1-column ASCII [or binary] table. This assumes that all the nodes are present and sorted according to specified ordering convention contained in *flags*. If incoming data represents rows, make *flags* start with **T**\ (op) if first row is y = ymax or **B**\ (ottom) if first row is y = ymin. Then, append **L** or **R** to indicate that first element is at left or right end of row. Likewise for column formats: start with **L** or **R** to position first column, and then append **T** or **B** to position first element in a row. **Note**: These two row/column indicators are only required for grids; for other tables they do not apply. For gridline registered grids: If data are periodic in x but the incoming data do not contain the (redundant) column at x = xmax, append **x**. For data periodic in y without redundant row at y = ymax, append **y**. Append **s**\ *n* to skip the first *n* number of bytes (probably a header). If the byte-order or the words needs to be swapped, append **w**. Select one of several data types (all binary except **a**): - **A** ASCII representation of one or more floating point values per record - **a** ASCII representation of a single item per record - **c** int8_t, signed 1-byte character - **u** uint8_t, unsigned 1-byte character - **h** int16_t, signed 2-byte integer - **H** uint16_t, unsigned 2-byte integer - **i** int32_t, signed 4-byte integer - **I** uint32_t, unsigned 4-byte integer - **l** int64_t, long (8-byte) integer - **L** uint64_t, unsigned long (8-byte) integer - **f** 4-byte floating point single precision - **d** 8-byte floating point double precision [Default format is scanline orientation of ASCII numbers: **La**]. The difference between **A** and **a** is that the latter can decode both *date*\ **T**\ *clock* and *ddd:mm:ss[.xx]* formats but expects each input record to have a single value, while the former can handle multiple values per record but can only parse regular floating point values. Translate incoming *z*-values via the ``incols`` parameter. {b} {d} {e} {f} {h} {i} {r} {w} Returns ------- ret: xarray.DataArray or None Return type depends on whether the ``outgrid`` parameter is set: - :class:`xarray.DataArray`: if ``outgrid`` is not set - None if ``outgrid`` is set (grid output will be stored in file set by ``outgrid``) Example ------- >>> import numpy as np >>> import pygmt >>> # generate a grid for z=x**2+y**2, with an x-range of 0 to 3, >>> # and a y-range of 10.5 to 12.5. The x- and y-spacing are 1.0 and 0.5. >>> x, y = np.meshgrid([0, 1, 2, 3], [10.5, 11.0, 11.5, 12.0, 12.5]) >>> z = x**2 + y**2 >>> xx, yy, zz = x.flatten(), y.flatten(), z.flatten() >>> grid = pygmt.xyz2grd( ... x=xx, y=yy, z=zz, spacing=(1.0, 0.5), region=[0, 3, 10, 13] ... ) """ if kwargs.get("I") is None or kwargs.get("R") is None: raise GMTInvalidInput("Both 'region' and 'spacing' must be specified.") with GMTTempFile(suffix=".nc") as tmpfile: with Session() as lib: file_context = lib.virtualfile_from_data( check_kind="vector", data=data, x=x, y=y, z=z, required_z=True ) with file_context as infile: if (outgrid := kwargs.get("G")) is None: kwargs["G"] = outgrid = tmpfile.name # output to tmpfile lib.call_module( module="xyz2grd", args=build_arg_string(kwargs, infile=infile) ) return load_dataarray(outgrid) if outgrid == tmpfile.name else None
def nearneighbor(data=None, x=None, y=None, z=None, **kwargs): r""" Grid table data using a "Nearest neighbor" algorithm **nearneighbor** reads arbitrarily located (*x,y,z*\ [,\ *w*]) triples [quadruplets] and uses a nearest neighbor algorithm to assign a weighted average value to each node that has one or more data points within a search radius centered on the node with adequate coverage across a subset of the chosen sectors. The node value is computed as a weighted mean of the nearest point from each sector inside the search radius. The weighting function and the averaging used is given by: .. math:: w(r_i) = \frac{{w_i}}{{1 + d(r_i) ^ 2}}, \quad d(r) = \frac {{3r}}{{R}}, \quad \bar{{z}} = \frac{{\sum_i^n w(r_i) z_i}}{{\sum_i^n w(r_i)}} where :math:`n` is the number of data points that satisfy the selection criteria and :math:`r_i` is the distance from the node to the *i*'th data point. If no data weights are supplied then :math:`w_i = 1`. .. figure:: https://docs.generic-mapping-tools.org/dev/_images/GMT_nearneighbor.png # noqa: W505 :width: 300 px :align: center Search geometry includes the search radius (R) which limits the points considered and the number of sectors (here 4), which restricts how points inside the search radius contribute to the value at the node. Only the closest point in each sector (red circles) contribute to the weighted estimate. Takes a matrix, xyz triples, or a file name as input. Must provide either ``data`` or ``x``, ``y``, and ``z``. Full option list at :gmt-docs:`nearneighbor.html` {aliases} Parameters ---------- data : str or {table-like} Pass in (x, y, z) or (longitude, latitude, elevation) values by providing a file name to an ASCII data table, a 2D {table-classes}. x/y/z : 1d arrays Arrays of x and y coordinates and values z of the data points. {I} {R} search_radius : str Sets the search radius that determines which data points are considered close to a node. outgrid : str Optional. The file name for the output netcdf file with extension .nc to store the grid in. empty : str Optional. Set the value assigned to empty nodes. Defaults to NaN. sectors : str *sectors*\ [**+m**\ *min_sectors*]\|\ **n**. Optional. The circular search area centered on each node is divided into *sectors* sectors. Average values will only be computed if there is *at least* one value inside each of at least *min_sectors* of the sectors for a given node. Nodes that fail this test are assigned the value NaN (but see ``empty``). If **+m** is omitted then *min_sectors* is set to be at least 50% of *sectors* (i.e., rounded up to next integer) [Default is a quadrant search with 100% coverage, i.e., *sectors* = *min_sectors* = 4]. Note that only the nearest value per sector enters into the averaging; the more distant points are ignored. Alternatively, use ``sectors="n"`` to call GDAL's nearest neighbor algorithm instead. {V} {a} {b} {d} {e} {f} {g} {h} {i} {r} {w} Returns ------- ret: xarray.DataArray or None Return type depends on whether the ``outgrid`` parameter is set: - :class:`xarray.DataArray`: if ``outgrid`` is not set - None if ``outgrid`` is set (grid output will be stored in file set by ``outgrid``) """ with GMTTempFile(suffix=".nc") as tmpfile: with Session() as lib: # Choose how data will be passed into the module table_context = lib.virtualfile_from_data(check_kind="vector", data=data, x=x, y=y, z=z, required_z=True) with table_context as infile: 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) return load_dataarray(outgrid) if outgrid == tmpfile.name else None
def load_earth_age(resolution="01d", region=None, registration=None): r""" Load Earth seafloor crustal ages in various resolutions. The grids are downloaded to a user data directory (usually ``~/.gmt/server/earth/earth_age/``) the first time you invoke this function. Afterwards, it will load the grid from the data directory. So you'll need an internet connection the first time around. These grids can also be accessed by passing in the file name **@earth_age**\_\ *res*\[_\ *reg*] to any grid plotting/processing function. *res* is the grid resolution (see below), and *reg* is grid registration type (**p** for pixel registration or **g** for gridline registration). Refer to :gmt-datasets:`earth-age.html` for more details. Parameters ---------- resolution : str The grid resolution. The suffix ``d`` and ``m`` stand for arc-degree, arc-minute and arc-second. It can be ``'01d'``, ``'30m'``, ``'20m'``, ``'15m'``, ``'10m'``, ``'06m'``, ``'05m'``, ``'04m'``, ``'03m'``, ``'02m'``, or ``'01m'``. region : str or list The subregion of the grid to load, in the forms of a list [*xmin*, *xmax*, *ymin*, *ymax*] or a string *xmin/xmax/ymin/ymax*. Required for grids with resolutions higher than 5 arc-minute (i.e., ``05m``). registration : str Grid registration type. Either ``pixel`` for pixel registration or ``gridline`` for gridline registration. Default is ``None``, where a pixel-registered grid is returned unless only the gridline-registered grid is available. Returns ------- grid : :class:`xarray.DataArray` The Earth seafloor crustal age grid. Coordinates are latitude and longitude in degrees. Age is in millions of years (Myr). Note ---- The :class:`xarray.DataArray` grid doesn't support slice operation, for Earth seafloor crustal age with resolutions of 5 arc-minutes or higher, which are stored as smaller tiles. """ # earth seafloor crust age data stored as single grids for low resolutions non_tiled_resolutions = ["01d", "30m", "20m", "15m", "10m", "06m"] # earth seafloor crust age data stored as tiles for high resolutions tiled_resolutions = ["05m", "04m", "03m", "02m", "01m"] if registration in ("pixel", "gridline", None): # If None, let GMT decide on Pixel/Gridline type reg = f"_{registration[0]}" if registration else "" else: raise GMTInvalidInput( f"Invalid grid registration: '{registration}', should be either " "'pixel', 'gridline' or None. Default is None, where a " "pixel-registered grid is returned unless only the " "gridline-registered grid is available." ) if resolution not in non_tiled_resolutions + tiled_resolutions: raise GMTInvalidInput(f"Invalid Earth relief resolution '{resolution}'.") # Choose earth relief data prefix earth_age_prefix = "earth_age_" # different ways to load tiled and non-tiled earth relief data # Known issue: tiled grids don't support slice operation # See https://github.com/GenericMappingTools/pygmt/issues/524 if region is None: if resolution not in non_tiled_resolutions: raise GMTInvalidInput( f"'region' is required for Earth age resolution '{resolution}'." ) fname = which(f"@earth_age_{resolution}{reg}", download="a") grid = load_dataarray(fname, engine="netcdf4") else: grid = grdcut(f"@{earth_age_prefix}{resolution}{reg}", region=region) # Add some metadata to the grid grid.name = "seafloor_age" grid.attrs["long_name"] = "age of seafloor crust" grid.attrs["units"] = "Myr" grid.attrs["vertical_datum"] = "EMG96" grid.attrs["horizontal_datum"] = "WGS84" # Remove the actual range because it gets outdated when indexing the grid, # which causes problems when exporting it to netCDF for usage on the # command-line. grid.attrs.pop("actual_range") for coord in grid.coords: grid[coord].attrs.pop("actual_range") return grid
def dimfilter(grid, **kwargs): r""" Filter a grid by dividing the filter circle. Filter a grid in the space (or time) domain by dividing the given filter circle into the given number of sectors, applying one of the selected primary convolution or non-convolution filters to each sector, and choosing the final outcome according to the selected secondary filter. It computes distances using Cartesian or Spherical geometries. The output grid can optionally be generated as a subregion of the input and/or with a new increment using ``spacing``, which may add an "extra space" in the input data to prevent edge effects for the output grid. If the filter is low-pass, then the output may be less frequently sampled than the input. **dimfilter** will not produce a smooth output as other spatial filters do because it returns a minimum median out of *N* medians of *N* sectors. The output can be rough unless the input data is noise-free. Thus, an additional filtering (e.g., Gaussian via :func:`pygmt.grdfilter`) of the DiM-filtered data is generally recommended. Full option list at :gmt-docs:`dimfilter.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. distance : int or str Distance flag tells how grid (x,y) relates to filter width, as follows: - **0**\ : grid (x,y) in same units as *width*, Cartesian distances. - **1**\ : grid (x,y) in degrees, *width* in kilometers, 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 two options are slower because they recompute weights for each latitude. - **3**\ : grid (x,y) in degrees, *width* in km, dx scaled by cosine(y), Cartesian distance calculation. - **4**\ : grid (x,y) in degrees, *width* in km, Spherical distance calculation. filter : str **x**\ *width*\ [**+l**\|\ **u**]. Sets the primary filter type. Choose among convolution and non-convolution filters. Use the filter code **x** followed by the full diameter *width*. Available convolution filters are: - (**b**) Boxcar: All weights are equal. - (**c**) Cosine Arch: Weights follow a cosine arch curve. - (**g**) Gaussian: Weights are given by the Gaussian function. Non-convolution filters are: - (**m**) Median: Returns median value. - (**p**) Maximum likelihood probability (a mode estimator): Return modal value. If more than one mode is found we return their average value. Append **+l** or **+h** to the filter width if you want to return the smallest or largest of each sector's modal values. sectors : str **x**\ *sectors*\ [**+l**\|\ **u**] Sets the secondary filter type **x** and the number of bow-tie sectors. *sectors* must be integer and larger than 0. When *sectors* is set to 1, the secondary filter is not effective. Available secondary filters **x** are: - (**l**) Lower: Return the minimum of all filtered values. - (**u**) Upper: Return the maximum of all filtered values. - (**a**) Average: Return the mean of all filtered values. - (**m**) Median: Return the median of all filtered values. - (**p**) Mode: Return the mode of all filtered values: If more than one mode is found we return their average value. Append **+l** or **+h** to the sectors if you rather want to return the smallest or largest of the modal values. spacing : str or list *x_inc* [and optionally *y_inc*] is the output Increment. Append **m** to indicate minutes, or **c** to indicate seconds. If the new *x_inc*, *y_inc* are NOT integer multiples of the old ones (in the input data), filtering will be considerably slower. [Default: Same as input.] region : str or list [*xmin*, *xmax*, *ymin*, *ymax*]. Defines the region of the output points. [Default: Same as input.] {V} Returns ------- ret: xarray.DataArray or None Return type depends on whether the ``outgrid`` parameter is set: - :class:`xarray.DataArray` if ``outgrid`` is not set - None if ``outgrid`` is set (grid output will be stored in file set by ``outgrid``) """ if not all(arg in kwargs for arg in ["D", "F", "N"]) and "Q" not in kwargs: raise GMTInvalidInput( """At least one of the following parameters must be specified: distance, filters, or sectors.""") with GMTTempFile(suffix=".nc") as tmpfile: with Session() as lib: file_context = lib.virtualfile_from_data(check_kind=None, data=grid) with file_context as infile: if (outgrid := kwargs.get("G")) is None: kwargs["G"] = outgrid = tmpfile.name # output to tmpfile lib.call_module(module="dimfilter", args=build_arg_string(kwargs, infile=infile)) return load_dataarray(outgrid) if outgrid == tmpfile.name else None
def load_earth_relief(resolution="01d", region=None, registration=None, use_srtm=False): r""" Load Earth relief grids (topography and bathymetry) in various resolutions. The grids are downloaded to a user data directory (usually ``~/.gmt/server/earth/earth_relief/``) the first time you invoke this function. Afterwards, it will load the grid from the data directory. So you'll need an internet connection the first time around. These grids can also be accessed by passing in the file name **@earth_relief**\_\ *res*\[_\ *reg*] to any grid plotting/processing function. *res* is the grid resolution (see below), and *reg* is grid registration type (**p** for pixel registration or **g** for gridline registration). Refer to :gmt-datasets:`earth-relief.html` for more details. Parameters ---------- resolution : str The grid resolution. The suffix ``d``, ``m`` and ``s`` stand for arc-degree, arc-minute and arc-second. It can be ``'01d'``, ``'30m'``, ``'20m'``, ``'15m'``, ``'10m'``, ``'06m'``, ``'05m'``, ``'04m'``, ``'03m'``, ``'02m'``, ``'01m'``, ``'30s'``, ``'15s'``, ``'03s'``, or ``'01s'``. region : str or list The subregion of the grid to load, in the forms of a list [*xmin*, *xmax*, *ymin*, *ymax*] or a string *xmin/xmax/ymin/ymax*. Required for Earth relief grids with resolutions higher than 5 arc-minute (i.e., ``05m``). registration : str Grid registration type. Either ``pixel`` for pixel registration or ``gridline`` for gridline registration. Default is ``None``, where a pixel-registered grid is returned unless only the gridline-registered grid is available. use_srtm : bool By default, the land-only SRTM tiles from NASA are used to generate the ``'03s'`` and ``'01s'`` grids, and the missing ocean values are filled by up-sampling the SRTM15+V2.1 tiles which have a resolution of 15 arc-second (i.e., ``'15s'``). If True, will only load the original land-only SRTM tiles. Returns ------- grid : :class:`xarray.DataArray` The Earth relief grid. Coordinates are latitude and longitude in degrees. Relief is in meters. Note ---- The :class:`xarray.DataArray` grid doesn't support slice operation, for Earth relief data with resolutions of 5 arc-minutes or higher, which are stored as smaller tiles. Examples -------- >>> # load the default grid (pixel-registered 01d grid) >>> grid = load_earth_relief() >>> # load the 30m grid with "gridline" registration >>> grid = load_earth_relief("30m", registration="gridline") >>> # load high-resolution grid for a specific region >>> grid = load_earth_relief( ... "05m", region=[120, 160, 30, 60], registration="gridline" ... ) >>> # load the original 3 arc-second land-only SRTM tiles from NASA >>> grid = load_earth_relief( ... "03s", ... region=[135, 136, 35, 36], ... registration="gridline", ... use_srtm=True, ... ) """ # earth relief data stored as single grids for low resolutions non_tiled_resolutions = ["01d", "30m", "20m", "15m", "10m", "06m"] # earth relief data stored as tiles for high resolutions tiled_resolutions = [ "05m", "04m", "03m", "02m", "01m", "30s", "15s", "03s", "01s" ] # resolutions of original land-only SRTM tiles from NASA land_only_srtm_resolutions = ["03s", "01s"] if registration in ("pixel", "gridline", None): # If None, let GMT decide on Pixel/Gridline type reg = f"_{registration[0]}" if registration else "" else: raise GMTInvalidInput( f"Invalid grid registration: '{registration}', should be either " "'pixel', 'gridline' or None. Default is None, where a " "pixel-registered grid is returned unless only the " "gridline-registered grid is available.") if resolution not in non_tiled_resolutions + tiled_resolutions: raise GMTInvalidInput( f"Invalid Earth relief resolution '{resolution}'.") # Check combination of resolution and registration. if (resolution == "15s" and registration == "gridline") or (resolution in ("03s", "01s") and registration == "pixel"): raise GMTInvalidInput( f"{registration}-registered Earth relief data for " f"resolution '{resolution}' is not supported.") # Choose earth relief data prefix earth_relief_prefix = "earth_relief_" if use_srtm and resolution in land_only_srtm_resolutions: earth_relief_prefix = "srtm_relief_" # different ways to load tiled and non-tiled earth relief data # Known issue: tiled grids don't support slice operation # See https://github.com/GenericMappingTools/pygmt/issues/524 if region is None: if resolution not in non_tiled_resolutions: raise GMTInvalidInput( f"'region' is required for Earth relief resolution '{resolution}'." ) fname = which(f"@earth_relief_{resolution}{reg}", download="a") grid = load_dataarray(fname, engine="netcdf4") else: grid = grdcut(f"@{earth_relief_prefix}{resolution}{reg}", region=region) # Add some metadata to the grid grid.name = "elevation" grid.attrs["long_name"] = "elevation relative to the geoid" grid.attrs["units"] = "meters" grid.attrs["vertical_datum"] = "EMG96" grid.attrs["horizontal_datum"] = "WGS84" # Remove the actual range because it gets outdated when indexing the grid, # which causes problems when exporting it to netCDF for usage on the # command-line. grid.attrs.pop("actual_range") for coord in grid.coords: grid[coord].attrs.pop("actual_range") return grid
class triangulate: # pylint: disable=invalid-name """ Delaunay triangulation or Voronoi partitioning and gridding of Cartesian data. Triangulate reads in x,y[,z] data and performs Delaunay triangulation, i.e., it finds how the points should be connected to give the most equilateral triangulation possible. If a map projection (give ``region`` and ``projection``) is chosen then it is applied before the triangulation is calculated. By default, the output is triplets of point id numbers that make up each triangle. The id numbers refer to the points position (line number, starting at 0 for the first line) in the input file. If ``outgrid`` and ``spacing`` are set a grid will be calculated based on the surface defined by the planar triangles. The actual algorithm used in the triangulations is either that of Watson [1982] or Shewchuk [1996] [Default is Shewchuk if installed; type ``gmt get GMT_TRIANGULATE`` on the command line to see which method is selected]. Furthermore, if the Shewchuk algorithm is installed then you can also perform the calculation of Voronoi polygons and optionally grid your data via the natural nearest neighbor algorithm. Note ---- For geographic data with global or very large extent you should consider :gmt-docs:`sphtriangulate <sphtriangulate.html>` instead since ``triangulate`` is a Cartesian or small-geographic area operator and is unaware of periodic or polar boundary conditions. """ @staticmethod @fmt_docstring @use_alias( G="outgrid", I="spacing", J="projection", R="region", V="verbose", b="binary", d="nodata", e="find", f="coltypes", h="header", i="incols", r="registration", s="skiprows", w="wrap", ) @kwargs_to_strings(I="sequence", R="sequence", i="sequence_comma") def _triangulate(data=None, x=None, y=None, z=None, *, output_type, outfile=None, **kwargs): """ Delaunay triangulation or Voronoi partitioning and gridding of Cartesian data. Must provide ``outfile`` or ``outgrid``. Full option list at :gmt-docs:`triangulate.html` {aliases} Parameters ---------- x/y/z : np.ndarray Arrays of x and y coordinates and values z of the data points. data : str or {table-like} Pass in (x, y, z) or (longitude, latitude, elevation) values by providing a file name to an ASCII data table, a 2D {table-classes}. {J} {R} {I} outgrid : bool or str The name of the output netCDF file with extension .nc to store the grid in. The interpolation is performed in the original coordinates, so if your triangles are close to the poles you are better off projecting all data to a local coordinate system before using ``triangulate`` (this is true of all gridding routines) or instead select :gmt-docs:`sphtriangulate <sphtriangulate.html>`. outfile : str or bool or None The name of the output ASCII file to store the results of the histogram equalization in. output_type: str Determines the output type. Use "file", "xarray", "pandas", or "numpy". {V} {b} {d} {e} {f} {h} {i} {r} Only valid with ``outgrid``. {s} {w} Returns ------- ret: numpy.ndarray or pandas.DataFrame or xarray.DataArray or None Return type depends on the ``output_type`` parameter: - numpy.ndarray if ``output_type`` is "numpy" - pandas.DataFrame if ``output_type`` is "pandas" - xarray.DataArray if ``output_type`` is "xarray"" - None if ``output_type`` is "file" (output is stored in ``outgrid`` or ``outfile``) """ with Session() as lib: # Choose how data will be passed into the module table_context = lib.virtualfile_from_data(check_kind="vector", data=data, x=x, y=y, z=z, required_z=False) with table_context as infile: # table output if outgrid is unset, else output to outgrid if (outgrid := kwargs.get("G")) is None: kwargs.update({">": outfile}) lib.call_module(module="triangulate", args=build_arg_string(kwargs, infile=infile)) if output_type == "file": return None if output_type == "xarray": return load_dataarray(outgrid) result = pd.read_csv(outfile, sep="\t", header=None) if output_type == "numpy": return result.to_numpy() return result
def sphdistance(data=None, x=None, y=None, **kwargs): r""" Create Voronoi distance, node, or natural nearest-neighbor grid on a sphere. Reads a table containing *lon, lat* columns and performs the construction of Voronoi polygons. These polygons are then processed to calculate the nearest distance to each node of the lattice and written to the specified grid. Full option list at :gmt-docs:`sphdistance.html` {aliases} Parameters ---------- data : str or {table-like} Pass in (x, y) or (longitude, latitude) values by providing a file name to an ASCII data table, a 2D {table-classes}. x/y : 1d arrays Arrays of x and y coordinates. outgrid : str or None The name of the output netCDF file with extension .nc to store the grid in. {I} {R} {V} single_form : bool For large data sets you can save some memory (at the expense of more processing) by only storing one form of location coordinates (geographic or Cartesian 3-D vectors) at any given time, translating from one form to the other when necessary [Default keeps both arrays in memory]. Not applicable with ``voronoi``. duplicate : bool Used to skip duplicate points since the algorithm cannot handle them. [Default assumes there are no duplicates]. quantity : str **d**\|\ **n**\|\ **z**\ [*dist*]. Specify the quantity that should be assigned to the grid nodes [Default is **d**]: - **d** - compute distances to the nearest data point - **n** - assign the ID numbers of the Voronoi polygons that each grid node is inside - **z** - assign all nodes inside the polygon the z-value of the center node for a natural nearest-neighbor grid. Optionally, append the resampling interval along Voronoi arcs in spherical degrees. unit : str Specify the unit used for distance calculations. Choose among **d** (spherical degree), **e** (m), **f** (feet), **k** (km), **M** (mile), **n** (nautical mile) or **u** survey foot. node_table : str Read the information pertaining to each Voronoi polygon (the unique node lon, lat and polygon area) from a separate file [Default acquires this information from the ASCII segment headers of the output file]. Required if binary input via `voronoi` is used. voronoi : str Append the name of a file with pre-calculated Voronoi polygons [Default performs the Voronoi construction on input data]. Returns ------- ret: xarray.DataArray or None Return type depends on whether the ``outgrid`` parameter is set: - :class:`xarray.DataArray` if ``outgrid`` is not set - None if ``outgrid`` is set (grid output will be stored in file set by ``outgrid``) """ if "I" not in kwargs or "R" not in kwargs: raise GMTInvalidInput("Both 'region' and 'spacing' must be specified.") with GMTTempFile(suffix=".nc") as tmpfile: with Session() as lib: file_context = lib.virtualfile_from_data(check_kind="vector", data=data, x=x, y=y) with file_context as infile: 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) return load_dataarray(outgrid) if outgrid == tmpfile.name else None