From f1d2ab06fccd9b32bda3cca8001e7e588360f071 Mon Sep 17 00:00:00 2001 From: Conor Bacon Date: Thu, 18 Jun 2020 14:58:17 +0100 Subject: [PATCH 1/7] Add tutorial for pygmt.Figure.text Add tutorial detailing how to add text annotations to PyGMT figures. Follows the style of the other tutorials available, showing how to use the currently available arguments in the binding to the underlying GMT program 'text'. Fixes #469 --- doc/index.rst | 1 + examples/tutorials/examples.txt | 1 + examples/tutorials/text.py | 128 ++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 examples/tutorials/examples.txt create mode 100644 examples/tutorials/text.py diff --git a/doc/index.rst b/doc/index.rst index b57c05e992d..4c3fd3d34e3 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -32,6 +32,7 @@ projections/index.rst tutorials/coastlines.rst tutorials/plot.rst + tutorials/text.rst .. toctree:: :maxdepth: 2 diff --git a/examples/tutorials/examples.txt b/examples/tutorials/examples.txt new file mode 100644 index 00000000000..a2a25e48ea5 --- /dev/null +++ b/examples/tutorials/examples.txt @@ -0,0 +1 @@ +114,0.5,BORNEO diff --git a/examples/tutorials/text.py b/examples/tutorials/text.py new file mode 100644 index 00000000000..61a431bfb34 --- /dev/null +++ b/examples/tutorials/text.py @@ -0,0 +1,128 @@ +""" +Plotting text +============= + +It is often useful to add annotations to a map plot. This is handled by +:meth:`pygmt.Figure.text`. +""" + +import pygmt + +######################################################################################## +# Basic map annotation +# -------------------- +# +# Text annotations can be added to a map using the :meth:`text` method of the +# :class:`pygmt.Figure`. +# +# Full details of the GMT6 command `text` can be found `here`_. +# The Python binding to this command is documented `here`_. +# +# Here we create a simple map and add an annotation using the ``text``, ``x``, +# and ``y`` arguments to specify the annotation text and position in the +# projection frame. ``text``, ``x``, and ``y`` accept `int`, `str`, or `float`. + +fig = pygmt.Figure() +with pygmt.config(MAP_FRAME_TYPE="plain"): + fig.basemap(region=[108, 120, -5, 8], projection="M20c", frame="a") +fig.coast(land="black", water="skyblue") + +# Plotting text annotations using single elements +fig.text(text="SOUTH CHINA SEA", x=112, y=6) + +# Plotting text annotations using lists of elements +fig.text(text=["CELEBES SEA", "JAVA SEA"], x=[119, 112], y=[3.25, -4.6]) + +fig.show() + +######################################################################################## +# Changing font style +# ------------------- +# The size, family/weight, and colour of an annotation can be specified using the ``font`` argument. +# +# A list of all recognised fonts can be found `here`_), +# including details of how to use non-default fonts. + +fig = pygmt.Figure() +with pygmt.config(MAP_FRAME_TYPE="plain"): + fig.basemap(region=[108, 120, -5, 8], projection="M20c", frame="a") +fig.coast(land="black", water="skyblue") + +# Customising the font style +fig.text(text="BORNEO", x="114.", y=0.5, font="22p,Helvetica-Bold,white") + +fig.show() + +######################################################################################## +# Plotting from a text file +# ------------------------- +# +# It is also possible to add annotations from a file containing `x`, `y`, and +# `text` fields. Here we give a complete example. + +fig = pygmt.Figure() +with pygmt.config(MAP_FRAME_TYPE="plain"): + fig.basemap(region=[108, 120, -5, 8], projection="M20c", frame="a") +fig.coast(land="black", water="skyblue") + +# Plot region names / sea names +fig.text(textfiles="examples.txt", font="22p,Helvetica-Bold,white") + +# Plot names of seas +fig.text(text=["CELEBES SEA", "JAVA SEA"], x=[119, 112], y=[3.25, -4.6]) +fig.text(text="SULU SEA", x=119.12, y=7.25, angle=-40) +fig.text(text="SOUTH CHINA SEA", x=112, y=6, angle=40) +fig.text(text="MAKASSAR STRAIT", x=118.4, y=-1, angle=65) +fig.show() + +######################################################################################## +# ``justify`` argument +# -------------------- +# +# ``justify`` is used to define the anchor point for the bounding box for text +# being added to a plot. The following code segment demonstrates the +# positioning of the anchor point relative to the text. +# +# The anchor is specified with a two letter (order independent) code, chosen +# from: +# * Horizontal anchor: L(eft), C(entre), R(ight) +# * Vertical anchor: T(op), M(iddle), B(ottom) + +fig = pygmt.Figure() +fig.basemap(region=[0, 4, 0, 4], projection="X10c", frame="WSen") +for i, y_justify in enumerate(["T", "M", "B"]): + y_pos = 3.5 - i*1.5 + fig.plot(x=[0., 4.], y=[y_pos, y_pos], W='3p,red@85') + for j, x_justify in enumerate(["L", "C", "R"]): + justify_text = x_justify + y_justify + x_pos = 0.5 + j*1.5 + fig.text(text=justify_text, x=x_pos, y=y_pos, + font="28p,Helvetica-Bold,black", justify=justify_text) + fig.plot(x=[x_pos, x_pos], y=[0., 4.], W="3p,red@85") +fig.show() + +######################################################################################## +# ``angle`` argument +# ------------------ +# ``angle`` is an optional argument used to specify the clockwise rotation of +# the text from the horizontal. + +fig = pygmt.Figure() +fig.basemap(region=[0, 4, 0, 4], projection="X10c", frame="WSen") +for i in range(0, 360, 30): + fig.text(text=f"` {i} Degrees", x=2, y=2, justify="LM", angle=i) +fig.show() + +######################################################################################## +# Additional arguments +# -------------------- +# +# Text can be further configured by passing an argument corresponding to the +# flag names in GMT, following the same convention as described in the GMT +# documentation. It is hoped that over time more bindings to these arguments +# will be written into PyGMT. + +fig = pygmt.Figure() +fig.basemap(region=[0, 1, 0, 1], projection="X5c", frame="WSen") +fig.text(text="Green", x=0.5, y=0.5, G="green") +fig.show() From 1e95af76e5f10ec5908a607e8394fec13243812e Mon Sep 17 00:00:00 2001 From: Wei Ji Date: Thu, 15 Oct 2020 11:15:55 +1300 Subject: [PATCH 2/7] Apply suggestions from code review Co-Authored-By: Dongdong Tian --- examples/tutorials/text.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/examples/tutorials/text.py b/examples/tutorials/text.py index 61a431bfb34..1d426397bf6 100644 --- a/examples/tutorials/text.py +++ b/examples/tutorials/text.py @@ -49,7 +49,7 @@ fig.coast(land="black", water="skyblue") # Customising the font style -fig.text(text="BORNEO", x="114.", y=0.5, font="22p,Helvetica-Bold,white") +fig.text(text="BORNEO", x=114.0, y=0.5, font="22p,Helvetica-Bold,white") fig.show() @@ -91,14 +91,19 @@ fig = pygmt.Figure() fig.basemap(region=[0, 4, 0, 4], projection="X10c", frame="WSen") for i, y_justify in enumerate(["T", "M", "B"]): - y_pos = 3.5 - i*1.5 - fig.plot(x=[0., 4.], y=[y_pos, y_pos], W='3p,red@85') + y_pos = 3.5 - i * 1.5 + fig.plot(x=[0.0, 4.0], y=[y_pos, y_pos], pen="3p,red@85") for j, x_justify in enumerate(["L", "C", "R"]): justify_text = x_justify + y_justify - x_pos = 0.5 + j*1.5 - fig.text(text=justify_text, x=x_pos, y=y_pos, - font="28p,Helvetica-Bold,black", justify=justify_text) - fig.plot(x=[x_pos, x_pos], y=[0., 4.], W="3p,red@85") + x_pos = 0.5 + j * 1.5 + fig.text( + text=justify_text, + x=x_pos, + y=y_pos, + font="28p,Helvetica-Bold,black", + justify=justify_text, + ) + fig.plot(x=[x_pos, x_pos], y=[0.0, 4.0], pen="3p,red@85") fig.show() ######################################################################################## From cb9f7137518de2433f2be86a1a22d0e0bb8ac72a Mon Sep 17 00:00:00 2001 From: Wei Ji Date: Thu, 15 Oct 2020 11:37:40 +1300 Subject: [PATCH 3/7] Simplify text positioning section to use e.g. TL, TC, TR, etc --- examples/tutorials/text.py | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/examples/tutorials/text.py b/examples/tutorials/text.py index 1d426397bf6..537e6ec3fc1 100644 --- a/examples/tutorials/text.py +++ b/examples/tutorials/text.py @@ -20,7 +20,8 @@ # # Here we create a simple map and add an annotation using the ``text``, ``x``, # and ``y`` arguments to specify the annotation text and position in the -# projection frame. ``text``, ``x``, and ``y`` accept `int`, `str`, or `float`. +# projection frame. ``text`` accepts 'str' types, while ``x``, and ``y`` +# accepts either 'int' or 'float' types. fig = pygmt.Figure() with pygmt.config(MAP_FRAME_TYPE="plain"): @@ -85,25 +86,18 @@ # # The anchor is specified with a two letter (order independent) code, chosen # from: -# * Horizontal anchor: L(eft), C(entre), R(ight) # * Vertical anchor: T(op), M(iddle), B(ottom) +# * Horizontal anchor: L(eft), C(entre), R(ight) fig = pygmt.Figure() -fig.basemap(region=[0, 4, 0, 4], projection="X10c", frame="WSen") -for i, y_justify in enumerate(["T", "M", "B"]): - y_pos = 3.5 - i * 1.5 - fig.plot(x=[0.0, 4.0], y=[y_pos, y_pos], pen="3p,red@85") - for j, x_justify in enumerate(["L", "C", "R"]): - justify_text = x_justify + y_justify - x_pos = 0.5 + j * 1.5 - fig.text( - text=justify_text, - x=x_pos, - y=y_pos, - font="28p,Helvetica-Bold,black", - justify=justify_text, - ) - fig.plot(x=[x_pos, x_pos], y=[0.0, 4.0], pen="3p,red@85") +fig.basemap(region=[0, 3, 0, 3], projection="X10c", frame=["WSne", "af0.5g"]) +for position in ("TL", "TC", "TR", "ML", "MC", "MR", "BL", "BC", "BR"): + fig.text( + text=position, + position=position, + font="28p,Helvetica-Bold,black", + justify=position, + ) fig.show() ######################################################################################## From 20994aa0294dec11ca376dd4c2fac485fdb04e42 Mon Sep 17 00:00:00 2001 From: Wei Ji Date: Thu, 15 Oct 2020 11:56:03 +1300 Subject: [PATCH 4/7] Make the examples.txt file on the fly Co-Authored-By: Conor Bacon --- examples/tutorials/examples.txt | 1 - examples/tutorials/text.py | 22 +++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) delete mode 100644 examples/tutorials/examples.txt diff --git a/examples/tutorials/examples.txt b/examples/tutorials/examples.txt deleted file mode 100644 index a2a25e48ea5..00000000000 --- a/examples/tutorials/examples.txt +++ /dev/null @@ -1 +0,0 @@ -114,0.5,BORNEO diff --git a/examples/tutorials/text.py b/examples/tutorials/text.py index 537e6ec3fc1..b87fe4298ad 100644 --- a/examples/tutorials/text.py +++ b/examples/tutorials/text.py @@ -6,6 +6,7 @@ :meth:`pygmt.Figure.text`. """ +import os import pygmt ######################################################################################## @@ -66,14 +67,21 @@ fig.basemap(region=[108, 120, -5, 8], projection="M20c", frame="a") fig.coast(land="black", water="skyblue") -# Plot region names / sea names -fig.text(textfiles="examples.txt", font="22p,Helvetica-Bold,white") +# Create space-delimited file +with open("examples.txt", "w") as f: + f.write("114 0.5 0 22p,Helvetica-Bold,white CM BORNEO\n") + f.write("119 3.25 0 12p,Helvetica-Bold,black CM CELEBES SEA\n") + f.write("112 -4.6 0 12p,Helvetica-Bold,black CM JAVA SEA\n") + f.write("112 6 40 12p,Helvetica-Bold,black CM SOUTH CHINA SEA\n") + f.write("119.12 7.25 -40 12p,Helvetica-Bold,black CM SULU SEA\n") + f.write("118.4 -1 65 12p,Helvetica-Bold,black CM MAKASSAR STRAIT\n") + +# Plot region names / sea names from a text file +fig.text(textfiles="examples.txt", angle=True, font=True, justify=True) + +# Cleanups +os.remove("examples.txt") -# Plot names of seas -fig.text(text=["CELEBES SEA", "JAVA SEA"], x=[119, 112], y=[3.25, -4.6]) -fig.text(text="SULU SEA", x=119.12, y=7.25, angle=-40) -fig.text(text="SOUTH CHINA SEA", x=112, y=6, angle=40) -fig.text(text="MAKASSAR STRAIT", x=118.4, y=-1, angle=65) fig.show() ######################################################################################## From 3dde4b0f77b231958991f4f20af9005bad8879ee Mon Sep 17 00:00:00 2001 From: Wei Ji Date: Thu, 15 Oct 2020 12:20:46 +1300 Subject: [PATCH 5/7] Use `fill` instead of G, and point advanced users to GMT cookbook --- examples/tutorials/text.py | 42 +++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/examples/tutorials/text.py b/examples/tutorials/text.py index b87fe4298ad..3e12b28b868 100644 --- a/examples/tutorials/text.py +++ b/examples/tutorials/text.py @@ -9,16 +9,13 @@ import os import pygmt -######################################################################################## +############################################################################### # Basic map annotation # -------------------- # # Text annotations can be added to a map using the :meth:`text` method of the # :class:`pygmt.Figure`. # -# Full details of the GMT6 command `text` can be found `here`_. -# The Python binding to this command is documented `here`_. -# # Here we create a simple map and add an annotation using the ``text``, ``x``, # and ``y`` arguments to specify the annotation text and position in the # projection frame. ``text`` accepts 'str' types, while ``x``, and ``y`` @@ -37,13 +34,15 @@ fig.show() -######################################################################################## +############################################################################### # Changing font style # ------------------- -# The size, family/weight, and colour of an annotation can be specified using the ``font`` argument. +# The size, family/weight, and colour of an annotation can be specified using +# the ``font`` argument. # -# A list of all recognised fonts can be found `here`_), -# including details of how to use non-default fonts. +# A list of all recognised fonts can be found at +# :gmt-docs:`cookbook/postscript_fonts.html`, including details of how to use +# non-default fonts. fig = pygmt.Figure() with pygmt.config(MAP_FRAME_TYPE="plain"): @@ -55,7 +54,7 @@ fig.show() -######################################################################################## +############################################################################### # Plotting from a text file # ------------------------- # @@ -84,7 +83,7 @@ fig.show() -######################################################################################## +############################################################################### # ``justify`` argument # -------------------- # @@ -108,7 +107,7 @@ ) fig.show() -######################################################################################## +############################################################################### # ``angle`` argument # ------------------ # ``angle`` is an optional argument used to specify the clockwise rotation of @@ -120,16 +119,21 @@ fig.text(text=f"` {i} Degrees", x=2, y=2, justify="LM", angle=i) fig.show() -######################################################################################## -# Additional arguments -# -------------------- +############################################################################### +# ``fill`` argument +# ----------------- # -# Text can be further configured by passing an argument corresponding to the -# flag names in GMT, following the same convention as described in the GMT -# documentation. It is hoped that over time more bindings to these arguments -# will be written into PyGMT. +# ``fill`` is used to set the fill colour of the area surrounding the text. fig = pygmt.Figure() fig.basemap(region=[0, 1, 0, 1], projection="X5c", frame="WSen") -fig.text(text="Green", x=0.5, y=0.5, G="green") +fig.text(text="Green", x=0.5, y=0.5, fill="green") fig.show() + +############################################################################### +# Advanced configuration +# ---------------------- +# +# For crafting more advanced styles, be sure to check out the GMT documentation +# at :gmt-docs:`text.html` and also the cookbook at +# :gmt-docs:`cookbook/features.html#placement-of-text`. Good luck! From 2afb5c8bb26f5270b1b1b88d8951501bb354699c Mon Sep 17 00:00:00 2001 From: Wei Ji Date: Thu, 15 Oct 2020 14:57:44 +1300 Subject: [PATCH 6/7] Some more stylistic fixes to the text documentation Co-Authored-By: Dongdong Tian --- examples/tutorials/text.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/examples/tutorials/text.py b/examples/tutorials/text.py index 3e12b28b868..95732d9684c 100644 --- a/examples/tutorials/text.py +++ b/examples/tutorials/text.py @@ -13,13 +13,13 @@ # Basic map annotation # -------------------- # -# Text annotations can be added to a map using the :meth:`text` method of the -# :class:`pygmt.Figure`. +# Text annotations can be added to a map using the :meth:`pygmt.Figure.text` +# method of the :class:`pygmt.Figure` class. # # Here we create a simple map and add an annotation using the ``text``, ``x``, # and ``y`` arguments to specify the annotation text and position in the # projection frame. ``text`` accepts 'str' types, while ``x``, and ``y`` -# accepts either 'int' or 'float' types. +# accepts either 'int'/'float' numbers, or a list/array of numbers. fig = pygmt.Figure() with pygmt.config(MAP_FRAME_TYPE="plain"): @@ -37,7 +37,7 @@ ############################################################################### # Changing font style # ------------------- -# The size, family/weight, and colour of an annotation can be specified using +# The size, family/weight, and color of an annotation can be specified using # the ``font`` argument. # # A list of all recognised fonts can be found at @@ -75,7 +75,11 @@ f.write("119.12 7.25 -40 12p,Helvetica-Bold,black CM SULU SEA\n") f.write("118.4 -1 65 12p,Helvetica-Bold,black CM MAKASSAR STRAIT\n") -# Plot region names / sea names from a text file +# Plot region names / sea names from a text file, where +# the longitude (x) and latitude (y) coordinates are in the first two columns. +# Setting angle/font/justiry to True will indicate that those columns are +# present in the text file too (Note: must be in that order!). +# Finally, the text to be printed will be in the last column fig.text(textfiles="examples.txt", angle=True, font=True, justify=True) # Cleanups @@ -114,16 +118,16 @@ # the text from the horizontal. fig = pygmt.Figure() -fig.basemap(region=[0, 4, 0, 4], projection="X10c", frame="WSen") +fig.basemap(region=[0, 4, 0, 4], projection="X5c", frame="WSen") for i in range(0, 360, 30): - fig.text(text=f"` {i} Degrees", x=2, y=2, justify="LM", angle=i) + fig.text(text=f"` {i}@.", x=2, y=2, justify="LM", angle=i) fig.show() ############################################################################### # ``fill`` argument # ----------------- # -# ``fill`` is used to set the fill colour of the area surrounding the text. +# ``fill`` is used to set the fill color of the area surrounding the text. fig = pygmt.Figure() fig.basemap(region=[0, 1, 0, 1], projection="X5c", frame="WSen") From 659860d42fc5035bfef431d59ea7497831156b37 Mon Sep 17 00:00:00 2001 From: Wei Ji Date: Thu, 15 Oct 2020 15:11:26 +1300 Subject: [PATCH 7/7] Fix typo in link to postscript-fonts documentation --- examples/tutorials/text.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/tutorials/text.py b/examples/tutorials/text.py index 95732d9684c..403f7ec8e72 100644 --- a/examples/tutorials/text.py +++ b/examples/tutorials/text.py @@ -41,7 +41,7 @@ # the ``font`` argument. # # A list of all recognised fonts can be found at -# :gmt-docs:`cookbook/postscript_fonts.html`, including details of how to use +# :gmt-docs:`cookbook/postscript-fonts.html`, including details of how to use # non-default fonts. fig = pygmt.Figure()