Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
fb64cbf
Figure.logo: Refactor using the AliasSystem class
seisman Jul 26, 2025
1eb6587
Update position_type
seisman Aug 10, 2025
6fa17ac
Updates
seisman Aug 10, 2025
cb40511
Merge branch 'main' into refactor/logo
seisman Sep 3, 2025
6edab47
Merge branch 'main' into refactor/logo
seisman Sep 4, 2025
cd1165f
fix
seisman Sep 9, 2025
dab0bdb
Merge branch 'main' into refactor/logo
seisman Sep 9, 2025
494afc5
Merge branch 'main' into refactor/logo
seisman Sep 9, 2025
b17ecfe
Remove D from use_alias
seisman Sep 9, 2025
6ec9c66
Fix typos
seisman Sep 9, 2025
9307150
Merge branch 'main' into refactor/logo
seisman Sep 11, 2025
9a0575d
Improve docstrings
seisman Sep 11, 2025
d19959e
Improve docstrings
seisman Sep 12, 2025
df0aba0
Merge branch 'main' into refactor/logo
seisman Sep 12, 2025
f8f418b
Backward compatibility
seisman Sep 14, 2025
df50342
Improve Figure.logo tests
seisman Sep 15, 2025
6bd1dc2
Merge branch 'main' into refactor/logo
seisman Sep 15, 2025
8699d9a
Add a test for mixed syntax
seisman Sep 15, 2025
2f09ee9
Merge branch 'main' into refactor/logo
seisman Sep 18, 2025
da38bd1
Merge branch 'main' into refactor/logo
seisman Oct 15, 2025
5e02d22
Update docstrings
seisman Oct 15, 2025
7568264
Fix formatting
seisman Oct 15, 2025
43d08a0
Fix docstrings
seisman Oct 15, 2025
91b6b25
Fix long docstrings
seisman Oct 15, 2025
4f61e2e
Merge branch 'main' into refactor/logo
seisman Oct 16, 2025
6d3dc9b
Fix docstrings
seisman Oct 16, 2025
62e6274
Fix docstrings
seisman Oct 16, 2025
e3d14d5
Fix docstrings
seisman Oct 16, 2025
e73dc9e
Fix comments
seisman Oct 16, 2025
e77993b
Fix docstrings
seisman Oct 16, 2025
66f9c4d
Fix docstrings
seisman Oct 16, 2025
a33bf5d
Merge branch 'main' into refactor/logo
seisman Oct 18, 2025
fb95478
Fix offset to anchor_offset in the Figure.inset doctest
seisman Oct 18, 2025
9ca90fb
Merge remote-tracking branch 'origin/refactor/logo' into refactor/logo
seisman Oct 18, 2025
51fe976
Improve the handling of deprecation position parameter
seisman Oct 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions examples/gallery/embellishments/gmt_logo.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,5 @@

# Add the GMT logo in the Top Right (TR) corner of the current plot, scaled up to be 3
# centimeters wide and offset by 0.3 cm in x-direction and 0.6 cm in y-direction.
fig.logo(position="jTR+o0.3c/0.6c+w3c")

