Skip to content

Commit d10f324

Browse files
Merge branch 'main' into add-vector-gmt4
2 parents 019bbf4 + 53faaba commit d10f324

4 files changed

Lines changed: 109 additions & 19 deletions

File tree

.github/workflows/publish-to-pypi.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ jobs:
9797
path: dist/
9898

9999
- name: Publish distribution 📦 to TestPyPI
100-
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
100+
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
101101
with:
102102
repository-url: https://test.pypi.org/legacy/
103103

@@ -121,4 +121,4 @@ jobs:
121121
path: dist/
122122

123123
- name: Publish distribution 📦 to PyPI
124-
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
124+
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0

pygmt/params/frame.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,11 @@ class Frame(BaseParam):
189189
#:
190190
#: GMT uses the notion of primary (the default) and secondary axes, while secondary
191191
#: axes are optional and mostly used for time axes annotations. To specify the
192-
#: attributes for the secondary axes, use the ``xaxis2``, ``yaxis2``, and ``zaxis2``
193-
#: parameters.
192+
#: same attributes for both secondary x and y axes, use the ``axis2`` parameter.
193+
#: To specify the attributes for the secondary axes separately, use the ``xaxis2``,
194+
#: ``yaxis2``, and ``zaxis2`` parameters.
194195
axis: Axis | None = None
196+
axis2: Axis | None = None
195197
xaxis: Axis | None = None
196198
yaxis: Axis | None = None
197199
zaxis: Axis | None = None
@@ -210,17 +212,34 @@ def _validate(self):
210212
conflicts_with=("axis", ["xaxis", "yaxis", "xaxis2", "yaxis2"]),
211213
reason="Either 'axis' or the individual axis parameters can be set, but not both.",
212214
)
215+
if self.axis2 is not None and any(
216+
[self.xaxis, self.yaxis, self.xaxis2, self.yaxis2]
217+
):
218+
raise GMTParameterError(
219+
conflicts_with=("axis2", ["xaxis", "yaxis", "xaxis2", "yaxis2"]),
220+
reason="Either 'axis2' or the individual axis parameters can be set, but not both.",
221+
)
213222

