Skip to content
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

Wrap clip #1779

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions doc/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Plotting tabular data
Figure.contour
Figure.histogram
Figure.meca
Figure.clip
Figure.plot
Figure.plot3d
Figure.rose
Expand Down
1 change: 1 addition & 0 deletions pygmt/figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@ def _repr_html_(self):

from pygmt.src import ( # pylint: disable=import-outside-toplevel
basemap,
clip,
coast,
colorbar,
contour,
Expand Down
1 change: 1 addition & 0 deletions pygmt/src/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from pygmt.src.basemap import basemap
from pygmt.src.binstats import binstats
from pygmt.src.blockm import blockmean, blockmedian, blockmode
from pygmt.src.clip import clip
from pygmt.src.coast import coast
from pygmt.src.colorbar import colorbar
from pygmt.src.config import config
Expand Down
102 changes: 102 additions & 0 deletions pygmt/src/clip.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"""
clip - Create a polygonal clip path.
"""
import contextlib

from pygmt.clib import Session
from pygmt.helpers import build_arg_string, fmt_docstring, kwargs_to_strings, use_alias


@fmt_docstring
@contextlib.contextmanager
@use_alias(
A="straight_line",
B="frame",
J="projection",
N="invert",
R="region",
W="pen",
V="verbose",
)
@kwargs_to_strings(R="sequence")
def clip(self, data=None, x=None, y=None, **kwargs):
r"""
Create a polygonal clip path.

This function sets a clip path for the figure. The clip path is applied
to plotting functions that are called within the context manager.

Full option list at :gmt-docs:`clip.html`

{aliases}

Parameters
----------
data : str or {table-like}
Pass in either a file name to an ASCII data table, a 2D
{table-classes}.
x/y : 1d arrays
The x and y coordinates of the clip path.
{B}
{J}
{R}
straight_line : bool or str
[**m**\|\ **p**\|\ **x**\|\ **y**\|\ **r**\|\ **t**].
By default, geographic line segments are connected as great circle
arcs. To connect them as straight lines, use ``straight_line``.
Alternatively, add **m** to connect the line by first following a
meridian, then a parallel. Or append **p** to start following a
parallel, then a meridian. (This can be practical to connect a line
along parallels, for example). For Cartesian data, points are
simply connected, unless you append **x** or **y** to draw
stair-case curves that whose first move is along *x* or *y*,
respectively. For polar projection, append **r** or **t** to connect
staircase curves whose first move is along *r* or *theta*,
respectively.
invert : bool
Invert the sense of what is inside and outside. For example, when
using a single clip path, use ``invert=True`` to only plot points
outside to path. Cannot be used with ``frame``.
{V}
pen : str
Draw the output of the clip path using the pen attributes before
clipping is initiated [Default is no outline].


Examples
--------
>>> import pygmt
>>>
>>> # Create x,y data for the clip path
>>> x = [-60, 60, 60, -60]
>>> y = [-30, -30, 30, 30]
>>>
>>> # Load the 1 degree global earth relief
>>> grid = pygmt.datasets.load_earth_relief()
>>>
>>> # Create a figure and draw the map frame
>>> fig = pygmt.Figure()
>>> fig.basemap(region="d", projection="W15c", frame=True)
>>>
>>> # Use a "with" statement to initialize the clip context manager
>>> with fig.clip(x=x, y=y):
... # Map elements under the "with" statement are clipped
... fig.grdimage(grid=grid)
...
>>> fig.show() # doctest: +SKIP
<IPython.core.display.Image object>
"""
kwargs = self._preprocess(**kwargs) # pylint: disable=protected-access
with Session() as lib:
try:
file_context = lib.virtualfile_from_data(
check_kind="vector", data=data, x=x, y=y
)

with file_context as fname:
arg_str = " ".join([fname, build_arg_string(kwargs)])
lib.call_module("clip", arg_str)
yield
finally:
# End the top most clipping path
lib.call_module("clip", "-C1")
4 changes: 4 additions & 0 deletions pygmt/tests/baseline/test_clip.png.dvc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
outs:
- md5: 449fec4d58132742abb615931e6e240a
size: 7968
path: test_clip.png
79 changes: 79 additions & 0 deletions pygmt/tests/test_clip.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"""
Tests for fig.clip.
"""
import numpy as np
import pandas as pd
import pytest
import xarray as xr
from pygmt import Figure
from pygmt.helpers.testing import load_static_earth_relief


@pytest.fixture(scope="module", name="grid")
def fixture_grid():
"""
Load the grid data from the static_earth_relief file.
"""
return load_static_earth_relief()


@pytest.fixture(scope="module", name="dataframe")
def fixture_dataframe():
"""
Load the table data from the sample bathymetry dataset.
"""
return pd.DataFrame(data={"x": [-52, -50, -50, -52], "y": [-20, -20, -16, -16]})


@pytest.fixture(scope="module", name="region")
def fixture_region():
"""
Load the table data from the sample bathymetry dataset.
"""
return [-55, -47, -24, -10]


@pytest.fixture(scope="module", name="projection")
def fixture_projection():
"""
Load the table data from the sample bathymetry dataset.
"""
return "M4c"


@pytest.mark.mpl_image_compare(filename="test_clip.png")
def test_clip_xy(grid, dataframe, region, projection):
"""
Test clip with x,y input.
"""
fig = Figure()
fig.basemap(region=region, frame=True, projection=projection)
with fig.clip(x=dataframe["x"], y=dataframe["y"]):
fig.grdimage(grid=grid)
return fig


@pytest.mark.parametrize("array_func", [np.array, xr.Dataset])
@pytest.mark.mpl_image_compare(filename="test_clip.png")
def test_clip_matrix(array_func, dataframe, grid, region, projection):
"""
Test clip with matrix input for the clip path.
"""
table = array_func(dataframe)
fig = Figure()
fig.basemap(region=region, frame=True, projection=projection)
with fig.clip(data=table):
fig.grdimage(grid=grid, region=region)
return fig


@pytest.mark.mpl_image_compare(filename="test_clip.png")
def test_clip_dataframe(grid, dataframe, region, projection):
"""
Test clip with dataframe input for the clip path.
"""
fig = Figure()
fig.basemap(region=region, frame=True, projection=projection)
with fig.clip(data=dataframe):
fig.grdimage(grid=grid, region=region)
return fig