fig.logo(position="TR", position_type="inside", anchor_offset=(0.3, 0.6), width="3c")
fig.show()
5 changes: 2 additions & 3 deletions pygmt/src/inset.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,8 @@ def inset(
... dcw="MG+gred",
... )
...
>>> # Map elements outside the "with" statement are plotted in the main
>>> # figure
>>> fig.logo(position="jBR+o0.2c+w3c")
>>> # Map elements outside the "with" statement are plotted in the main figure
>>> fig.logo(position="BR", position_type="inside", anchor_offset=0.2, width="3c")
>>> fig.show()
"""
self._activate_figure()
Expand Down
134 changes: 120 additions & 14 deletions pygmt/src/logo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,26 @@
from collections.abc import Sequence
from typing import Literal

from pygmt._typing import AnchorCode
from pygmt.alias import Alias, AliasSystem
from pygmt.clib import Session
from pygmt.helpers import build_arg_list, fmt_docstring, kwargs_to_strings, use_alias
from pygmt.exceptions import GMTInvalidInput
from pygmt.helpers import build_arg_list, fmt_docstring, kwargs_to_strings
from pygmt.params import Box


@fmt_docstring
@use_alias(D="position")
@kwargs_to_strings(p="sequence")
def logo(
def logo( # noqa: PLR0913
self,
position: Sequence[str | float] | AnchorCode | None = None,
position_type: Literal[
"mapcoords", "boxcoords", "plotcoords", "inside", "outside"
] = "plotcoords",
anchor: AnchorCode | None = None,
anchor_offset: Sequence[float | str] | None = None,
height: float | str | None = None,
width: float | str | None = None,
projection: str | None = None,
region: Sequence[float | str] | str | None = None,
style: Literal["standard", "url", "no_label"] = "standard",
Expand All @@ -29,14 +38,29 @@ def logo(
r"""
Plot the GMT logo.
By default, the GMT logo is 2 inches wide and 1 inch high and
will be positioned relative to the current plot origin.
Use various options to change this and to place a transparent or
opaque rectangular map panel behind the GMT logo.
.. figure:: https://docs.generic-mapping-tools.org/6.6/_images/GMT_coverlogo.png
:alt: GMT logo
:align: center
:width: 300px
By default, the GMT logo is 2 inches wide and 1 inch high and will be positioned
relative to the current plot origin. The position can be changed by specifying the
reference point (via ``position_type`` and ``position``) and anchor point (via
``anchor`` and ``anchor_offset``). Refer to :doc:`/techref/reference_anchor_points`
for details about the positioning.
Full GMT docs at :gmt-docs:`gmtlogo.html`.
{aliases}
**Aliases:**
.. hlist::
:columns: 1
- D = position/position_type, **+j**: anchor, **+o**: anchor_offset,
**+w**: width, **+h**: height
.. hlist::
:columns: 3
- F = box
- J = projection
- R = region
Expand All @@ -47,17 +71,53 @@ def logo(
Parameters
----------
{projection}
{region}
position : str
[**g**\|\ **j**\|\ **J**\|\ **n**\|\ **x**]\ *refpoint*\
**+w**\ *width*\ [**+j**\ *justify*]\ [**+o**\ *dx*\ [/*dy*]].
Set reference point on the map for the image.
position
Specify the reference point on the plot for the GMT logo. The method of defining
the reference point is controlled by ``position_type``, and the exact location
is set by ``position``.
position_type
Specify the type of coordinates used to define the reference point. It can be
one of the following values:
- ``"mapcoords"``: ``position`` is specified as (*longitude*, *latitude*) in map
coordinates. Example: (120, -45) places the reference point at 120°E, 45°S.
- ``"boxcoords"``: ``position`` is specified as (*nx*, *ny*) in normalized
coordinates, i.e., fractional values between 0 and 1 along the x- and y-axes.
Example: (0, 0) corresponds to the lower-left corner, and (1, 1) to the
upper-right corner of the plot bounding box.
- ``"plotcoords"``: ``position`` is specified as (*x*, *y*) in plot coordinates,
i.e., distances from the lower-left plot origin given in inches, centimeters,
or points. Example: ("1c", "2c") places the reference point 1 cm to the right
and 2 cm above the plot origin.
- ``"inside"`` or ``"outside"``: ``position`` is one of the nine
:doc:`two-character justification codes </techref/justification_codes>`,
indicating a specific location relative to the plot bounding box. Example:
``"TL"`` places the reference point at the top-left corner, either inside or
outside the bounding box.
anchor
Specify the anchor point of the GMT logo, using one of the
:doc:`2-character justification codes </techref/justification_codes>`.
The default value depends on ``position_type``.
- ``position_type="inside"``: ``anchor`` defaults to the same as ``position``.
- ``position_type="outside"``: ``anchor`` defaults to the mirror opposite of
``position``.
- Otherwise, ``anchor`` defaults to ``"MC"`` (middle center).
anchor_offset
Specifies an offset for the anchor point as *offset* or
(*offset_x*, *offset_y*). If a single value *offset* is given, both *offset_x*
and *offset_y* are set to *offset*.
width
height
Width or height of the GMT logo. Since the aspect ratio is fixed, only one of
the two can be specified.
box
Draw a background box behind the logo. If set to ``True``, a simple rectangular
box is drawn using :gmt-term:`MAP_FRAME_PEN`. To customize the box appearance,
pass a :class:`pygmt.params.Box` object to control style, fill, pen, and other
box properties.
{projection}
{region}
style
Control what is written beneath the map portion of the logo.
Expand All @@ -70,7 +130,53 @@ def logo(
"""
self._activate_figure()

# Prior PyGMT v0.17.0, 'position' was aliased to the -D option. For backward
# compatibility, need to check if users pass a string with the GMT CLI syntax to
# 'position', i.e., a string starting with one of the codes "g", "n", "x", "j", "J",
# or contains modifiers with "+".
_is_deprecated_position = isinstance(position, str) and (
position.startswith(("g", "n", "x", "j", "J")) or "+" in position
)

if _is_deprecated_position and any(
v is not None for v in (anchor, anchor_offset, height, width)
):
msg = (
"Parameter 'position' is given with a raw GMT CLI syntax, and conflicts "
"with parameters 'anchor', 'anchor_offset', 'height', and 'width'. "
"Please refer to the documentation for the recommended usage."
)
raise GMTInvalidInput(msg)

# width and height are mutually exclusive.
if width is not None and height is not None:
msg = "Cannot specify both width and height."
raise GMTInvalidInput(msg)

_position_types = {
"mapcoords": "g",
"boxcoords": "n",
"plotcoords": "x",
"inside": "j",
"outside": "J",
}

aliasdict = AliasSystem(
D=Alias(position, name="position")
if _is_deprecated_position
else [
Alias(
position,
name="position",
sep="/",
size=2,
prefix=_position_types[position_type],
),
Alias(anchor, name="anchor", prefix="+j"),
Alias(anchor_offset, name="anchor_offset", prefix="+o", sep="/", size=2),
Alias(height, name="height", prefix="+h"),
Alias(width, name="width", prefix="+w"),
],
F=Alias(box, name="box"),
S=Alias(
style, name="style", mapping={"standard": "l", "url": "u", "no_label": "n"}
Expand Down
5 changes: 5 additions & 0 deletions pygmt/tests/baseline/test_logo_position_type.png.dvc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
outs:
- md5: 9b9d740219df9edb298dbc49e7ef1351
size: 232635
hash: md5
path: test_logo_position_type.png
61 changes: 60 additions & 1 deletion pygmt/tests/test_logo.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import pytest
from pygmt import Figure
from pygmt.exceptions import GMTInvalidInput


@pytest.mark.benchmark
Expand All @@ -24,5 +25,63 @@ def test_logo_on_a_map():
"""
fig = Figure()
fig.basemap(region=[-90, -70, 0, 20], projection="M15c", frame=True)
fig.logo(position="jTR+o0.25c/0.25c+w7.5c", box=True)
fig.logo(
position_type="inside",
position="TR",
anchor_offset=(0.25, 0.25),
width="7.5c",
box=True,
)
return fig


@pytest.mark.mpl_image_compare
def test_logo_position_type():
"""
Test that the new group of parameters works as expected.
"""
fig = Figure()
fig.basemap(region=[-90, -70, 0, 20], projection="M15c", frame=True)
fig.logo(position_type="inside", position="TL")
fig.logo(position_type="outside", position="TR")
fig.logo(position_type="mapcoords", position=(-80, 15))
fig.logo(position_type="boxcoords", position=(0, 0.5))
fig.logo(position_type="plotcoords", position=("2c", "0c"), width="5c")
fig.logo(position=("8c", "0c")) # Default position_type is "plotcoords".
return fig


@pytest.mark.mpl_image_compare(filename="test_logo_position_type.png")
def test_logo_position_deprecated_syntax():
"""
Test that passing the deprecated GMT CLI syntax string to 'position' works.
"""
fig = Figure()
fig.basemap(region=[-90, -70, 0, 20], projection="M15c", frame=True)
fig.logo(position="jTL")
fig.logo(position="JTR")
fig.logo(position="g-80/15")
fig.logo(position="n0/0.5")
fig.logo(position="x2c/0c+w5c")
fig.logo(position="8c/0c")
return fig


def test_logo_width_and_height():
"""
Test that an error is raised when both width and height are specified.
"""
fig = Figure()
with pytest.raises(GMTInvalidInput):
fig.logo(width="5c", height="5c")


def test_logo_position_mixed_syntax():
"""
Test that an error is raised when mixing new and deprecated syntax in 'position'.
"""
fig = Figure()
with pytest.raises(GMTInvalidInput):
fig.logo(position="jTL", width="5c")
with pytest.raises(GMTInvalidInput):
fig.logo(position="jTL", anchor="BR")
Loading