214223
@property
215224
def _aliases(self):
216225
# _Axes() maps to an empty string, which becomes '-B' without arguments and is
217226
# invalid when combined with individual axis settings (e.g., '-B -Bxaf -Byaf').
218227
frame_settings = _Axes(axes=self.axes, title=self.title, fill=self.fill)
228+
has_secondary_xy_axis = any([self.axis2, self.xaxis2, self.yaxis2])
219229
return [
220230
Alias(frame_settings) if str(frame_settings) else Alias(None),
221-
Alias(self.axis, name="axis"),
222-
Alias(self.xaxis, name="xaxis", prefix="px" if self.xaxis2 else "x"),
223-
Alias(self.yaxis, name="yaxis", prefix="py" if self.yaxis2 else "y"),
231+
Alias(self.axis, name="axis", prefix="p" if has_secondary_xy_axis else ""),
232+
Alias(self.axis2, name="axis2", prefix="s"),
233+
Alias(
234+
self.xaxis,
235+
name="xaxis",
236+
prefix="px" if self.xaxis2 or self.axis2 else "x",
237+
),
238+
Alias(
239+
self.yaxis,
240+
name="yaxis",
241+
prefix="py" if self.yaxis2 or self.axis2 else "y",
242+
),
224243
Alias(self.zaxis, name="zaxis", prefix="pz" if self.zaxis2 else "z"),
225244
Alias(self.xaxis2, name="xaxis2", prefix="sx"),
226245
Alias(self.yaxis2, name="yaxis2", prefix="sy"),

pygmt/tests/test_config.py

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,9 @@ def test_config_format_time_map():
108108
fig.basemap(
109109
region=["2020-1-24T", "2020-1-27T", 0, 1],
110110
projection="X6c/1c",
111-
frame=["pa1K", "sa1K", "NWse"],
111+
frame=Frame(axes="NWse", axis=Axis(annot="1K"), axis2=Axis(annot="1K")),
112112
)
113-
fig.basemap(frame=["pa1K", "sa1K", "nwSE"])
113+
fig.basemap(frame=Frame(axes="nwSE", axis=Axis(annot="1K"), axis2=Axis(annot="1K")))
114114
return fig
115115

116116

@@ -125,9 +125,9 @@ def test_config_map_annot_offset():
125125
fig.basemap(
126126
region=["2020-1-24T", "2020-1-27T", 0, 1],
127127
projection="X6c/1c",
128-
frame=["pa1d", "sa1d", "NWse"],
128+
frame=Frame(axes="NWse", axis=Axis(annot="1d"), axis2=Axis(annot="1d")),
129129
)
130-
fig.basemap(frame=["pa1d", "sa1d", "nwSE"])
130+
fig.basemap(frame=Frame(axes="nwSE", axis=Axis(annot="1d"), axis2=Axis(annot="1d")))
131131
return fig
132132

133133

@@ -142,11 +142,22 @@ def test_config_map_grid_cross_size():
142142
fig.basemap(
143143
region=["2020-1-24T21:00", "2020-1-25T00:00", 0, 1],
144144
projection="X6c/2c",
145-
frame=["pa1Hg", "sa45mg45m", "NWse"],
145+
frame=Frame(
146+
axes="NWse",
147+
axis=Axis(annot="1H", grid=True),
148+
axis2=Axis(annot="45m", grid="45m"),
149+
),
146150
verbose="error",
147151
)
148152
fig.shift_origin(yshift=-3)
149-
fig.basemap(frame=["pa1Hg", "sa45mg45m", "nwSE"], verbose="error")
153+
fig.basemap(
154+
frame=Frame(
155+
axes="nwSE",
156+
axis=Axis(annot="1H", grid=True),
157+
axis2=Axis(annot="45m", grid="45m"),
158+
),
159+
verbose="error",
160+
)
150161
return fig
151162

152163

@@ -161,11 +172,22 @@ def test_config_map_grid_pen():
161172
fig.basemap(
162173
region=["2020-1-24T21:00", "2020-1-25T00:00", 0, 1],
163174
projection="X6c/2c",
164-
frame=["pa1Hg", "sa45mg45m", "NWse"],
175+
frame=Frame(
176+
axes="NWse",
177+
axis=Axis(annot="1H", grid=True),
178+
axis2=Axis(annot="45m", grid="45m"),
179+
),
165180
verbose="error",
166181
)
167182
fig.shift_origin(yshift=-3)
168-
fig.basemap(frame=["pa1Hg", "sa45mg45m", "nwSE"], verbose="error")
183+
fig.basemap(
184+
frame=Frame(
185+
axes="nwSE",
186+
axis=Axis(annot="1H", grid=True),
187+
axis2=Axis(annot="45m", grid="45m"),
188+
),
189+
verbose="error",
190+
)
169191
return fig
170192

171193

@@ -180,11 +202,22 @@ def test_config_map_tick_length():
180202
fig.basemap(
181203
region=["2020-1-24T21:00", "2020-1-25T00:00", 0, 1],
182204
projection="X6c/2c",
183-
frame=["pa1Hg", "sa45mg45m", "NWse"],
205+
frame=Frame(
206+
axes="NWse",
207+
axis=Axis(annot="1H", grid=True),
208+
axis2=Axis(annot="45m", grid="45m"),
209+
),
184210
verbose="error",
185211
)
186212
fig.shift_origin(yshift=-3)
187-
fig.basemap(frame=["pa1Hg", "sa45mg45m", "nwSE"], verbose="error")
213+
fig.basemap(
214+
frame=Frame(
215+
axes="nwSE",
216+
axis=Axis(annot="1H", grid=True),
217+
axis2=Axis(annot="45m", grid="45m"),
218+
),
219+
verbose="error",
220+
)
188221
return fig
189222

190223

@@ -199,11 +232,22 @@ def test_config_map_tick_pen():
199232
fig.basemap(
200233
region=["2020-1-24T21:00", "2020-1-25T00:00", 0, 1],
201234
projection="X6c/2c",
202-
frame=["pa1Hg", "sa45mg45m", "NWse"],
235+
frame=Frame(
236+
axes="NWse",
237+
axis=Axis(annot="1H", grid=True),
238+
axis2=Axis(annot="45m", grid="45m"),
239+
),
203240
verbose="error",
204241
)
205242
fig.shift_origin(yshift=-3)
206-
fig.basemap(frame=["pa1Hg", "sa45mg45m", "nwSE"], verbose="error")
243+
fig.basemap(
244+
frame=Frame(
245+
axes="nwSE",
246+
axis=Axis(annot="1H", grid=True),
247+
axis2=Axis(annot="45m", grid="45m"),
248+
),
249+
verbose="error",
250+
)
207251
return fig
208252

209253

pygmt/tests/test_params_frame.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Test the Frame and Axis classes.
33
"""
44

5+
import pytest
6+
from pygmt.exceptions import GMTParameterError
57
from pygmt.params import Axis, Frame
68

79

@@ -41,6 +43,14 @@ def test_params_frame_axis():
4143
)
4244
assert list(frame) == ["WSEN+tMy Title", "afg+lLABEL"]
4345

46+
frame = Frame(
47+
axes="WSEN",
48+
title="My Title",
49+
axis=Axis(annot=30, tick=15, grid=10),
50+
axis2=Axis(annot=60, tick=30, grid=20),
51+
)
52+
assert list(frame) == ["WSEN+tMy Title", "pa30f15g10", "sa60f30g20"]
53+
4454

4555
def test_params_frame_separate_axes():
4656
"""
@@ -96,3 +106,20 @@ def test_params_frame_separate_axis_secondary():
96106
yaxis=Axis(annot=True, tick=True, grid=True, label="Y-LABEL"),
97107
)
98108
assert list(frame) == ["WSEN+tMy Title", "xafg+lX-LABEL", "yafg+lY-LABEL"]
109+
110+
111+
def test_params_frame_invalid_axis_combinations():
112+
"""
113+
Test that invalid combinations of uniform and individual axis settings fail.
114+
"""
115+
with pytest.raises(GMTParameterError, match="Either 'axis' or"):
116+
Frame(axis=Axis(annot=1), xaxis=Axis(annot=2))
117+
118+
with pytest.raises(GMTParameterError, match="Either 'axis' or"):
119+
Frame(axis=Axis(annot=1), xaxis2=Axis(annot=2))
120+
121+
with pytest.raises(GMTParameterError, match="Either 'axis2' or"):
122+
Frame(axis2=Axis(annot=1), xaxis=Axis(annot=2))
123+
124+
with pytest.raises(GMTParameterError, match="Either 'axis2' or"):
125+
Frame(axis2=Axis(annot=1), yaxis2=Axis(annot=2))

0 commit comments

Comments
 (0)