From fb64cbf18f6f8cf870c9cd8a0892b3874e3b1664 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Sat, 26 Jul 2025 15:14:02 +0800 Subject: [PATCH 1/3] Figure.logo: Refactor using the AliasSystem class --- pygmt/src/logo.py | 48 +++++++++++++++++++++++++++++++++++++--- pygmt/tests/test_logo.py | 8 ++++++- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/pygmt/src/logo.py b/pygmt/src/logo.py index d65bf3bc775..b302d806883 100644 --- a/pygmt/src/logo.py +++ b/pygmt/src/logo.py @@ -2,7 +2,11 @@ logo - Plot the GMT logo. """ +from typing import Literal + +from pygmt.alias import Alias, AliasSystem from pygmt.clib import Session +from pygmt.exceptions import GMTInvalidInput from pygmt.helpers import build_arg_list, fmt_docstring, kwargs_to_strings, use_alias @@ -10,7 +14,6 @@ @use_alias( R="region", J="projection", - D="position", F="box", S="style", V="verbose", @@ -18,7 +21,18 @@ t="transparency", ) @kwargs_to_strings(R="sequence", c="sequence_comma", p="sequence") -def logo(self, **kwargs): +def logo( + self, + position_type: Literal[ + "user", "justify", "mirror", "normalize", "plot", None + ] = None, + position=None, + height=None, + width=None, + justify=None, + offset=None, + **kwargs, +): r""" Plot the GMT logo. @@ -39,6 +53,9 @@ def logo(self, **kwargs): [**g**\|\ **j**\|\ **J**\|\ **n**\|\ **x**]\ *refpoint*\ **+w**\ *width*\ [**+j**\ *justify*]\ [**+o**\ *dx*\ [/*dy*]]. Set reference point on the map for the image. + positon_type + width/height + Width or height of the GMT logo. box : bool or str If set to ``True``, draw a rectangular border around the GMT logo. @@ -55,5 +72,30 @@ def logo(self, **kwargs): {transparency} """ self._activate_figure() + if width is not None and height is not None: + msg = "Cannot specify both width and height." + raise GMTInvalidInput(msg) + + aliasdict = AliasSystem( + D=[ + Alias( + position_type, + name="position_type", + mapping={ + "user": "g", + "justify": "j", + "mirror": "J", + "normalize": "n", + "plot": "x", + }, + ), + Alias(position, name="position", separator="/"), + Alias(height, name="height", prefix="+h"), + Alias(width, name="width", prefix="+w"), + Alias(justify, name="justify", prefix="+j"), + Alias(offset, name="offset", prefix="+o", separator="/", size=2), + ] + ).merge(kwargs) + with Session() as lib: - lib.call_module(module="logo", args=build_arg_list(kwargs)) + lib.call_module(module="logo", args=build_arg_list(aliasdict)) diff --git a/pygmt/tests/test_logo.py b/pygmt/tests/test_logo.py index 62bddf4eb24..bcd803d8252 100644 --- a/pygmt/tests/test_logo.py +++ b/pygmt/tests/test_logo.py @@ -24,5 +24,11 @@ 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="justify", + position="TR", + offset=(0.25, 0.25), + width="7.5c", + box=True, + ) return fig From 1eb6587657ffc55ed33b48c0a677a91e3165819c Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Sun, 10 Aug 2025 20:12:00 +0800 Subject: [PATCH 2/3] Update position_type --- pygmt/src/logo.py | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/pygmt/src/logo.py b/pygmt/src/logo.py index b302d806883..f02cf44b8bc 100644 --- a/pygmt/src/logo.py +++ b/pygmt/src/logo.py @@ -2,8 +2,10 @@ logo - Plot the GMT logo. """ +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.exceptions import GMTInvalidInput @@ -23,14 +25,14 @@ @kwargs_to_strings(R="sequence", c="sequence_comma", p="sequence") def logo( self, + position: Sequence[str | float] | AnchorCode, position_type: Literal[ - "user", "justify", "mirror", "normalize", "plot", None - ] = None, - position=None, + "mapcoords", "inside", "outside", "boxcoords", "plotcoords" + ] = "mapcoords", height=None, width=None, justify=None, - offset=None, + anchor_offset=None, **kwargs, ): r""" @@ -49,11 +51,21 @@ def logo( ---------- {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. - positon_type + position/position_type + Location of the GMT logo. The actual meaning of this parameter depends on the + ``position_type`` parameter. + - ``position_type="mapcoords"``: *position* is given as (x, y) in user + coordinates. + - ``position_type="boxcoords"``: *position* is given as (nx, ny) in normalized + coordinates, where (0, 0) is the lower-left corner and (1, 1) is the + upper-right corner of the map. + - ``position_type="plotcoords"``: *position* is given as (x, y) in plot + coordinates. + - ``position_type="inside"``: *position* is given as a two-character + justification code, meaning the anchor point of the rose is inside the map + bounding box. + - ``position_type="outside"``: *position* is given as a two-character + justification code, but the rose is outside the map bounding box. width/height Width or height of the GMT logo. box : bool or str @@ -82,18 +94,18 @@ def logo( position_type, name="position_type", mapping={ - "user": "g", - "justify": "j", - "mirror": "J", - "normalize": "n", - "plot": "x", + "mapcoords": "g", + "inside": "j", + "outside": "J", + "boxcoords": "n", + "plotcoords": "x", }, ), - Alias(position, name="position", separator="/"), + Alias(position, name="position", sep="/"), Alias(height, name="height", prefix="+h"), Alias(width, name="width", prefix="+w"), Alias(justify, name="justify", prefix="+j"), - Alias(offset, name="offset", prefix="+o", separator="/", size=2), + Alias(anchor_offset, name="anchor_offset", prefix="+o", sep="/", size=2), ] ).merge(kwargs) From 6fa17ac3cbe843d75268ce8464781adbc835d231 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Sun, 10 Aug 2025 20:39:36 +0800 Subject: [PATCH 3/3] Updates --- pygmt/src/logo.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pygmt/src/logo.py b/pygmt/src/logo.py index f02cf44b8bc..230a23555a8 100644 --- a/pygmt/src/logo.py +++ b/pygmt/src/logo.py @@ -27,7 +27,7 @@ def logo( self, position: Sequence[str | float] | AnchorCode, position_type: Literal[ - "mapcoords", "inside", "outside", "boxcoords", "plotcoords" + "mapcoords", "boxcoords", "plotcoords", "inside", "outside" ] = "mapcoords", height=None, width=None, @@ -58,14 +58,15 @@ def logo( coordinates. - ``position_type="boxcoords"``: *position* is given as (nx, ny) in normalized coordinates, where (0, 0) is the lower-left corner and (1, 1) is the - upper-right corner of the map. + upper-right corner of the plot. - ``position_type="plotcoords"``: *position* is given as (x, y) in plot - coordinates. + coordinates, i.e., the distances in inches, centimeters, or points from the + lower left plot origin. - ``position_type="inside"``: *position* is given as a two-character - justification code, meaning the anchor point of the rose is inside the map + justification code, meaning the anchor point of the rose is inside the plot bounding box. - ``position_type="outside"``: *position* is given as a two-character - justification code, but the rose is outside the map bounding box. + justification code, but the rose is outside the plot bounding box. width/height Width or height of the GMT logo. box : bool or str @@ -95,10 +96,10 @@ def logo( name="position_type", mapping={ "mapcoords": "g", - "inside": "j", - "outside": "J", "boxcoords": "n", "plotcoords": "x", + "inside": "j", + "outside": "J", }, ), Alias(position, name="position", sep="/"),