Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9087c6e
Figure.subplot: Pythonic implemention for the subplot tagging
seisman Dec 20, 2025
6a05085
Figure.subplot: Pythonic implemention for the subplot tagging
seisman Dec 20, 2025
72671b7
Merge branch 'main' into subplot/A
seisman Jan 30, 2026
b316a22
Checking tag_position and tag_box
seisman Jan 30, 2026
58e8044
Add doctests
seisman Jan 30, 2026
7675235
Merge remote-tracking branch 'origin/subplot/A' into subplot/A
seisman Jan 30, 2026
7096da6
Update tests and gallery examples
seisman Jan 30, 2026
8340829
Fix the validation logic for tag_position
seisman Jan 30, 2026
9d27178
Rename test_subplot_autolabel_margins_title.png.dvc -> test_subplot_…
seisman Jan 30, 2026
d91d395
Merge branch 'main' into subplot/A
seisman Feb 5, 2026
0c7de28
Fix conflicts
seisman Feb 5, 2026
89e4e88
Add more tests
seisman Feb 5, 2026
c3a3282
Improve comments
seisman Feb 5, 2026
af724ea
Fix type hints
seisman Feb 5, 2026
a002c23
Merge branch 'main' into subplot/A
seisman Feb 6, 2026
76bee1e
Merge branch 'main' into subplot/A
seisman Feb 6, 2026
a009dac
Merge branch 'main' into subplot/A
seisman Feb 6, 2026
1f15907
Rename autotag to tag
seisman Feb 7, 2026
1f7af38
Fix a typo
seisman Feb 7, 2026
d652e01
Fix tests
seisman Feb 7, 2026
f768117
Merge remote-tracking branch 'origin/subplot/A' into subplot/A
seisman Feb 7, 2026
81ae0ee
Improve docstrings
seisman Feb 7, 2026
0c85280
Rewrap to 88 characeters
seisman Feb 7, 2026
48ccdf9
Merge branch 'main' into subplot/A
seisman Feb 7, 2026
6020654
Merge branch 'main' into subplot/A
seisman Feb 8, 2026
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
33 changes: 15 additions & 18 deletions examples/gallery/embellishments/colorbars_multiple.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
Multiple colormaps
==================

This gallery example shows how to create multiple colormaps for different
subplots. To better understand how GMT modern mode maintains several levels of
colormaps, please refer to
:gmt-docs:`reference/features.html#gmt-modern-mode-hierarchical-levels` for
This gallery example shows how to create multiple colormaps for different subplots. To
better understand how GMT modern mode maintains several levels of colormaps, please
refer to :gmt-docs:`reference/features.html#gmt-modern-mode-hierarchical-levels` for
details.
"""

Expand All @@ -19,26 +18,24 @@
subset_region = [-14, 30, 35, 60]
grid_subset = pygmt.datasets.load_earth_relief(resolution="10m", region=subset_region)

# Define a 1-row, 2-column subplot layout. The overall figure dimensions are
# set to be 15 cm wide and 8 cm high. Each subplot is automatically labelled.
# The space between the subplots is set to be 0.5 cm.
with fig.subplot(
nrows=1, ncols=2, figsize=("15c", "8c"), autolabel=True, margins="0.5c"
):
# Activate the first panel so that the colormap created by the makecpt
# function is a panel-level CPT
# Define a 1-row, 2-column subplot layout. The overall figure dimensions are set to be
# 15 cm wide and 8 cm high. Each subplot is automatically tagged. The space between the
# subplots is set to be 0.5 cm.
with fig.subplot(nrows=1, ncols=2, figsize=("15c", "8c"), tag=True, margins=0.5):
# Activate the first panel so that the colormap created by the makecpt function is
# a panel-level CPT
with fig.set_panel(panel=0):
pygmt.makecpt(cmap="gmt/geo", series=[-8000, 8000])
# "R?" means Winkel Tripel projection with map width automatically
# determined from the subplot width.
# "R?" means Winkel Tripel projection with map width automatically determined
# from the subplot width.
fig.grdimage(grid=grid_globe, projection="R?", region="g", frame="a")
fig.colorbar(frame=["a4000f2000", "x+lElevation", "y+lm"])
# Activate the second panel so that the colormap created by the makecpt
# function is a panel-level CPT
# Activate the second panel so that the colormap created by the makecpt function is
# a panel-level CPT
with fig.set_panel(panel=1):
pygmt.makecpt(cmap="gmt/globe", series=[-6000, 3000])
# "M?" means Mercator projection with map width also automatically
# determined from the subplot width.
# "M?" means Mercator projection with map width also automatically determined
# from the subplot width.
fig.grdimage(grid=grid_subset, projection="M?", region=subset_region, frame="a")
fig.colorbar(frame=["a2000f1000", "x+lElevation", "y+lm"])

Expand Down
166 changes: 80 additions & 86 deletions examples/tutorials/advanced/subplots.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@
Making subplots
===============

When you're preparing a figure for a paper, there will often be times when
you'll need to put many individual plots into one large figure, and label them
'abcd'. These individual plots are called subplots.
When you're preparing a figure for a paper, there will often be times when you'll need
to put many individual plots into one large figure, and tag them 'abcd'. These
individual plots are called subplots.

There are two main ways to create subplots in GMT:

- Use :meth:`pygmt.Figure.shift_origin` to manually move each individual plot
to the right position.
- Use :meth:`pygmt.Figure.shift_origin` to manually move each individual plot to the
right position.
- Use :meth:`pygmt.Figure.subplot` to define the layout of the subplots.

The first method is easier to use and should handle simple cases involving a
couple of subplots. For more advanced subplot layouts, however, we recommend
the use of :meth:`pygmt.Figure.subplot` which offers finer grained control, and
this is what the tutorial below will cover.
The first method is easier to use and should handle simple cases involving a couple of
subplots. For more advanced subplot layouts, however, we recommend the use of
:meth:`pygmt.Figure.subplot` which offers finer grained control, and this is what the
tutorial below will cover.
"""

