Skip to content

Wrap subplot using with statement #822

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 42 commits into from
Feb 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
f2ac98b
Wrap subplot - version 3
weiji14 Jan 30, 2021
683ff57
Add fig.subplot and fig.sca to API docs
weiji14 Jan 30, 2021
0742da7
Merge branch 'master' into subplot_v3
weiji14 Feb 3, 2021
95e3a64
Alias fixedlabel (A), clearance (C), verbose (V) for sca
weiji14 Feb 3, 2021
8283f65
Turn fig.sca into a context manager
weiji14 Feb 3, 2021
92b7fbd
Alias projection (J), region (R), verbose (V), x/yshift (X/Y) for sub…
weiji14 Feb 5, 2021
6cb2e59
Merge branch 'master' into subplot_v3
weiji14 Feb 5, 2021
9d6f20b
Fix subplot end -V
weiji14 Feb 5, 2021
3f0c008
Improve docstring of fig.subplot and fig.sca
weiji14 Feb 5, 2021
967fba3
Small tweaks to subplot tutorial
weiji14 Feb 5, 2021
3de8489
Merge branch 'master' into subplot_v3
weiji14 Feb 6, 2021
14ae58c
Allow list or tuple inputs to ax (c) argument in basemap
weiji14 Feb 6, 2021
ddee738
Use sequence_comma instead of sequence
weiji14 Feb 6, 2021
7a2662a
Merge branch 'master' into subplot_v3
weiji14 Feb 6, 2021
dbd4677
Remove use of matplotlib-like Axes (axs) object
weiji14 Feb 6, 2021
4126c16
Allow for spaces in title and labels without needing double quotes
weiji14 Feb 6, 2021
df9f5f0
Merge branch 'master' into subplot_v3
weiji14 Feb 6, 2021
0521851
Ensure that a list can be passed into region (R)
weiji14 Feb 6, 2021
6eb58ea
Allow for list inputs into fig.sca(ax=...)
weiji14 Feb 6, 2021
2d042eb
Merge branch 'master' into subplot_v3
weiji14 Feb 7, 2021
d70cce0
Merge branch 'master' into subplot_v3
weiji14 Feb 10, 2021
b03a5dd
Rename sca to set_panel and ax to panel
weiji14 Feb 10, 2021
1e46b71
Merge branch 'master' into subplot_v3
weiji14 Feb 11, 2021
6ba4d49
Update docstring for layout (S) to say +w is for the figsize/subsize arg
weiji14 Feb 11, 2021
d3c0a50
Apply formatting suggestions from code review
weiji14 Feb 12, 2021
eadb847
Fix bug that prevented boolean to -A from working
weiji14 Feb 12, 2021
f568982
Add note that subplot panel is activated until further notice
weiji14 Feb 12, 2021
2c239c2
Merge branch 'master' into subplot_v3
weiji14 Feb 12, 2021
6c1ed41
Remove arg_str strip() for subplot set and end
weiji14 Feb 12, 2021
fab1b9d
Split layout (S) into sharex (SC) and sharey (SR)
weiji14 Feb 12, 2021
3f042d0
Merge branch 'master' into subplot_v3
weiji14 Feb 12, 2021
ad34871
Fix small typo
weiji14 Feb 12, 2021
ef9ee2d
Proofread edits to subplot and set_panel docstring
weiji14 Feb 13, 2021
c6b0242
Update fig.set_panel clearance docstring with code-block example
weiji14 Feb 13, 2021
c475861
Validate subplot nrows/ncols and figsize/subsize argument inputs
weiji14 Feb 13, 2021
a48b600
Proof edits to subplot round 2
weiji14 Feb 13, 2021
2f18fe7
Merge branch 'master' into subplot_v3
weiji14 Feb 13, 2021
f4499a8
Revise advanced subplot layout subsection to use two subplots calls
weiji14 Feb 13, 2021
e0900e9
Proofread edits to subplot round 3
weiji14 Feb 14, 2021
ebc807e
Replace argument with parameter as per #886
weiji14 Feb 14, 2021
d16de28
Merge branch 'master' into subplot_v3
weiji14 Feb 14, 2021
30ef9c4
Proofread edits to subplot round 4
weiji14 Feb 14, 2021
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
2 changes: 2 additions & 0 deletions doc/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ Plotting data and laying out the map:
Figure.meca
Figure.plot
Figure.plot3d
Figure.set_panel
Figure.shift_origin
Figure.subplot
Figure.text

