-
Notifications
You must be signed in to change notification settings - Fork 235
Wrap grdtrack #308
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
weiji14
merged 17 commits into
GenericMappingTools:master
from
weiji14:sampling/grdtrack
Mar 26, 2020
Merged
Wrap grdtrack #308
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
a6cef02
Wrap grdtrack
weiji14 97c2b4a
Enable netcdf file input for grdtrack
weiji14 bcfab7f
Modify grdtrack parameter names according to code review
weiji14 028b55a
Remove east_pacific_rise_grid, add test for load_ocean_ridge_points
weiji14 3776214
Add grdtrack and load_ocean_ridge_points tutorial data to docs
weiji14 a37fb0a
Enable ascii file input for grdtrack
weiji14 b1e7b75
Add gallery example 'sampling along tracks' for grdtrack
weiji14 1f94896
Finalize grdtrack wrapper, use numpy assertion, change grid bg to gray
weiji14 421e10d
Merge branch 'master' into sampling/grdtrack
weiji14 e9c8c3d
Merge branch 'master' into sampling/grdtrack
weiji14 7590d4a
Merge branch 'master' into sampling/grdtrack
weiji14 b737684
Merge branch 'master' into sampling/grdtrack
weiji14 afb4382
Fix bathymetry values in test_grdtrack
weiji14 4581a3e
Merge branch 'master' into sampling/grdtrack
weiji14 fb8bb46
Merge branch 'master' into sampling/grdtrack
weiji14 0ed8eb4
Fix test values and truncate docstrings to 79 char
weiji14 f0b6de3
Minor formatting fix
weiji14 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| Grids | ||
| ----- |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| """ | ||
| Sampling along tracks | ||
| --------------------- | ||
|
|
||
| The :func:`pygmt.grdtrack` function samples a raster grid's value along specified | ||
| points. We will need to input a 2D raster to ``grid`` which can be an | ||
| ``xarray.DataArray``. The ``points`` parameter can be a ``pandas.DataFrame`` table where | ||
| the first two columns are x and y (or longitude and latitude). Note also that there is a | ||
| ``newcolname`` parameter that will be used to name the new column of values we sampled | ||
| from the grid. | ||
|
|
||
| Alternatively, we can provide a NetCDF file path to ``grid``. An ASCII file path can | ||
| also be accepted for ``points``, but an ``outfile`` parameter will then need to be set | ||
| to name the resulting output ASCII file. | ||
| """ | ||
|
|
||
| import pygmt | ||
|
|
||
| # Load sample grid and point datasets | ||
| grid = pygmt.datasets.load_earth_relief() | ||
| points = pygmt.datasets.load_ocean_ridge_points() | ||
| # Sample the bathymetry along the world's ocean ridges at specified track points | ||
| track = pygmt.grdtrack(points=points, grid=grid, newcolname="bathymetry") | ||
|
|
||
| fig = pygmt.Figure() | ||
| # Plot the earth relief grid on Cylindrical Stereographic projection, masking land areas | ||
| fig.basemap(region="g", frame=True, projection="Cyl_stere/150/-20/8i") | ||
| fig.grdimage(grid=grid, cmap="gray") | ||
| fig.coast(land="#666666") | ||
| # Plot using circles (c) of 0.15cm, the sampled bathymetry points | ||
| # Points are colored using elevation values (normalized for visual purposes) | ||
| fig.plot( | ||
| x=track.longitude, | ||
| y=track.latitude, | ||
| style="c0.15c", | ||
| cmap="terra", | ||
| color=(track.bathymetry - track.bathymetry.mean()) / track.bathymetry.std(), | ||
| ) | ||
| fig.show() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| """ | ||
| GMT modules for Sampling of 1-D and 2-D Data | ||
| """ | ||
| import pandas as pd | ||
|
|
||
| from .clib import Session | ||
| from .helpers import ( | ||
| build_arg_string, | ||
| fmt_docstring, | ||
| GMTTempFile, | ||
| data_kind, | ||
| dummy_context, | ||
| ) | ||
| from .exceptions import GMTInvalidInput | ||
|
|
||
|
|
||
| @fmt_docstring | ||
| def grdtrack(points, grid, newcolname=None, outfile=None, **kwargs): | ||
| """ | ||
| Sample grids at specified (x,y) locations. | ||
|
|
||
| Grdtrack reads one or more grid files and a table with (x,y) [or (lon,lat)] | ||
| positions in the first two columns (more columns may be present). It | ||
| interpolates the grid(s) at the positions in the table and writes out the | ||
| table with the interpolated values added as (one or more) new columns. A | ||
| bicubic [Default], bilinear, B-spline or nearest-neighbor (see -n) | ||
| interpolation is used, requiring boundary conditions at the limits of the | ||
| region. | ||
|
|
||
| Full option list at :gmt-docs:`grdtrack.html` | ||
|
|
||
| Parameters | ||
| ---------- | ||
| points: pandas.DataFrame or file (csv, txt, etc) | ||
| Either a table with (x, y) or (lon, lat) values in the first two | ||
| columns, or a data file name. More columns may be present. | ||
|
|
||
| grid: xarray.DataArray or file (netcdf) | ||
| Gridded array from which to sample values from. | ||
|
|
||
| newcolname: str | ||
| Required if 'points' is a pandas.DataFrame. The name for the new column | ||
| in the track pandas.DataFrame table where the sampled values will be | ||
| placed. | ||
|
|
||
| outfile: str | ||
| Required if 'points' is a file. The file name for the output ASCII | ||
| file. | ||
|
|
||
| Returns | ||
| ------- | ||
| track: pandas.DataFrame or None | ||
| Return type depends on whether the outfile parameter is set: | ||
| - pandas.DataFrame table with (x, y, ..., newcolname) if outfile is not | ||
| set | ||
| - None if outfile is set (track output will be stored in outfile) | ||
|
|
||
| """ | ||
|
|
||
| with GMTTempFile(suffix=".csv") as tmpfile: | ||
| with Session() as lib: | ||
| # Store the pandas.DataFrame points table in virtualfile | ||
| if data_kind(points) == "matrix": | ||
| if newcolname is None: | ||
| raise GMTInvalidInput("Please pass in a str to 'newcolname'") | ||
| table_context = lib.virtualfile_from_matrix(points.values) | ||
| elif data_kind(points) == "file": | ||
| if outfile is None: | ||
| raise GMTInvalidInput("Please pass in a str to 'outfile'") | ||
| table_context = dummy_context(points) | ||
| else: | ||
| raise GMTInvalidInput(f"Unrecognized data type {type(points)}") | ||
|
|
||
| # Store the xarray.DataArray grid in virtualfile | ||
| if data_kind(grid) == "grid": | ||
| grid_context = lib.virtualfile_from_grid(grid) | ||
| elif data_kind(grid) == "file": | ||
| grid_context = dummy_context(grid) | ||
| else: | ||
| raise GMTInvalidInput(f"Unrecognized data type {type(grid)}") | ||
|
|
||
| # Run grdtrack on the temporary (csv) points table | ||
| # and (netcdf) grid virtualfile | ||
| with table_context as csvfile: | ||
| with grid_context as grdfile: | ||
| kwargs.update({"G": grdfile}) | ||
| if outfile is None: # Output to tmpfile if outfile is not set | ||
| outfile = tmpfile.name | ||
| arg_str = " ".join( | ||
| [csvfile, build_arg_string(kwargs), "->" + outfile] | ||
| ) | ||
| lib.call_module(module="grdtrack", args=arg_str) | ||
|
|
||
| # Read temporary csv output to a pandas table | ||
| if outfile == tmpfile.name: # if user did not set outfile, return pd.DataFrame | ||
| column_names = points.columns.to_list() + [newcolname] | ||
| result = pd.read_csv(tmpfile.name, sep="\t", names=column_names) | ||
| elif outfile != tmpfile.name: # return None if outfile set, output in outfile | ||
| result = None | ||
|
|
||
| return result | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| """ | ||
| Tests for grdtrack | ||
| """ | ||
| import os | ||
|
|
||
| import numpy.testing as npt | ||
| import pandas as pd | ||
weiji14 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| import pytest | ||
|
|
||
| from .. import grdtrack | ||
| from .. import which | ||
| from ..datasets import load_earth_relief, load_ocean_ridge_points | ||
| from ..exceptions import GMTInvalidInput | ||
| from ..helpers import data_kind | ||
|
|
||
| TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "data") | ||
| TEMP_TRACK = os.path.join(TEST_DATA_DIR, "tmp_track.txt") | ||
|
|
||
|
|
||
| def test_grdtrack_input_dataframe_and_dataarray(): | ||
| """ | ||
| Run grdtrack by passing in a pandas.DataFrame and xarray.DataArray as | ||
| inputs | ||
| """ | ||
| dataframe = load_ocean_ridge_points() | ||
| dataarray = load_earth_relief().sel(lat=slice(-49, -42), lon=slice(-118, -107)) | ||
|
|
||
| output = grdtrack(points=dataframe, grid=dataarray, newcolname="bathymetry") | ||
| assert isinstance(output, pd.DataFrame) | ||
| assert output.columns.to_list() == ["longitude", "latitude", "bathymetry"] | ||
| npt.assert_allclose(output.iloc[0], [-110.9536, -42.2489, -2797.482959]) | ||
|
|
||
| return output | ||
|
|
||
|
|
||
| def test_grdtrack_input_csvfile_and_dataarray(): | ||
| """ | ||
| Run grdtrack by passing in a csvfile and xarray.DataArray as inputs | ||
| """ | ||
| csvfile = which("@ridge.txt", download="c") | ||
| dataarray = load_earth_relief().sel(lat=slice(-49, -42), lon=slice(-118, -107)) | ||
|
|
||
| try: | ||
| output = grdtrack(points=csvfile, grid=dataarray, outfile=TEMP_TRACK) | ||
| assert output is None # check that output is None since outfile is set | ||
| assert os.path.exists(path=TEMP_TRACK) # check that outfile exists at path | ||
|
|
||
| track = pd.read_csv(TEMP_TRACK, sep="\t", header=None, comment=">") | ||
| npt.assert_allclose(track.iloc[0], [-110.9536, -42.2489, -2797.482959]) | ||
| finally: | ||
| os.remove(path=TEMP_TRACK) | ||
|
|
||
| return output | ||
|
|
||
|
|
||
| def test_grdtrack_input_dataframe_and_ncfile(): | ||
| """ | ||
| Run grdtrack by passing in a pandas.DataFrame and netcdf file as inputs | ||
| """ | ||
| dataframe = load_ocean_ridge_points() | ||
| ncfile = which("@earth_relief_60m", download="c") | ||
|
|
||
| output = grdtrack(points=dataframe, grid=ncfile, newcolname="bathymetry") | ||
| assert isinstance(output, pd.DataFrame) | ||
| assert output.columns.to_list() == ["longitude", "latitude", "bathymetry"] | ||
| npt.assert_allclose(output.iloc[0], [-32.2971, 37.4118, -1686.692142]) | ||
|
|
||
| return output | ||
|
|
||
|
|
||
| def test_grdtrack_input_csvfile_and_ncfile(): | ||
| """ | ||
| Run grdtrack by passing in a csvfile and netcdf file as inputs | ||
| """ | ||
| csvfile = which("@ridge.txt", download="c") | ||
| ncfile = which("@earth_relief_60m", download="c") | ||
|
|
||
| try: | ||
| output = grdtrack(points=csvfile, grid=ncfile, outfile=TEMP_TRACK) | ||
| assert output is None # check that output is None since outfile is set | ||
| assert os.path.exists(path=TEMP_TRACK) # check that outfile exists at path | ||
|
|
||
| track = pd.read_csv(TEMP_TRACK, sep="\t", header=None, comment=">") | ||
| npt.assert_allclose(track.iloc[0], [-32.2971, 37.4118, -1686.692142]) | ||
| finally: | ||
| os.remove(path=TEMP_TRACK) | ||
|
|
||
| return output | ||
|
|
||
|
|
||
| def test_grdtrack_wrong_kind_of_points_input(): | ||
| """ | ||
| Run grdtrack using points input that is not a pandas.DataFrame (matrix) or | ||
| file | ||
| """ | ||
| dataframe = load_ocean_ridge_points() | ||
| invalid_points = dataframe.longitude.to_xarray() | ||
| dataarray = load_earth_relief().sel(lat=slice(-49, -42), lon=slice(-118, -107)) | ||
|
|
||
| assert data_kind(invalid_points) == "grid" | ||
| with pytest.raises(GMTInvalidInput): | ||
| grdtrack(points=invalid_points, grid=dataarray, newcolname="bathymetry") | ||
|
|
||
|
|
||
| def test_grdtrack_wrong_kind_of_grid_input(): | ||
| """ | ||
| Run grdtrack using grid input that is not as xarray.DataArray (grid) or | ||
| file | ||
| """ | ||
| dataframe = load_ocean_ridge_points() | ||
| dataarray = load_earth_relief().sel(lat=slice(-49, -42), lon=slice(-118, -107)) | ||
| invalid_grid = dataarray.to_dataset() | ||
|
|
||
| assert data_kind(invalid_grid) == "matrix" | ||
| with pytest.raises(GMTInvalidInput): | ||
| grdtrack(points=dataframe, grid=invalid_grid, newcolname="bathymetry") | ||
|
|
||
|
|
||
| def test_grdtrack_without_newcolname_setting(): | ||
| """ | ||
| Run grdtrack by not passing in newcolname parameter setting | ||
| """ | ||
| dataframe = load_ocean_ridge_points() | ||
| dataarray = load_earth_relief().sel(lat=slice(-49, -42), lon=slice(-118, -107)) | ||
|
|
||
| with pytest.raises(GMTInvalidInput): | ||
| grdtrack(points=dataframe, grid=dataarray) | ||
|
|
||
|
|
||
| def test_grdtrack_without_outfile_setting(): | ||
| """ | ||
| Run grdtrack by not passing in outfile parameter setting | ||
| """ | ||
| csvfile = which("@ridge.txt", download="c") | ||
| dataarray = load_earth_relief().sel(lat=slice(-49, -42), lon=slice(-118, -107)) | ||
|
|
||
| with pytest.raises(GMTInvalidInput): | ||
| grdtrack(points=csvfile, grid=dataarray) | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.