# %%
Expand All @@ -31,10 +31,10 @@
# Define subplot layout
# ---------------------
#
# The :meth:`pygmt.Figure.subplot` method is used to set up the layout, size,
# and other attributes of the figure. It divides the whole canvas into regular
# grid areas with *n* rows and *m* columns. Each grid area can contain an
# individual subplot. For example:
# The :meth:`pygmt.Figure.subplot` method is used to set up the layout, size, and other
# attributes of the figure. It divides the whole canvas into regular grid areas with
# *n* rows and *m* columns. Each grid area can contain an individual subplot. For
# example:

# %%
# .. code-block:: default
Expand All @@ -44,10 +44,10 @@

# %%
# will define our figure to have a 2 row and 3 column grid layout.
# ``figsize=("15c", "6c")`` defines the overall size of the figure to be 15 cm
# wide by 6 cm high. Using ``frame="lrtb"`` allows us to customize the map
# frame for all subplots instead of setting them individually. The figure
# layout will look like the following:
# ``figsize=("15c", "6c")`` defines the overall size of the figure to be 15 cm wide by
# 6 cm high. Using ``frame="lrtb"`` allows us to customize the map frame for all
# subplots instead of setting them individually. The figure layout will look like the
# following:

with fig.subplot(nrows=2, ncols=3, figsize=("15c", "6c"), frame="lrtb"):
for i in range(2): # row number starting from 0
Expand All @@ -62,45 +62,44 @@
fig.show()

# %%
# The :meth:`pygmt.Figure.set_panel` method activates a specified subplot,
# and all subsequent plotting methods will take place in that subplot panel.
# This is similar to matplotlib's ``plt.sca`` method. In order to specify a
# subplot, you will need to provide the identifier for that subplot via the
# ``panel`` parameter. Pass in either the *index* number, or a tuple/list like
# (*row*, *col*) to ``panel``.
# The :meth:`pygmt.Figure.set_panel` method activates a specified subplot, and all
# subsequent plotting methods will take place in that subplot panel. This is similar to
# matplotlib's ``plt.sca`` method. In order to specify a subplot, you will need to
# provide the identifier for that subplot via the ``panel`` parameter. Pass in either
# the *index* number, or a tuple/list like (*row*, *col*) to ``panel``.

# %%
# .. note::
#
# The row and column numbering starts from 0. So for a subplot layout with
# N rows and M columns, row numbers will go from 0 to N-1, and column
# numbers will go from 0 to M-1.
# The row and column numbering starts from 0. So for a subplot layout with N rows
# and M columns, row numbers will go from 0 to N-1, and column numbers will go from
# 0 to M-1.

# %%
# For example, to activate the subplot on the top right corner (index: 2) at
# *row*\=0 and *col*\=2, so that all subsequent plotting commands happen
# there, you can use the following command:
# For example, to activate the subplot on the top right corner (index: 2) at *row*\=0
# and *col*\=2, so that all subsequent plotting commands happen there, you can use the
# following command:

# %%
# .. code-block:: default
#
# with fig.set_panel(panel=[0, 2]):
# with fig.set_panel(panel=(0, 2)):
# ...