Color palette table generation:
Expand Down
1 change: 1 addition & 0 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
tutorials/earth-relief.rst
tutorials/3d-perspective-image.rst
tutorials/inset.rst
tutorials/subplots.rst
tutorials/configuration.rst

.. toctree::
Expand Down
237 changes: 237 additions & 0 deletions examples/tutorials/subplots.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
"""
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.

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.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.
"""
# sphinx_gallery_thumbnail_number = 3

import pygmt

###############################################################################
#
# Let's start by initializing a :class:`pygmt.Figure` instance.

fig = pygmt.Figure()

###############################################################################
# Define subplot layout
# ---------------------
#
# The :meth:`pygmt.Figure.subplot` function 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
#
# with fig.subplot(nrows=2, ncols=3, figsize=("15c", "6c"), frame="lrtb"):
# ...

###############################################################################
# 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:

with fig.subplot(nrows=2, ncols=3, figsize=("15c", "6c"), frame="lrtb"):
for i in range(2): # row number starting from 0
for j in range(3): # column number starting from 0
index = i * 3 + j # index number starting from 0
with fig.set_panel(panel=index): # sets the current panel
fig.text(
position="MC",
text=f"index: {index}; row: {i}, col: {j}",
region=[0, 1, 0, 1],
)
fig.show()

###############################################################################
# The :meth:`pygmt.Figure.set_panel` function activates a specified subplot, and
# all subsequent plotting functions 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.

###############################################################################
# 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]):
# ...

###############################################################################
# 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.

fig = pygmt.Figure()
with fig.subplot(
nrows=2,
ncols=2,
figsize=("15c", "6c"),
autolabel=True,
frame=["af", "WSne"],
margins=["0.1c", "0.2c"],
title="My Subplot Heading",
):
fig.basemap(region=[0, 10, 0, 10], projection="X?", panel=[0, 0])
fig.basemap(region=[0, 20, 0, 10], projection="X?", panel=[0, 1])
fig.basemap(region=[0, 10, 0, 20], projection="X?", panel=[1, 0])
fig.basemap(region=[0, 20, 0, 20], projection="X?", panel=[1, 1])
fig.show()

###############################################################################
# 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:
#
# - ``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.
# - ``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 the each subplot's map
# frame.

###############################################################################
# .. tip::
#
# 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.

###############################################################################
# .. note::
#
# All plotting functions (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 axis labels
# --------------------------
# 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,
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
sharey="l", # shared y-axis on the left side
frame="WSrt",
):
fig.basemap(region=[0, 10, 0, 10], projection="X?", panel=True)
fig.basemap(region=[0, 20, 0, 10], projection="X?", panel=True)
fig.basemap(region=[0, 10, 0, 20], projection="X?", panel=True)
fig.basemap(region=[0, 20, 0, 20], projection="X?", panel=True)
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.
#
# Of course, instead of using the ``sharex``/``sharey`` option, you can also
# set a different ``frame`` for each subplot to control the axis properties
# individually for each subplot.

###############################################################################
# Advanced subplot layouts
# ------------------------
#
# Nested subplot 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.

fig = pygmt.Figure()
# Bottom row, two subplots
with fig.subplot(nrows=1, ncols=2, figsize=("15c", "3c"), autolabel="b)"):
fig.basemap(
region=[0, 5, 0, 5], projection="X?", frame=["af", "WSne"], panel=[0, 0]
)
fig.basemap(
region=[0, 5, 0, 5], projection="X?", frame=["af", "WSne"], panel=[0, 1]
)
# 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)"):
fig.basemap(
region=[0, 10, 0, 10], projection="X?", frame=["af", "WSne"], panel=[0, 0]
)
fig.text(text="TEXT", x=5, y=5)

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.

###############################################################################
# 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.
2 changes: 2 additions & 0 deletions pygmt/figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,5 +387,7 @@ def _repr_html_(self):
meca,
plot,
plot3d,
set_panel,
subplot,
text,
)
1 change: 1 addition & 0 deletions pygmt/src/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from pygmt.src.meca import meca
from pygmt.src.plot import plot
from pygmt.src.plot3d import plot3d
from pygmt.src.subplot import set_panel, subplot
from pygmt.src.surface import surface
from pygmt.src.text import text_ as text # "text" is an argument within "text_"
from pygmt.src.which import which
Loading