Skip to content

Commit 0e630e3

Browse files
yvonnefroehlichseismanactions-botYvonne
authored
Figure.grdcontour: Adjust processing of arguments passed to the "annotation" and "interval" parameters, deprecate "sequence_plus" (#3116)
Co-authored-by: Dongdong Tian <[email protected]> Co-authored-by: actions-bot <[email protected]> Co-authored-by: Yvonne <[email protected]>
1 parent 72ce692 commit 0e630e3

File tree

4 files changed

+122
-30
lines changed

4 files changed

+122
-30
lines changed

pygmt/src/grdcontour.py

Lines changed: 61 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,16 @@
22
grdcontour - Plot a contour figure.
33
"""
44

5+
import warnings
6+
57
from pygmt.clib import Session
6-
from pygmt.helpers import build_arg_list, fmt_docstring, kwargs_to_strings, use_alias
8+
from pygmt.helpers import (
9+
build_arg_list,
10+
fmt_docstring,
11+
is_nonstr_iter,
12+
kwargs_to_strings,
13+
use_alias,
14+
)
715

816
__doctest_skip__ = ["grdcontour"]
917

@@ -27,9 +35,7 @@
2735
p="perspective",
2836
t="transparency",
2937
)
30-
@kwargs_to_strings(
31-
R="sequence", L="sequence", A="sequence_plus", c="sequence_comma", p="sequence"
32-
)
38+
@kwargs_to_strings(R="sequence", L="sequence", c="sequence_comma", p="sequence")
3339
def grdcontour(self, grid, **kwargs):
3440
r"""
3541
Convert grids or images to contours and plot them on maps.
@@ -43,26 +49,26 @@ def grdcontour(self, grid, **kwargs):
4349
Parameters
4450
----------
4551
{grid}
46-
interval : str or int
52+
interval : float, list, or str
4753
Specify the contour lines to generate.
4854
49-
- The file name of a CPT file where the color boundaries will
50-
be used as contour levels.
51-
- The file name of a 2 (or 3) column file containing the contour
52-
levels (col 1), (**C**)ontour or (**A**)nnotate (col 2), and optional
53-
angle (col 3).
54-
- A fixed contour interval *cont_int* or a single contour with
55-
+\ *cont_int*.
56-
annotation : str, int, or list
55+
- The file name of a CPT file where the color boundaries will be used as
56+
contour levels.
57+
- The file name of a 2 (or 3) column file containing the contour levels (col 0),
58+
(**C**)ontour or (**A**)nnotate (col 1), and optional angle (col 2).
59+
- A fixed contour interval.
60+
- A list of contour levels.
61+
annotation : float, list, or str
5762
Specify or disable annotated contour levels, modifies annotated
5863
contours specified in ``interval``.
5964
60-
- Specify a fixed annotation interval *annot_int* or a
61-
single annotation level +\ *annot_int*.
62-
- Disable all annotation with **-**.
63-
- Optional label modifiers can be specified as a single string
64-
``"[annot_int]+e"`` or with a list of arguments
65-
``([annot_int], "e", "f10p", "gred")``.
65+
- Specify a fixed annotation interval.
66+
- Specify a list of annotation levels.
67+
- Disable all annotations by setting ``annotation="n"``.
68+
- Adjust the appearance by appending different modifiers, e.g.,
69+
``"annot_int+f10p+gred"`` gives annotations with a font size of 10 points
70+
and a red filled box. For all available modifiers see
71+
:gmt-docs:`grdcontour.html#a`.
6672
limit : str or list of 2 ints
6773
*low*/*high*.
6874
Do no draw contours below `low` or above `high`, specify as string
@@ -96,32 +102,58 @@ def grdcontour(self, grid, **kwargs):
96102
Example
97103
-------
98104
>>> import pygmt
99-
>>> # load the 15 arc-minutes grid with "gridline" registration
100-
>>> # in a specified region
105+
>>> # Load the 15 arc-minutes grid with "gridline" registration in the
106+
>>> # specified region
101107
>>> grid = pygmt.datasets.load_earth_relief(
102108
... resolution="15m",
103109
... region=[-92.5, -82.5, -3, 7],
104110
... registration="gridline",
105111
... )
106-
>>> # create a new plot with pygmt.Figure()
112+
>>> # Create a new plot with pygmt.Figure()
107113
>>> fig = pygmt.Figure()
108-
>>> # create the contour plot
114+
>>> # Create the contour plot
109115
>>> fig.grdcontour(
110-
... # pass in the grid downloaded above
116+
... # Pass in the grid downloaded above
111117
... grid=grid,
112-
... # set the interval for contour lines at 250 meters
118+
... # Set the interval for contour lines at 250 meters
113119
... interval=250,
114-
... # set the interval for annotated contour lines at 1,000 meters
120+
... # Set the interval for annotated contour lines at 1,000 meters
115121
... annotation=1000,
116-
... # add a frame for the plot
122+
... # Add a frame for the plot
117123
... frame="a",
118-
... # set the projection to Mercator for the 10 cm figure
124+
... # Set the projection to Mercator for the 10 cm figure
119125
... projection="M10c",
120126
... )
121-
>>> # show the plot
127+
>>> # Show the plot
122128
>>> fig.show()
123129
"""
124130
kwargs = self._preprocess(**kwargs)
131+
132+
# Backward compatibility with the old syntax for the annotation parameter, e.g.,
133+
# [100, "e", "f10p", "gred"].
134+
if is_nonstr_iter(kwargs.get("A")) and any(
135+
i[0] in "acdefgijlLnoprtuvwx=" for i in kwargs["A"] if isinstance(i, str)
136+
):
137+
msg = (
138+
"Argument of the parameter 'annotation'/'A' is using the old, deprecated "
139+
"syntax. Please refer to the PyGMT documentation for the new syntax. "
140+
"The warning will be removed in v0.14.0 and the old syntax will no longer "
141+
"be supported. "
142+
)
143+
warnings.warn(msg, category=FutureWarning, stacklevel=2)
144+
kwargs["A"] = "+".join(f"{item}" for item in kwargs["A"])
145+
146+
# Specify levels for the annotation and interval parameters.
147+
# One level is converted to a string with a trailing comma to separate it from
148+
# specifying an interval.
149+
# Multiple levels are concatenated to a comma-separated string.
150+
for arg in ["A", "C"]:
151+
if is_nonstr_iter(kwargs.get(arg)):
152+
if len(kwargs[arg]) == 1: # One level
153+
kwargs[arg] = str(kwargs[arg][0]) + ","
154+
else: # Multiple levels
155+
kwargs[arg] = ",".join(f"{item}" for item in kwargs[arg])
156+
125157
with Session() as lib:
126158
with lib.virtualfile_in(check_kind="raster", data=grid) as vingrd:
127159
lib.call_module(
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
outs:
2+
- md5: 4d20cdb71af2e6568f64f0246ec860ea
3+
size: 64008
4+
isexec: true
5+
hash: md5
6+
path: test_grdcontour_multiple_levels.png
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
outs:
2+
- md5: fc624766f0b8eac8206735a05c7c9662
3+
size: 45023
4+
isexec: true
5+
hash: md5
6+
path: test_grdcontour_one_level.png

pygmt/tests/test_grdcontour.py

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ def fixture_grid():
2424
@pytest.mark.mpl_image_compare
2525
def test_grdcontour(grid):
2626
"""
27-
Plot a contour image using an xarray grid with fixed contour interval.
27+
Plot a contour image using an xarray grid with fixed (different) contour and
28+
annotation intervals.
2829
"""
2930
fig = Figure()
3031
fig.grdcontour(
@@ -33,6 +34,53 @@ def test_grdcontour(grid):
3334
return fig
3435

3536

37+
@pytest.mark.mpl_image_compare
38+
def test_grdcontour_one_level(grid):
39+
"""
40+
Plot a contour image using an xarray grid with one contour level and one
41+
(different) annotation level.
42+
"""
43+
fig = Figure()
44+
fig.grdcontour(
45+
grid=grid, interval=[400], annotation=[570], projection="M10c", frame=True
46+
)
47+
return fig
48+
49+
50+
@pytest.mark.mpl_image_compare(filename="test_grdcontour_one_level.png")
51+
def test_grdcontour_old_annotations(grid):
52+
"""
53+
Test the old syntax for the annotation parameter using "sequence_plus".
54+
Modified from the "test_grdcontour_one_level()" test. Can be removed in v0.14.0.
55+
"""
56+
fig = Figure()
57+
fig.grdcontour(
58+
grid=grid,
59+
interval=[400],
60+
annotation=["570,", "gwhite"],
61+
projection="M10c",
62+
frame=True,
63+
)
64+
return fig
65+
66+
67+
@pytest.mark.mpl_image_compare
68+
def test_grdcontour_multiple_levels(grid):
69+
"""
70+
Plot a contour image using an xarray grid with multiple (different) contour
71+
and annotation levels.
72+
"""
73+
fig = Figure()
74+
fig.grdcontour(
75+
grid=grid,
76+
interval=[400, 450, 500],
77+
annotation=[400, 570],
78+
projection="M10c",
79+
frame=True,
80+
)
81+
return fig
82+
83+
3684
@pytest.mark.benchmark
3785
@pytest.mark.mpl_image_compare
3886
def test_grdcontour_labels(grid):

0 commit comments

Comments
 (0)