Skip to content

Commit a525760

Browse files
committed
Add Figure.magnetic_rose to plot a magnetic rose on map
1 parent b4a94d7 commit a525760

File tree

6 files changed

+171
-4
lines changed

6 files changed

+171
-4
lines changed

doc/api/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Plotting map elements
3131
Figure.inset
3232
Figure.legend
3333
Figure.logo
34+
Figure.magnetic_rose
3435
Figure.solar
3536
Figure.text
3637
Figure.timestamp

pygmt/figure.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ def _repr_html_(self) -> str:
422422
inset,
423423
legend,
424424
logo,
425+
magnetic_rose,
425426
meca,
426427
plot,
427428
plot3d,

pygmt/src/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from pygmt.src.inset import inset
3636
from pygmt.src.legend import legend
3737
from pygmt.src.logo import logo
38+
from pygmt.src.magnetic_rose import magnetic_rose
3839
from pygmt.src.makecpt import makecpt
3940
from pygmt.src.meca import meca
4041
from pygmt.src.nearneighbor import nearneighbor

pygmt/src/magnetic_rose.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
"""
2+
magnetic_rose - Add a map magnetic rose.
3+
"""
4+
5+
from collections.abc import Sequence
6+
from typing import Literal
7+
8+
from pygmt.alias import Alias, AliasSystem
9+
from pygmt.clib import Session
10+
from pygmt.exceptions import GMTInvalidInput
11+
from pygmt.helpers import build_arg_list
12+
from pygmt.params import Box, Position
13+
14+
15+
def magnetic_rose( # noqa: PLR0913
16+
self,
17+
position: Position | None = None,
18+
width: float | str | None = None,
19+
labels: Sequence[str] | bool = False,
20+
outer_pen: str | bool = False,
21+
inner_pen: str | bool = False,
22+
declination: float | None = None,
23+
declination_label: str | None = None,
24+
intervals: Sequence[float] | None = None,
25+
box: Box | bool = False,
26+
perspective: str | bool = False,
27+
verbose: Literal["quiet", "error", "warning", "timing", "info", "compat", "debug"]
28+
| bool = False,
29+
transparency: float | None = None,
30+
):
31+
"""
32+
Add a magnetic rose to the map.
33+
34+
Parameters
35+
----------
36+
position
37+
Specify the location of the magnetic rose on a map. See
38+
:class:`pygmt.params.Position` for details.
39+
width
40+
Width of the rose in plot coordinates (append **i** (inch), **cm**
41+
(centimeters), or **p** (points)), or append % for a size in percentage of map
42+
width [Default is 15 %].
43+
labels
44+
A sequence of four strings to label the cardinal points W,E,S,N. Use an empty
45+
string to skip a specific label. If the north label is ``"*"``, then a north
46+
star is plotted instead of the north label. If set to ``True``, use the default
47+
labels ``["W", "E", "S", "N"]``.
48+
outer_pen
49+
Draw the outer circle of the magnetic rose, using the given pen attributes.
50+
inner_pen
51+
Draw the inner circle of the magnetic rose, using the given pen attributes.
52+
declination
53+
Magnetic declination in degrees. By default, only a geographic north is plotted.
54+
With this parameter set, a magnetic north is also plotted. A magnetic compass
55+
needle is drawn inside the rose to indicate the direction to magnetic north.
56+
declination_label
57+
Label for the magnetic compass needle. Default is to format a label based on
58+
**declination**. To bypass the label, set to ``"-"``.
59+
intervals
60+
Specify the annotation and tick intervals for the geographic and magnetic
61+
directions. It can be a seqeunce of three or six values. If three values are
62+
given, they are used for both geographic and magnetic directions. If six values
63+
are given, the first three are used for geographic directions and the last three
64+
for magnetic directions. Default is ``(30, 5, 1)``. **Note**: If
65+
:gmt-term:`MAP_EMBELLISHMENT_MODE` is ``"auto"`` and the compass size is smaller
66+
than 2.5 cm then the interval defaults are reset to ``(90,30, 3, 45, 15, 3)``.
67+
box
68+
Draw a background box behind the magnetic rose. If set to ``True``, a simple
69+
rectangular box is drawn using :gmt-term:`MAP_FRAME_PEN`. To customize the box
70+
appearance, pass a :class:`pygmt.params.Box` object to control style, fill, pen,
71+
and other box properties.
72+
$perspective
73+
$verbose
74+
$transparency
75+
76+
Examples
77+
--------
78+
>>> import pygmt
79+
>>> from pygmt.params import Position
80+
>>> fig = pygmt.Figure()
81+
>>> fig.basemap(region=[-10, 10, -10, 10], projection="M15c", frame=True)
82+
>>> fig.magnetic_rose(
83+
... position=Position((-5, -5), cstype="mapcoords"),
84+
... width="4c",
85+
... labels=["W", "E", "S", "*"],
86+
... intervals=(45, 15, 3, 60, 20, 4),
87+
... outer_pen="1p,red",
88+
... inner_pen="1p,blue",
89+
... declination=11.5,
90+
... declination_label="11.5°E",
91+
... )
92+
>>> fig.show()
93+
"""
94+
self._activate_figure()
95+
96+
if declination_label is not None and declination is None:
97+
msg = "Parameter 'declination' must be set when 'declination_label' is set."
98+
raise GMTInvalidInput(msg)
99+
100+
aliasdict = AliasSystem(
101+
F=Alias(box, name="box"),
102+
Tm=[
103+
Alias(position, name="position"),
104+
Alias(width, name="width", prefix="+w"),
105+
Alias(labels, name="labels", prefix="+l", sep=",", size=4),
106+
Alias(outer_pen, name="outer_pen", prefix="+p"),
107+
Alias(inner_pen, name="inner_pen", prefix="+i"),
108+
Alias(declination, name="declination", prefix="+d"),
109+
Alias(declination_label, name="declination_label", prefix="/"),
110+
Alias(intervals, name="intervals", prefix="+t", sep="/", size=(3, 6)),
111+
],
112+
).add_common(
113+
V=verbose,
114+
p=perspective,
115+
t=transparency,
116+
)
117+
118+
with Session() as lib:
119+
lib.call_module(module="basemap", args=build_arg_list(aliasdict))

