|
| 1 | + |
| 2 | +.. _figure_explanation: |
| 3 | + |
| 4 | +================================================ |
| 5 | +Creating, viewing, and saving Matplotlib Figures |
| 6 | +================================================ |
| 7 | + |
| 8 | +.. plot:: |
| 9 | + :include-source: |
| 10 | + |
| 11 | + fig = plt.figure(figsize=(2, 2), facecolor='lightskyblue', |
| 12 | + layout='constrained') |
| 13 | + fig.suptitle('Figure') |
| 14 | + ax = fig.add_subplot() |
| 15 | + ax.set_title('Axes', loc='left', fontstyle='oblique', fontsize='medium') |
| 16 | + |
| 17 | +When looking at Matplotlib visualization, you are almost always looking at |
| 18 | +Artists placed on a `~.Figure`. In the example above, the figure is the |
| 19 | +blue region and `~.Figure.add_subplot` has added an `~.axes.Axes` artist to the |
| 20 | +`~.Figure` (see :ref:`figure_parts`). A more complicated visualization can add |
| 21 | +multiple Axes to the Figure, colorbars, legends, annotations, and the Axes |
| 22 | +themselves can have multiple Artists added to them |
| 23 | +(e.g. ``ax.plot`` or ``ax.imshow``). |
| 24 | + |
| 25 | +.. _viewing_figures: |
| 26 | + |
| 27 | +Viewing Figures |
| 28 | +================ |
| 29 | + |
| 30 | +We will discuss how to create Figures in more detail below, but first it is |
| 31 | +helpful to understand how to view a Figure. This varies based on how you are |
| 32 | +using Matplotlib, and what :ref:`Backend <what-is-a-backend>` you are using. |
| 33 | + |
| 34 | +Notebooks and IDEs |
| 35 | +------------------ |
| 36 | + |
| 37 | +If you are using a Notebook (e.g. `Jupyter <https://jupyter.org>`_) or an IDE |
| 38 | +that renders Notebooks (PyCharm, VSCode, etc), then they have a backend that |
| 39 | +will render the Matplotlib Figure when a code cell is executed. One thing to |
| 40 | +be aware of is that the default Jupyter backend (``%matplotlib inline``) will |
| 41 | +by default trim or expand the figure size to have a tight box around Artists |
| 42 | +added to the Figure (see :ref:`saving_figures`, below). |
| 43 | + |
| 44 | +Standalone scripts and interactive use |
| 45 | +-------------------------------------- |
| 46 | + |
| 47 | +If the user is on a client with a windowing system, there are a number of |
| 48 | +:ref:`Backends <what-is-a-backend>` that can be used to render the Figure to |
| 49 | +the screen, usually using a Python Qt, Tk, or Wx toolkit, though there is a native |
| 50 | +MacOS backend as well. These are typically chosen either in the user's |
| 51 | +:ref:`matplotlibrc <customizing-with-matplotlibrc-files>`, or by calling |
| 52 | +``matplotlib.use('QtAgg')`` at the beginning of a session or script. |
| 53 | + |
| 54 | +When run from a script, or interactively (e.g. from an |
| 55 | +`iPython shell <https://https://ipython.readthedocs.io/en/stable/>`_) the Figure |
| 56 | +will not be shown until we call ``plt.show()``. The Figure will appear in |
| 57 | +a new GUI window, and usually will have a toolbar with Zoom, Pan, and other tools |
| 58 | +for interacting with the Figure. By default, ``plt.show()`` blocks |
| 59 | +further interaction from the script or shell until the Figure window is closed, |
| 60 | +though that can be toggled off for some purposes. For more details, please see |
| 61 | +:ref:`controlling-interactive`. |
| 62 | + |
| 63 | +Note that if you are on a client that does not have access to a windowing |
| 64 | +system, the Figure will fallback to being drawn using the "Agg" backend, and |
| 65 | +cannot be viewed, though it can be :ref:`saved <saving_figures>`. |
| 66 | + |
| 67 | +.. _creating_figures: |
| 68 | + |
| 69 | +Creating Figures |
| 70 | +================ |
| 71 | + |
| 72 | +By far the most common way to create a figure is using the |
| 73 | +:doc:`pyplot </tutorials/introductory/pyplot>` interface. As noted in |
| 74 | +:ref:`api_interfaces`, the pyplot interface serves two purposes. One is to spin |
| 75 | +up the Backend and keep track of GUI windows. The other is a global state for |
| 76 | +Axes and Artists that allow a short-form API to plotting methods. In the |
| 77 | +example above, we use pyplot for the first purpose, and create the Figure object, |
| 78 | +``fig``. As a side effect ``fig`` is also added to pyplot's global state, and |
| 79 | +can be accessed via `~.pyplot.gcf`. |
| 80 | + |
| 81 | +Users typically want an Axes or a grid of Axes when they create a Figure, so in |
| 82 | +addition to `~.pyplot.figure`, there are convenience methods that return both |
| 83 | +a Figure and some Axes. A simple grid of Axes can be achieved with |
| 84 | +`.pyplot.subplots` (which |
| 85 | +simply wraps `.Figure.subplots`): |
| 86 | + |
| 87 | +.. plot:: |
| 88 | + :include-source: |
| 89 | + |
| 90 | + fig, axs = plt.subplots(2, 2, figsize=(4, 3), layout='constrained') |
| 91 | + |
| 92 | +More complex grids can be achieved with `.pyplot.subplot_mosaic` (which wraps |
| 93 | +`.Figure.subplot_mosaic`): |
| 94 | + |
| 95 | +.. plot:: |
| 96 | + :include-source: |
| 97 | + |
| 98 | + fig, axs = plt.subplot_mosaic([['A', 'right'], ['B', 'right']], |
| 99 | + figsize=(4, 3), layout='constrained') |
| 100 | + for ax_name in axs: |
| 101 | + axs[ax_name].text(0.5, 0.5, ax_name, ha='center', va='center') |
| 102 | + |
| 103 | +Sometimes we want to have a nested layout in a Figure, with two or more sets of |
| 104 | +Axes that do not share the same subplot grid. |
| 105 | +We can use `~.Figure.add_subfigure` or `~.Figure.subfigures` to create virtual |
| 106 | +figures inside a parent Figure; see |
| 107 | +:doc:`/gallery/subplots_axes_and_figures/subfigures` for more details. |
| 108 | + |
| 109 | +.. plot:: |
| 110 | + :include-source: |
| 111 | + |
| 112 | + fig = plt.figure(layout='constrained', facecolor='lightskyblue') |
| 113 | + fig.suptitle('Figure') |
| 114 | + figL, figR = fig.subfigures(1, 2) |
| 115 | + figL.set_facecolor('thistle') |
| 116 | + axL = figL.subplots(2, 1, sharex=True) |
| 117 | + axL[1].set_xlabel('x [m]') |
| 118 | + figL.suptitle('Left subfigure') |
| 119 | + figR.set_facecolor('paleturquoise') |
| 120 | + axR = figR.subplots(1, 2, sharey=True) |
| 121 | + axR[0].set_title('Axes 1') |
| 122 | + figR.suptitle('Right subfigure') |
| 123 | + |
| 124 | +It is possible to directly instantiate a `.Figure` instance without using the |
| 125 | +pyplot interface. This is usually only necessary if you want to create your |
| 126 | +own GUI application or service that you do not want carrying the pyplot global |
| 127 | +state. See the embedding examples in :doc:`/gallery/user_interfaces/index` for |
| 128 | +examples of how to do this. |
| 129 | + |
| 130 | +Figure options |
| 131 | +-------------- |
| 132 | + |
| 133 | +There are a few options available when creating figures. The Figure size on |
| 134 | +the screen is set by *figsize* and *dpi*. *figsize* is the ``(width, height)`` |
| 135 | +of the Figure in inches (or, if preferred, units of 72 typographic points). *dpi* |
| 136 | +are how many pixels per inch the figure will be rendered at. To make your Figures |
| 137 | +appear on the screen at the physical size you requested, you should set *dpi* |
| 138 | +to the same *dpi* as your graphics system. Note that many graphics systems now use |
| 139 | +a "dpi ratio" to specify how many screen pixels are used to represent a graphics |
| 140 | +pixel. Matplotlib applies the dpi ratio to the *dpi* passed to the figure to make |
| 141 | +it have higher resolution, so you should pass the lower number to the figure. |
| 142 | + |
| 143 | +The *facecolor*, *edgecolor*, *linewidth*, and *frameon* options all change the appearance of the |
| 144 | +figure in expected ways, with *frameon* making the figure transparent if set to *False*. |
| 145 | + |
| 146 | +Finally, the user can specify a layout engine for the figure with the *layout* |
| 147 | +parameter. Currently Matplotlib supplies |
| 148 | +:doc:`"constrained" </tutorials/intermediate/constrainedlayout_guide>`, |
| 149 | +:ref:`"compressed" <compressed_layout>` and |
| 150 | +:doc:`"tight" </tutorials/intermediate/tight_layout_guide>` layout engines. These |
| 151 | +rescale axes inside the Figure to prevent overlap of ticklabels, and try and align |
| 152 | +axes, and can save significant manual adjustment of artists on a Figure for many |
| 153 | +common cases. |
| 154 | + |
| 155 | +Adding Artists |
| 156 | +-------------- |
| 157 | + |
| 158 | +The `~.FigureBase` class has a number of methods to add artists to a `~.Figure` or |
| 159 | +a `~.SubFigure`. By far the most common are to add Axes of various configurations |
| 160 | +(`~.FigureBase.add_axes`, `~.FigureBase.add_subplot`, `~.FigureBase.subplots`, |
| 161 | +`~.FigureBase.subplot_mosaic`) and subfigures (`~.FigureBase.subfigures`). Colorbars |
| 162 | +are added to Axes or group of Axes at the Figure level (`~.FigureBase.colorbar`). |
| 163 | +It is also possible to have a Figure-level legend (`~.FigureBase.legend`). |
| 164 | +Other Artists include figure-wide labels (`~.FigureBase.suptitle`, |
| 165 | +`~.FigureBase.supxlabel`, `~.FigureBase.supylabel`) and text (`~.FigureBase.text`). |
| 166 | +Finally, low-level Artists can be added directly using `~.FigureBase.add_artist` |
| 167 | +usually with care being taken to use the appropriate transform. Usually these |
| 168 | +include ``Figure.transFigure`` which ranges from 0 to 1 in each direction, and |
| 169 | +represents the fraction of the current Figure size, or ``Figure.dpi_scale_trans`` |
| 170 | +which will be in physical units of inches from the bottom left corner of the Figure |
| 171 | +(see :doc:`/tutorials/advanced/transforms_tutorial` for more details). |
| 172 | + |
| 173 | + |
| 174 | +.. _saving_figures: |
| 175 | + |
| 176 | +Saving Figures |
| 177 | +============== |
| 178 | + |
| 179 | +Finally, Figures can be saved to disk using the `~.Figure.savefig` method. |
| 180 | +``fig.savefig('MyFigure.png', dpi=200)`` will save a PNG formatted figure to |
| 181 | +the file ``MyFigure.png`` in the current directory on disk with 200 dots-per-inch |
| 182 | +resolution. Note that the filename can include a relative or absolute path to |
| 183 | +any place on the file system. |
| 184 | + |
| 185 | +Many types of output are supported, including raster formats like PNG, GIF, JPEG, |
| 186 | +TIFF and vector formats like PDF, EPS, and SVG. |
| 187 | + |
| 188 | +By default, the size of the saved Figure is set by the Figure size (in inches) and, for the raster |
| 189 | +formats, the *dpi*. If *dpi* is not set, then the *dpi* of the Figure is used. |
| 190 | +Note that *dpi* still has meaning for vector formats like PDF if the Figure includes |
| 191 | +Artists that have been :doc:`rasterized </gallery/misc/rasterization_demo>`; the |
| 192 | +*dpi* specified will be the resolution of the rasterized objects. |
| 193 | + |
| 194 | +It is possible to change the size of the Figure using the *bbox_inches* argument |
| 195 | +to savefig. This can be specified manually, again in inches. However, by far |
| 196 | +the most common use is ``bbox_inches='tight'``. This option "shrink-wraps", trimming |
| 197 | +or expanding as needed, the size of the figure so that it is tight around all the artists |
| 198 | +in a figure, with a small pad that can be specified by *pad_inches*, which defaults to |
| 199 | +0.1 inches. The dashed box in the plot below shows the portion of the figure that |
| 200 | +would be saved if ``bbox_inches='tight'`` were used in savefig. |
| 201 | + |
| 202 | +.. plot:: |
| 203 | + |
| 204 | + import matplotlib.pyplot as plt |
| 205 | + from matplotlib.patches import FancyBboxPatch |
| 206 | + |
| 207 | + fig, ax = plt.subplots(figsize=(4, 2), facecolor='lightskyblue') |
| 208 | + ax.set_position([0.1, 0.2, 0.8, 0.7]) |
| 209 | + ax.set_aspect(1) |
| 210 | + bb = ax.get_tightbbox() |
| 211 | + bb = bb.padded(10) |
| 212 | + fancy = FancyBboxPatch(bb.p0, bb.width, bb.height, fc='none', |
| 213 | + ec=(0, 0.0, 0, 0.5), lw=2, linestyle='--', |
| 214 | + transform=None, clip_on=False) |
| 215 | + ax.add_patch(fancy) |
0 commit comments