# %%
# Making your first subplot
# -------------------------
#
# Next, let's use what we learned above to make a 2 row by 2 column subplot
# figure. We'll also pick up on some new parameters to configure our subplot.
# Next, let's use what we learned above to make a 2 row by 2 column subplot figure.
# We'll also pick up on some new parameters to configure our subplot.

fig = pygmt.Figure()
with fig.subplot(
nrows=2,
ncols=2,
figsize=("15c", "6c"),
autolabel=True,
tag=True,
frame=["af", "WSne"],
margins=["0.1c", "0.2c"],
title="My Subplot Heading",
Expand All @@ -113,62 +112,59 @@

# %%
# In this example, we define a 2-row, 2-column (2x2) subplot layout using
# :meth:`pygmt.Figure.subplot`. The overall figure dimensions is set to be
# 15 cm wide and 6 cm high (``figsize=["15c", "6c"]``). In addition, we use
# some optional parameters to fine-tune some details of the figure creation:
# :meth:`pygmt.Figure.subplot`. The overall figure dimensions is set to be 15 cm wide
# and 6 cm high (``figsize=("15c", "6c")``). In addition, we use some optional
# parameters to fine-tune some details of the figure creation:
#
# - ``autolabel=True``: Each subplot is automatically labelled 'abcd'.
# - ``margins=["0.1c", "0.2c"]``: Adjusts the space between adjacent subplots.
# In this case, it is set as 0.1 cm in the x-direction and 0.2 cm in the
# y-direction.
# - ``tag=True``: Each subplot is automatically tagged 'abcd'.
# - ``margins=["0.1c", "0.2c"]``: Adjusts the space between adjacent subplots. In this
# case, it is set as 0.1 cm in the x-direction and 0.2 cm in the y-direction.
# - ``title="My Subplot Heading"``: Adds a title on top of the whole figure.
#
# Notice that each subplot was set to use a linear projection ``"X?"``.
# Usually, we need to specify the width and height of the map frame, but it is
# also possible to use a question mark ``"?"`` to let GMT decide automatically
# on what is the most appropriate width/height for each subplot's map frame.
# Notice that each subplot was set to use a linear projection ``"X?"``. Usually, we need
# to specify the width and height of the map frame, but it is also possible to use a
# question mark ``"?"`` to let GMT decide automatically on what is the most appropriate
# width/height for each subplot's map frame.

# %%
# .. tip::
#
# In the above example, we used the following commands to activate the
# four subplots explicitly one after another::
# In the above example, we used the following commands to activate the four subplots
# explicitly one after another::
#
# fig.basemap(..., panel=[0, 0])
# fig.basemap(..., panel=[0, 1])
# fig.basemap(..., panel=[1, 0])
# fig.basemap(..., panel=[1, 1])
#
# In fact, we can just use ``fig.basemap(..., panel=True)`` without
# specifying any subplot index number, and GMT will automatically activate
# the next subplot panel.
# In fact, we can just use ``fig.basemap(..., panel=True)`` without specifying any
# subplot index number, and GMT will automatically activate the next subplot panel.

# %%
# .. note::
#
# All plotting methods (e.g. :meth:`pygmt.Figure.coast`,
# :meth:`pygmt.Figure.text`, etc) are able to use ``panel`` parameter when
# in subplot mode. Once a panel is activated using ``panel`` or
# :meth:`pygmt.Figure.set_panel`, subsequent plotting commands that don't
# set a ``panel`` will have their elements added to the same panel as
# before.
# All plotting methods (e.g. :meth:`pygmt.Figure.coast`, :meth:`pygmt.Figure.text`,
# etc) are able to use ``panel`` parameter when in subplot mode. Once a panel is
# activated using ``panel`` or :meth:`pygmt.Figure.set_panel`, subsequent plotting
# commands that don't set a ``panel`` will have their elements added to the same
# panel as before.


# %%
# Shared x- and y-axes
# --------------------
#
# In the example above with the four subplots, the two subplots for each row
# have the same y-axis range, and the two subplots for each column have the
# same x-axis range. You can use the ``sharex``/``sharey`` parameters to set a
# common x- and/or y-axis between subplots.
# In the example above with the four subplots, the two subplots for each row have the
# same y-axis range, and the two subplots for each column have the same x-axis range.
# You can use the ``sharex``/``sharey`` parameters to set a common x- and/or y-axis
# between subplots.

fig = pygmt.Figure()
with fig.subplot(
nrows=2,
ncols=2,
figsize=("15c", "6c"), # width of 15 cm, height of 6 cm
autolabel=True,
tag=True,
margins=["0.3c", "0.2c"], # horizontal 0.3 cm and vertical 0.2 cm margins
title="My Subplot Heading",
sharex="b", # shared x-axis on the bottom side
Expand All @@ -182,29 +178,28 @@
fig.show()

# %%
# ``sharex="b"`` indicates that subplots in a column will share the x-axis, and
# only the **b**\ ottom axis is displayed. ``sharey="l"`` indicates that
# subplots within a row will share the y-axis, and only the **l**\ eft axis is
# displayed.
# ``sharex="b"`` indicates that subplots in a column will share the x-axis, and only the
# **b**\ ottom axis is displayed. ``sharey="l"`` indicates that subplots within a row
# will share the y-axis, and only the **l**\ eft axis is displayed.
#
# Of course, instead of using the ``sharex``/``sharey`` parameters, you can
# also set a different ``frame`` for each subplot to control the axis
# properties individually for each subplot.
# Of course, instead of using the ``sharex``/``sharey`` parameters, you can also set a
# different ``frame`` for each subplot to control the axis properties individually for
# each subplot.


# %%
# Advanced subplot layouts
# ------------------------
#
# Nested subplots are currently not supported. If you want to create more
# complex subplot layouts, some manual adjustments are needed.
# Nested subplots are currently not supported. If you want to create more complex
# subplot layouts, some manual adjustments are needed.
#
# The following example draws three subplots in a 2-row, 2-column layout, with
# the first subplot occupying the first row.
# The following example draws three subplots in a 2-row, 2-column layout, with the first
# subplot occupying the first row.

fig = pygmt.Figure()
# Bottom row, two subplots
with fig.subplot(nrows=1, ncols=2, figsize=("15c", "3c"), autolabel="b)"):
with fig.subplot(nrows=1, ncols=2, figsize=("15c", "3c"), tag="b)"):
fig.basemap(
region=[0, 5, 0, 5], projection="X?", frame=["af", "WSne"], panel=[0, 0]
)
Expand All @@ -214,7 +209,7 @@
# Move plot origin by 1 cm above the height of the entire figure
fig.shift_origin(yshift="h+1c")
# Top row, one subplot
with fig.subplot(nrows=1, ncols=1, figsize=("15c", "3c"), autolabel="a)"):
with fig.subplot(nrows=1, ncols=1, figsize=("15c", "3c"), tag="a)"):
fig.basemap(
region=[0, 10, 0, 10], projection="X?", frame=["af", "WSne"], panel=[0, 0]
)
Expand All @@ -223,20 +218,19 @@
fig.show()

# %%
# We start by drawing the bottom two subplots, setting ``autolabel="b)"`` so
# that the subplots are labelled 'b)' and 'c)'. Next, we use
# :meth:`pygmt.Figure.shift_origin` to move the plot origin 1 cm above the
# **h**\ eight of the entire figure that is currently plotted (i.e. the bottom
# row subplots). A single subplot is then plotted on the top row. You may need
# to adjust the ``yshift`` parameter to make your plot look nice. This top row
# uses ``autolabel="a)"``, and we also plotted some text inside. Note that
# ``projection="X?"`` was used to let GMT automatically determine the size of
# the subplot according to the size of the subplot area.
# We start by drawing the bottom two subplots, setting ``tag="b)"`` so that the subplots
# are tagged 'b)' and 'c)'. Next, we use :meth:`pygmt.Figure.shift_origin` to move the
# plot origin 1 cm above the **h**\ eight of the entire figure that is currently plotted
# (i.e. the bottom row subplots). A single subplot is then plotted on the top row. You
# may need to adjust the ``yshift`` parameter to make your plot look nice. This top row
# uses ``tag="a)"``, and we also plotted some text inside. Note that ``projection="X?"``
# was used to let GMT automatically determine the size of the subplot according to the
# size of the subplot area.

# %%
# You can also manually override the ``autolabel`` for each subplot using for
# example, ``fig.set_panel(..., fixedlabel="b) Panel 2")`` which would allow
# you to manually label a single subplot as you wish. This can be useful for
# adding a more descriptive subtitle to individual subplots.
# You can also manually override the ``tag`` for each subplot using for example,
# ``fig.set_panel(..., fixedlabel="b) Panel 2")`` which would allow you to manually tag
# a single subplot as you wish. This can be useful for adding a more descriptive
# subtitle to individual subplots.

# sphinx_gallery_thumbnail_number = 3
Loading
Loading