pygmt/tests/test_config.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,21 @@ def test_config_font_one():
4747
"""
4848
fig = Figure()
4949
with config(FONT="8p,red"):
50-
fig.basemap(region=[0, 9, 0, 9], projection="C3/3/9c", compass="jTL+w3c+d4.5+l")
51-
fig.basemap(compass="jBR+w3.5c+d-4.5+l")
50+
fig.basemap(region=[0, 9, 0, 9], projection="C3/3/9c", frame="+n")
51+
fig.magnetic_rose(
52+
position_type="inside",
53+
position="TL",
54+
width="3c",
55+
declination=4.5,
56+
labels=True,
57+
)
58+
fig.magnetic_rose(
59+
position_type="inside",
60+
position="BR",
61+
width="3.5c",
62+
declination=-4.5,
63+
labels=True,
64+
)
5265
return fig
5366

5467

@@ -60,8 +73,21 @@ def test_config_font_annot():
6073
"""
6174
fig = Figure()
6275
with config(FONT_ANNOT="6p,red"):
63-
fig.basemap(region=[0, 9, 0, 9], projection="C3/3/9c", compass="jTL+w3c+d4.5")
64-
fig.basemap(compass="jBR+w3.5c+d-4.5")
76+
fig.basemap(region=[0, 9, 0, 9], projection="C3/3/9c", frame="+n")
77+
fig.magnetic_rose(
78+
position_type="inside",
79+
position="TL",
80+
width="3c",
81+
declination=4.5,
82+
labels=True,
83+
)
84+
fig.magnetic_rose(
85+
position_type="inside",
86+
position="BR",
87+
width="3.5c",
88+
declination=-4.5,
89+
labels=True,
90+
)
6591
return fig
6692

6793

pygmt/tests/test_magnetic_rose.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""
2+
Test Figure.magnetic_rose.
3+
"""
4+
5+
import pytest
6+
from pygmt import Figure
7+
8+
9+
@pytest.mark.mpl_image_compare(filename="test_basemap_compass.png")
10+
def test_magnetic_rose():
11+
"""
12+
Create a map with a compass. Modified from the test_basemap_compass test.
13+
"""
14+
fig = Figure()
15+
fig.basemap(region=[127.5, 128.5, 26, 27], projection="H15c", frame=True)
16+
fig.magnetic_rose(
17+
position_type="inside", position="MC", width="5c", declination=11.5
18+
)
19+
return fig

0 commit comments

Comments
 (0)