Skip to content

Commit 9e7a353

Browse files
committed
Allow text placement using position argument instead of x/y pairs
Equivalent to using `-F+c` in GMT.
1 parent 46e98d7 commit 9e7a353

File tree

3 files changed

+62
-6
lines changed

3 files changed

+62
-6
lines changed

pygmt/base_plotting.py

+38-6
Original file line numberDiff line numberDiff line change
@@ -826,20 +826,24 @@ def text(
826826
textfiles=None,
827827
x=None,
828828
y=None,
829+
position=None,
829830
text=None,
830831
angle=None,
831832
font=None,
832833
justify=None,
833834
**kwargs,
834835
):
835836
"""
836-
Plot or typeset text on maps
837+
Plot or typeset text strings of variable size, font type, and
838+
orientation.
837839
838840
Used to be pstext.
839841
840-
Takes in textfile(s) or (x,y,text) triples as input.
842+
Must provide at least one of the following combinations as input:
841843
842-
Must provide at least *textfiles* or *x*, *y*, and *text*.
844+
- *textfiles*
845+
- *x*, *y*, and *text*
846+
- *position* and *text*
843847
844848
Full option list at :gmt-docs:`text.html`
845849
@@ -853,6 +857,17 @@ def text(
853857
x/y : float or 1d arrays
854858
The x and y coordinates, or an array of x and y coordinates to plot
855859
the text
860+
position : str
861+
Sets reference point on the map for the text by using x,y
862+
coordinates extracted from *region* instead of providing them
863+
through *x* and *y*. Specify with a two letter (order independent)
864+
code, chosen from:
865+
866+
* Horizontal: L(eft), C(entre), R(ight)
867+
* Vertical: T(op), M(iddle), B(ottom)
868+
869+
For example, position="TL" plots the text at the Upper Left corner
870+
of the map.
856871
text : str or 1d array
857872
The text string, or an array of strings to plot on the figure
858873
angle: int, float, str or bool
@@ -899,17 +914,34 @@ def text(
899914
"""
900915
kwargs = self._preprocess(**kwargs)
901916

902-
kind = data_kind(textfiles, x, y, text)
917+
# Ensure inputs are either textfiles, x/y/text, or position/text
918+
if position is None:
919+
kind = data_kind(textfiles, x, y, text)
920+
elif position is not None:
921+
if x is not None or y is not None:
922+
raise GMTInvalidInput(
923+
"Provide either position only, or x/y pairs, not both"
924+
)
925+
kind = "vectors"
926+
903927
if kind == "vectors" and text is None:
904-
raise GMTInvalidInput("Must provide text with x and y.")
928+
raise GMTInvalidInput("Must provide text with x/y pairs or position")
905929
if kind == "file":
906930
for textfile in textfiles.split(" "): # ensure that textfile(s) exist
907931
if not os.path.exists(textfile):
908932
raise GMTInvalidInput(f"Cannot find the file: {textfile}")
909933

910-
if angle is not None or font is not None or justify is not None:
934+
# Build the `-F` argument in gmt text.
935+
if (
936+
position is not None
937+
or angle is not None
938+
or font is not None
939+
or justify is not None
940+
):
911941
if "F" not in kwargs.keys():
912942
kwargs.update({"F": ""})
943+
if position is not None and isinstance(position, str):
944+
kwargs["F"] += f"+c{position}"
913945
if angle is not None and isinstance(angle, (int, float, str)):
914946
kwargs["F"] += f"+a{str(angle)}"
915947
if font is not None and isinstance(font, str):
Loading

pygmt/tests/test_text.py

+24
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,30 @@ def test_text_nonexistent_filename():
9797
fig.text(region=[10, 70, -5, 10], textfiles=[POINTS_DATA, "notexist.txt"])
9898

9999

100+
@pytest.mark.mpl_image_compare
101+
def test_text_position_four_corners(region):
102+
"""
103+
Print text at four corners (top left/right, bottom left/right) of map.
104+
"""
105+
fig = Figure()
106+
for position in ("TL", "TR", "BL", "BR"):
107+
fig.text(
108+
region=region, projection="x1c", frame="a", position=position, text=position
109+
)
110+
return fig
111+
112+
113+
def test_text_xy_with_position_fails(region, projection):
114+
"""
115+
Run text by providing both x/y pairs and position arguments.
116+
"""
117+
fig = Figure()
118+
with pytest.raises(GMTInvalidInput):
119+
fig.text(
120+
region=region, projection="x1c", x=1.2, y=2.4, position="MC", text="text"
121+
)
122+
123+
100124
@pytest.mark.mpl_image_compare
101125
def test_text_angle_30(region, projection):
102126
"""

0 commit comments

Comments
 (0)