Skip to content

Commit 753be82

Browse files
committed
Add Figure.directional_rose for adding directional rose on maps
1 parent 2200457 commit 753be82

File tree

4 files changed

+148
-0
lines changed

4 files changed

+148
-0
lines changed

doc/api/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Plotting map elements
2727
Figure.basemap
2828
Figure.coast
2929
Figure.colorbar
30+
Figure.directional_rose
3031
Figure.hlines
3132
Figure.inset
3233
Figure.legend

pygmt/figure.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ def _repr_html_(self) -> str:
435435
coast,
436436
colorbar,
437437
contour,
438+
directional_rose,
438439
grdcontour,
439440
grdimage,
440441
grdview,

pygmt/src/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from pygmt.src.config import config
1111
from pygmt.src.contour import contour
1212
from pygmt.src.dimfilter import dimfilter
13+
from pygmt.src.directional_rose import directional_rose
1314
from pygmt.src.filter1d import filter1d
1415
from pygmt.src.grd2cpt import grd2cpt
1516
from pygmt.src.grd2xyz import grd2xyz

pygmt/src/directional_rose.py

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
"""
2+
directional_rose - Add a map directional rose.
3+
"""
4+
5+
from collections.abc import Sequence
6+
from typing import Literal
7+
8+
from pygmt._typing import AnchorCode
9+
from pygmt.alias import Alias, AliasSystem
10+
from pygmt.clib import Session
11+
from pygmt.exceptions import GMTInvalidInput
12+
from pygmt.helpers import build_arg_list
13+
from pygmt.params import Box
14+
15+
16+
def directional_rose( # noqa: PLR0913
17+
self,
18+
position: Sequence[float | str] | AnchorCode | None = None,
19+
position_type: Literal[
20+
"mapcoords", "boxcoords", "plotcoords", "inside", "outside"
21+
] = "plotcoords",
22+
anchor: AnchorCode | None = None,
23+
anchor_offset: Sequence[float | str] | None = None,
24+
width: float | str | None = None,
25+
label: Sequence[str] | bool = False,
26+
fancy: Literal[1, 2, 3] | bool = False,
27+
box: Box | bool = False,
28+
perspective: str | bool = False,
29+
verbose: Literal["quiet", "error", "warning", "timing", "info", "compat", "debug"]
30+
| bool = False,
31+
transparency: float | None = None,
32+
):
33+
r"""
34+
Add a directional rose on the map.
35+
36+
The directional rose is plotted at the location defined by the reference point
37+
(specified by the **position** and *position_type** parameters) and anchor point
38+
(specified by the **anchor** and **anchor_offset** parameters). Refer to
39+
:doc:`/techref/reference_anchor_points` for details about the positioning.
40+
41+
Parameters
42+
----------
43+
position/position_type
44+
Specify the reference point on the map for the directional rose. The reference
45+
point can be specified in five different ways, which is selected by the
46+
**position_type** parameter. The actual reference point is then given by the
47+
coordinates or code specified by the **position** parameter.
48+
49+
The **position_type** parameter can be one of the following:
50+
51+
- ``"mapcoords"``: **position** is given as (*longitude*, *latitude*) in map
52+
coordinates.
53+
- ``"boxcoords"``: **position** is given as (*nx*, *ny*) in normalized
54+
coordinates, i.e., fractional coordinates between 0 and 1 in both the x and y
55+
directions. For example, (0, 0) is the lower-left corner and (1, 1) is the
56+
upper-right corner of the plot bounding box.
57+
- ``"plotcoords"``: **position** is given as (x, y) in plot coordinates, i.e.,
58+
the distances in inches, centimeters, or points from the lower left plot
59+
origin.
60+
- ``"inside"`` or ``"outside"``: **position** is one of the nine
61+
:doc:`2-character justification codes </techref/justification_codes>`, meaning
62+
placing the reference point at specific locations, either inside or outside
63+
the plot bounding box.
64+
anchor
65+
Anchor point of the directional rose, specified by one of the
66+
:doc:`2-character justification codes </techref/justification_codes>`.
67+
The default value depends on the **position_type** parameter.
68+
69+
- ``position_type="inside"``: **anchor** defaults to the same as **position**.
70+
- ``position_type="outside"``: **anchor** defaults to the mirror opposite of
71+
**position**.
72+
- Otherwise, **anchor** defaults to ``"MC"`` (middle center).
73+
anchor_offset
74+
*offset* or (*offset_x*, *offset_y*).
75+
Offset the anchor point by *offset_x* and *offset_y*. If a single value *offset*
76+
is given, *offset_y* = *offset_x* = *offset*.
77+
width
78+
Width of the rose in plot coordinates (append **i** (inch), **cm**
79+
(centimeters), or **p** (points)), or append % for a size in percentage of map
80+
width [Default is 10 %].
81+
label
82+
A sequence of four strings to label the cardinal points W,E,S,N. Use an empty
83+
string to skip a specific label. If set to ``True``, use the default labels
84+
``["W", "E", "S", "N"]``.
85+
fancy
86+
Get a fancy rose. The fanciness level can be set to 1, 2, or 3:
87+
88+
- Level 1 draws the two principal E-W, N-S orientations
89+
- Level 2 adds the two intermediate NW-SE and NE-SW orientations
90+
- Level 3 adds the four minor orientations WNW-ESE, NNW-SSE, NNE-SSW, and
91+
ENE-WSW
92+
93+
If set to ``True``, defaults to level 1.
94+
box
95+
Draw a background box behind the directional rose. If set to ``True``, a simple
96+
rectangular box is drawn using :gmt-term:`MAP_FRAME_PEN`. To customize the box
97+
appearance, pass a :class:`pygmt.params.Box` object to control style, fill, pen,
98+
and other box properties.
99+
{perspective}
100+
{verbose}
101+
{transparency}
102+
103+
Examples
104+
--------
105+
>>> import pygmt
106+
>>> fig = pygmt.Figure()
107+
>>> fig.basemap(region=[0, 80, -30, 30], projection="M10c", frame=True)
108+
>>> fig.directional_rose(position=(10, 10), position_type="mapcoords")
109+
>>> fig.show()
110+
"""
111+
self._activate_figure()
112+
113+
if position is None:
114+
msg = "Parameter 'position' is required."
115+
raise GMTInvalidInput(msg)
116+
117+
aliasdict = AliasSystem(
118+
F=Alias(box, name="box"),
119+
Td=[
120+
Alias(
121+
position_type,
122+
name="position_type",
123+
mapping={
124+
"mapcoords": "g",
125+
"boxcoords": "n",
126+
"plotcoords": "x",
127+
"inside": "j",
128+
"outside": "J",
129+
},
130+
),
131+
Alias(position, name="position", sep="/", size=2),
132+
Alias(anchor, name="anchor", prefix="+j"),
133+
Alias(anchor_offset, name="anchor_offset", prefix="+o", sep="/", size=2),
134+
Alias(fancy, name="fancy", prefix="+f"), # +F is not supported yet.
135+
Alias(label, name="label", prefix="+l", sep=",", size=4),
136+
Alias(width, name="width", prefix="+w"),
137+
],
138+
p=Alias(perspective, name="perspective"),
139+
).add_common(
140+
V=verbose,
141+
t=transparency,
142+
)
143+
144+
with Session() as lib:
145+
lib.call_module(module="basemap", args=build_arg_list(aliasdict))

0 commit comments

Comments
 (0)