From 9ec640760780c26cd2794f5039cb0fb51a6c501e Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Sun, 11 Jun 2023 18:06:02 -0700 Subject: [PATCH] DOC: fix levels in user/explain/figure Co-authored-by: Ruth Comer <10599679+rcomer@users.noreply.github.com> --- .../users_explain/artists/artist_intro.rst | 187 ++++++++++++ galleries/users_explain/artists/index.rst | 198 +------------ galleries/users_explain/axes/axes_intro.rst | 180 ++++++++++++ galleries/users_explain/axes/index.rst | 171 +---------- .../users_explain/figure/figure_intro.rst | 257 +++++++++++++++++ galleries/users_explain/figure/index.rst | 270 ++---------------- 6 files changed, 664 insertions(+), 599 deletions(-) create mode 100644 galleries/users_explain/artists/artist_intro.rst create mode 100644 galleries/users_explain/axes/axes_intro.rst create mode 100644 galleries/users_explain/figure/figure_intro.rst diff --git a/galleries/users_explain/artists/artist_intro.rst b/galleries/users_explain/artists/artist_intro.rst new file mode 100644 index 000000000000..5f82c972ca00 --- /dev/null +++ b/galleries/users_explain/artists/artist_intro.rst @@ -0,0 +1,187 @@ +.. _users_artists: + +Introduction to Artists +----------------------- + +Almost all objects you interact with on a Matplotlib plot are called "Artist" +(and are subclasses of the `.Artist` class). :doc:`Figure <../figure/index>` +and :doc:`Axes <../axes/index>` are Artists, and generally contain :doc:`Axis +<../axis/index>` Artists and Artists that contain data or annotation +information. + + +Creating Artists +~~~~~~~~~~~~~~~~ + +Usually we do not instantiate Artists directly, but rather use a plotting +method on `~.axes.Axes`. Some examples of plotting methods and the Artist +object they create is given below: + +========================================= ================= +Axes helper method Artist +========================================= ================= +`~.axes.Axes.annotate` - text annotations `.Annotation` +`~.axes.Axes.bar` - bar charts `.Rectangle` +`~.axes.Axes.errorbar` - error bar plots `.Line2D` and + `.Rectangle` +`~.axes.Axes.fill` - shared area `.Polygon` +`~.axes.Axes.hist` - histograms `.Rectangle` +`~.axes.Axes.imshow` - image data `.AxesImage` +`~.axes.Axes.legend` - Axes legend `.Legend` +`~.axes.Axes.plot` - xy plots `.Line2D` +`~.axes.Axes.scatter` - scatter charts `.PolyCollection` +`~.axes.Axes.text` - text `.Text` +========================================= ================= + +As an example, we can save the Line2D Artist returned from `.axes.Axes.plot`: + +.. sourcecode:: ipython + + In [209]: import matplotlib.pyplot as plt + In [210]: import matplotlib.artist as martist + In [211]: import numpy as np + + In [212]: fig, ax = plt.subplots() + In [213]: x, y = np.random.rand(2, 100) + In [214]: lines = ax.plot(x, y, '-', label='example') + In [215]: print(lines) + [] + +Note that ``plot`` returns a _list_ of lines because you can pass in multiple x, +y pairs to plot. The line has been added to the Axes, and we can retrieve the +Artist via `~.Axes.get_lines()`: + +.. sourcecode:: ipython + + In [216]: print(ax.get_lines()) + + In [217]: print(ax.get_lines()[0]) + Line2D(example) + +Changing Artist properties +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Getting the ``lines`` object gives us access to all the properties of the +Line2D object. So if we want to change the *linewidth* after the fact, we can do so using `.Artist.set`. + +.. plot:: + :include-source: + + fig, ax = plt.subplots(figsize=(4, 2.5)) + x = np.arange(0, 13, 0.2) + y = np.sin(x) + lines = ax.plot(x, y, '-', label='example', linewidth=0.2, color='blue') + lines[0].set(color='green', linewidth=2) + +We can interrogate the full list of settable properties with +`matplotlib.artist.getp`: + +.. sourcecode:: ipython + + In [218]: martist.getp(lines[0]) + agg_filter = None + alpha = None + animated = False + antialiased or aa = True + bbox = Bbox(x0=0.004013842290585101, y0=0.013914221641967... + children = [] + clip_box = TransformedBbox( Bbox(x0=0.0, y0=0.0, x1=1.0, ... + clip_on = True + clip_path = None + color or c = blue + dash_capstyle = butt + dash_joinstyle = round + data = (array([0.91377845, 0.58456834, 0.36492019, 0.0379... + drawstyle or ds = default + figure = Figure(550x450) + fillstyle = full + gapcolor = None + gid = None + in_layout = True + label = example + linestyle or ls = - + linewidth or lw = 2.0 + marker = None + markeredgecolor or mec = blue + markeredgewidth or mew = 1.0 + markerfacecolor or mfc = blue + markerfacecoloralt or mfcalt = none + markersize or ms = 6.0 + markevery = None + mouseover = False + path = Path(array([[0.91377845, 0.51224793], [0.58... + path_effects = [] + picker = None + pickradius = 5 + rasterized = False + sketch_params = None + snap = None + solid_capstyle = projecting + solid_joinstyle = round + tightbbox = Bbox(x0=70.4609002763619, y0=54.321277798941786, x... + transform = CompositeGenericTransform( TransformWrapper( ... + transformed_clip_path_and_affine = (None, None) + url = None + visible = True + window_extent = Bbox(x0=70.4609002763619, y0=54.321277798941786, x... + xdata = [0.91377845 0.58456834 0.36492019 0.03796664 0.884... + xydata = [[0.91377845 0.51224793] [0.58456834 0.9820474 ] ... + ydata = [0.51224793 0.9820474 0.24469912 0.61647032 0.483... + zorder = 2 + +Note most Artists also have a distinct list of setters; e.g. +`.Line2D.set_color` or `.Line2D.set_linewidth`. + +Changing Artist data +~~~~~~~~~~~~~~~~~~~~ + +In addition to styling properties like *color* and *linewidth*, the Line2D +object has a *data* property. You can set the data after the line has been +created using `.Line2D.set_data`. This is often used for Animations, where the +same line is shown evolving over time (see :doc:`../animations/index`) + +.. plot:: + :include-source: + + fig, ax = plt.subplots(figsize=(4, 2.5)) + x = np.arange(0, 13, 0.2) + y = np.sin(x) + lines = ax.plot(x, y, '-', label='example') + lines[0].set_data([x, np.cos(x)]) + +Manually adding Artists +~~~~~~~~~~~~~~~~~~~~~~~ + +Not all Artists have helper methods, or you may want to use a low-level method +for some reason. For example the `.patches.Circle` Artist does not have a +helper, but we can still create and add to an Axes using the +`.axes.Axes.add_artist` method: + +.. plot:: + :include-source: + + import matplotlib.patches as mpatches + + fig, ax = plt.subplots(figsize=(4, 2.5)) + circle = mpatches.Circle((0.5, 0.5), 0.25, ec="none") + ax.add_artist(circle) + clipped_circle = mpatches.Circle((1, 0.5), 0.125, ec="none", facecolor='C1') + ax.add_artist(clipped_circle) + ax.set_aspect(1) + +The Circle takes the center and radius of the Circle as arguments to its +constructor; optional arguments are passed as keyword arguments. + +Note that when we add an Artist manually like this, it doesn't necessarily +adjust the axis limits like most of the helper methods do, so the Artists can +be clipped, as is the case above for the ``clipped_circle`` patch. + +See :ref:`artist_reference` for other patches. + +Removing Artists +~~~~~~~~~~~~~~~~ + +Sometimes we want to remove an Artist from a figure without re-specifying the +whole figure from scratch. Most Artists have a usable *remove* method that +will remove the Artist from its Axes list. For instance ``lines[0].remove()`` +would remove the *Line2D* artist created in the example above. diff --git a/galleries/users_explain/artists/index.rst b/galleries/users_explain/artists/index.rst index 1b5e248d1ea7..26164d51f3a3 100644 --- a/galleries/users_explain/artists/index.rst +++ b/galleries/users_explain/artists/index.rst @@ -1,7 +1,6 @@ -.. _users_artists: - -Using Artists -------------- ++++++++ +Artists ++++++++ Almost all objects you interact with on a Matplotlib plot are called "Artist" (and are subclasses of the `.Artist` class). :doc:`Figure <../figure/index>` @@ -9,192 +8,17 @@ and :doc:`Axes <../axes/index>` are Artists, and generally contain :doc:`Axis <../axis/index>` Artists and Artists that contain data or annotation information. +.. toctree:: + :maxdepth: 2 -Creating Artists -~~~~~~~~~~~~~~~~ - -Usually we do not instantiate Artists directly, but rather use a plotting -method on `~.axes.Axes`. Some examples of plotting methods and the Artist -object they create is given below: - -========================================= ================= -Axes helper method Artist -========================================= ================= -`~.axes.Axes.annotate` - text annotations `.Annotation` -`~.axes.Axes.bar` - bar charts `.Rectangle` -`~.axes.Axes.errorbar` - error bar plots `.Line2D` and - `.Rectangle` -`~.axes.Axes.fill` - shared area `.Polygon` -`~.axes.Axes.hist` - histograms `.Rectangle` -`~.axes.Axes.imshow` - image data `.AxesImage` -`~.axes.Axes.legend` - Axes legend `.Legend` -`~.axes.Axes.plot` - xy plots `.Line2D` -`~.axes.Axes.scatter` - scatter charts `.PolyCollection` -`~.axes.Axes.text` - text `.Text` -========================================= ================= - -As an example, we can save the Line2D Artist returned from `.axes.Axes.plot`: - -.. sourcecode:: ipython - - In [209]: import matplotlib.pyplot as plt - In [210]: import matplotlib.artist as martist - In [211]: import numpy as np - - In [212]: fig, ax = plt.subplots() - In [213]: x, y = np.random.rand(2, 100) - In [214]: lines = ax.plot(x, y, '-', label='example') - In [215]: print(lines) - [] - -Note that ``plot`` returns a _list_ of lines because you can pass in multiple x, -y pairs to plot. The line has been added to the Axes, and we can retrieve the -Artist via `~.Axes.get_lines()`: - -.. sourcecode:: ipython - - In [216]: print(ax.get_lines()) - - In [217]: print(ax.get_lines()[0]) - Line2D(example) - -Changing Artist properties -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Getting the ``lines`` object gives us access to all the properties of the -Line2D object. So if we want to change the *linewidth* after the fact, we can do so using `.Artist.set`. - -.. plot:: - :include-source: - - fig, ax = plt.subplots(figsize=(4, 2.5)) - x = np.arange(0, 13, 0.2) - y = np.sin(x) - lines = ax.plot(x, y, '-', label='example', linewidth=0.2, color='blue') - lines[0].set(color='green', linewidth=2) - -We can interrogate the full list of settable properties with -`matplotlib.artist.getp`: - -.. sourcecode:: ipython - - In [218]: martist.getp(lines[0]) - agg_filter = None - alpha = None - animated = False - antialiased or aa = True - bbox = Bbox(x0=0.004013842290585101, y0=0.013914221641967... - children = [] - clip_box = TransformedBbox( Bbox(x0=0.0, y0=0.0, x1=1.0, ... - clip_on = True - clip_path = None - color or c = blue - dash_capstyle = butt - dash_joinstyle = round - data = (array([0.91377845, 0.58456834, 0.36492019, 0.0379... - drawstyle or ds = default - figure = Figure(550x450) - fillstyle = full - gapcolor = None - gid = None - in_layout = True - label = example - linestyle or ls = - - linewidth or lw = 2.0 - marker = None - markeredgecolor or mec = blue - markeredgewidth or mew = 1.0 - markerfacecolor or mfc = blue - markerfacecoloralt or mfcalt = none - markersize or ms = 6.0 - markevery = None - mouseover = False - path = Path(array([[0.91377845, 0.51224793], [0.58... - path_effects = [] - picker = None - pickradius = 5 - rasterized = False - sketch_params = None - snap = None - solid_capstyle = projecting - solid_joinstyle = round - tightbbox = Bbox(x0=70.4609002763619, y0=54.321277798941786, x... - transform = CompositeGenericTransform( TransformWrapper( ... - transformed_clip_path_and_affine = (None, None) - url = None - visible = True - window_extent = Bbox(x0=70.4609002763619, y0=54.321277798941786, x... - xdata = [0.91377845 0.58456834 0.36492019 0.03796664 0.884... - xydata = [[0.91377845 0.51224793] [0.58456834 0.9820474 ] ... - ydata = [0.51224793 0.9820474 0.24469912 0.61647032 0.483... - zorder = 2 - -Note most Artists also have a distinct list of setters; e.g. -`.Line2D.set_color` or `.Line2D.set_linewidth`. - -Changing Artist data -~~~~~~~~~~~~~~~~~~~~ - -In addition to styling properties like *color* and *linewidth*, the Line2D -object has a *data* property. You can set the data after the line has been -created using `.Line2D.set_data`. This is often used for Animations, where the -same line is shown evolving over time (see :doc:`../animations/index`) - -.. plot:: - :include-source: - - fig, ax = plt.subplots(figsize=(4, 2.5)) - x = np.arange(0, 13, 0.2) - y = np.sin(x) - lines = ax.plot(x, y, '-', label='example') - lines[0].set_data([x, np.cos(x)]) - -Manually adding Artists -~~~~~~~~~~~~~~~~~~~~~~~ - -Not all Artists have helper methods, or you may want to use a low-level method -for some reason. For example the `.patches.Circle` Artist does not have a -helper, but we can still create and add to an Axes using the -`.axes.Axes.add_artist` method: - -.. plot:: - :include-source: - - import matplotlib.patches as mpatches - - fig, ax = plt.subplots(figsize=(4, 2.5)) - circle = mpatches.Circle((0.5, 0.5), 0.25, ec="none") - ax.add_artist(circle) - clipped_circle = mpatches.Circle((1, 0.5), 0.125, ec="none", facecolor='C1') - ax.add_artist(clipped_circle) - ax.set_aspect(1) - -The Circle takes the center and radius of the Circle as arguments to its -constructor; optional arguments are passed as keyword arguments. - -Note that when we add an Artist manually like this, it doesn't necessarily -adjust the axis limits like most of the helper methods do, so the Artists can -be clipped, as is the case above for the ``clipped_circle`` patch. - -See :ref:`artist_reference` for other patches. - -Removing Artists -~~~~~~~~~~~~~~~~ - -Sometimes we want to remove an Artist from a figure without re-specifying the -whole figure from scratch. Most Artists have a usable *remove* method that -will remove the Artist from its Axes list. For instance ``lines[0].remove()`` -would remove the *Line2D* artist created in the example above. - -More details -~~~~~~~~~~~~ + artist_intro .. toctree:: :maxdepth: 1 - Concept: Automated color cycle - Concept: optimizing Artists for performance - Concept: Paths - Concept: Path effects guide - In Depth: understanding the extent keyword argument of imshow + Automated color cycle + Optimizing Artists for performance + Paths + Path effects guide + Understanding the extent keyword argument of imshow transforms_tutorial diff --git a/galleries/users_explain/axes/axes_intro.rst b/galleries/users_explain/axes/axes_intro.rst new file mode 100644 index 000000000000..17f9059b80af --- /dev/null +++ b/galleries/users_explain/axes/axes_intro.rst @@ -0,0 +1,180 @@ +################################## +Introduction to Axes (or Subplots) +################################## + + +Matplotlib `~.axes.Axes` are the gateway to creating your data visualizations. +Once an Axes is placed on a figure there are many methods that can be used to +add data to the Axes. An Axes typically has a pair of :doc:`Axis <../axis/index>` +Artists that define the data coordinate system, and include methods to add +annotations like x- and y-labels, titles, and legends. + +.. _anatomy_local: + +.. figure:: /_static/anatomy.png + :width: 80% + + Anatomy of a Figure + +In the picture above, the Axes object was created with ``ax = fig.subplots()``. +Everything else on the figure was created with methods on this ``ax`` object, +or can be accessed from it. If we want to change the label on the x-axis, we +call ``ax.set_xlabel('New Label')``, if we want to plot some data we call +``ax.plot(x, y)``. Indeed, in the figure above, the only Artist that is not +part of the Axes is the Figure itself, so the `.axes.Axes` class is really the +gateway to much of Matplotlib's functionality. + +Note that Axes are so fundamental to the operation of Matplotlib that a lot of +material here is duplicate of that in :ref:`quick_start`. + +Creating Axes +------------- + +.. plot:: + :include-source: + + import matplotlib.pyplot as plt + import numpy as np + + fig, axs = plt.subplots(ncols=2, nrows=2, figsize=(3.5, 2.5), + layout="constrained") + # for each Axes, add an artist, in this case a nice label in the middle... + for row in range(2): + for col in range(2): + axs[row, col].annotate(f'axs[{row}, {col}]', (0.5, 0.5), + transform=axs[row, col].transAxes, + ha='center', va='center', fontsize=18, + color='darkgrey') + fig.suptitle('plt.subplots()') + + +Axes are added using methods on `~.Figure` objects, or via the `~.pyplot` interface. These methods are discussed in more detail in :ref:`creating_figures` and :doc:`arranging_axes`. However, for instance `~.Figure.add_axes` will manually position an Axes on the page. In the example above `~.pyplot.subplots` put a grid of subplots on the figure, and ``axs`` is a (2, 2) array of Axes, each of which can have data added to them. + +There are a number of other methods for adding Axes to a Figure: + +* `.Figure.add_axes`: manually position an Axes. ``fig.add_axes([0, 0, 1, + 1])`` makes an Axes that fills the whole figure. +* `.pyplot.subplots` and `.Figure.subplots`: add a grid of Axes as in the example + above. The pyplot version returns both the Figure object and an array of + Axes. Note that ``fig, ax = plt.subplots()`` adds a single Axes to a Figure. +* `.pyplot.subplot_mosaic` and `.Figure.subplot_mosaic`: add a grid of named + Axes and return a dictionary of axes. For ``fig, axs = + plt.subplot_mosaic([['left', 'right'], ['bottom', 'bottom']])``, + ``axs['left']`` is an Axes in the top row on the left, and ``axs['bottom']`` + is an Axes that spans both columns on the bottom. + +See :doc:`arranging_axes` for more detail on how to arrange grids of Axes on a +Figure. + + +Axes plotting methods +--------------------- + +Most of the high-level plotting methods are accessed from the `.axes.Axes` +class. See the API documentation for a full curated list, and +:ref:`plot_types` for examples. A basic example is `.axes.Axes.plot`: + +.. plot:: + :include-source: + + fig, ax = plt.subplots(figsize=(4, 3)) + np.random.seed(19680801) + t = np.arange(100) + x = np.cumsum(np.random.randn(100)) + lines = ax.plot(t, x) + +Note that ``plot`` returns a list of *lines* Artists which can subsequently be +manipulated, as discussed in :ref:`users_artists`. + +A very incomplete list of plotting methods is below. Again, see :ref:`plot_types` +for more examples, and `.axes.Axes` for the full list of methods. + +========================= ================================================== +:ref:`basic_plots` `~.axes.Axes.plot`, `~.axes.Axes.scatter`, + `~.axes.Axes.bar`, `~.axes.Axes.step`, +:ref:`arrays` `~.axes.Axes.pcolormesh`, `~.axes.Axes.contour`, + `~.axes.Axes.quiver`, `~.axes.Axes.streamplot`, + `~.axes.Axes.imshow` +:ref:`stats_plots` `~.axes.Axes.hist`, `~.axes.Axes.errorbar`, + `~.axes.Axes.hist2d`, `~.axes.Axes.pie`, + `~.axes.Axes.boxplot`, `~.axes.Axes.violinplot` +:ref:`unstructured_plots` `~.axes.Axes.tricontour`, `~.axes.Axes.tripcolor` +========================= ================================================== + +Axes labelling and annotation +----------------------------- + +Usually we want to label the Axes with an xlabel, ylabel, and title, and often we want to have a legend to differentiate plot elements. The `~.axes.Axes` class has a number of methods to create these annotations. + +.. plot:: + :include-source: + + fig, ax = plt.subplots(figsize=(5, 3), layout='constrained') + np.random.seed(19680801) + t = np.arange(200) + x = np.cumsum(np.random.randn(200)) + y = np.cumsum(np.random.randn(200)) + linesx = ax.plot(t, x, label='Random walk x') + linesy = ax.plot(t, y, label='Random walk y') + + ax.set_xlabel('Time [s]') + ax.set_ylabel('Distance [km]') + ax.set_title('Random walk example') + ax.legend() + +These methods are relatively straight-forward, though there are a number of :ref:`text_props` that can be set on the text objects, like *fontsize*, *fontname*, *horizontalalignment*. Legends can be much more complicated; see :ref:`legend_guide` for more details. + +Note that text can also be added to axes using `~.axes.Axes.text`, and `~.axes.Axes.annotate`. This can be quite sophisticated: see :ref:`text_props` and :ref:`annotations` for more information. + + +Axes limits, scales, and ticking +-------------------------------- + +Each Axes has two (or more) `~.axis.Axis` objects, that can be accessed via :attr:`~matplotlib.axes.Axes.xaxis` and :attr:`~matplotlib.axes.Axes.yaxis` properties. These have substantial number of methods on them, and for highly customizable Axis-es it is useful to read more about that API (:doc:`../axis/index`). However, the Axes class offers a number of helpers for the most common of these methods. Indeed, the `~.axes.Axes.set_xlabel`, discussed above, is a helper for the `~.Axis.set_label_text`. + +Other important methods set the extent on the axes (`~.axes.Axes.set_xlim`, `~.axes.Axes.set_ylim`), or more fundamentally the scale of the axes. So for instance, we can make an Axis have a logarithmic scale, and zoom in on a sub-portion of the data: + +.. plot:: + :include-source: + + fig, ax = plt.subplots(figsize=(4, 2.5), layout='constrained') + np.random.seed(19680801) + t = np.arange(200) + x = 2**np.cumsum(np.random.randn(200)) + linesx = ax.plot(t, x) + ax.set_yscale('log') + ax.set_xlim([20, 180]) + +The Axes class also has helpers to deal with Axis ticks and their labels. Most straight-forward is `~.axes.Axes.set_xticks` and `~.axes.Axes.set_yticks` which manually set the tick locations and optionally their labels. Minor ticks can be toggled with `~.axes.Axes.minorticks_on` or `~.axes.Axes.minorticks_off`. + +Many aspects of Axes ticks and tick labeling can be adjusted using `~.axes.Axes.tick_params`. For instance, to label the top of the axes instead of the bottom,color the ticks red, and color the ticklabels green: + +.. plot:: + :include-source: + + fig, ax = plt.subplots(figsize=(4, 2.5)) + ax.plot(np.arange(10)) + ax.tick_params(top=True, labeltop=True, color='red', axis='x', + labelcolor='green') + + +More fine-grained control on ticks, setting scales, and controlling the Axis can be highly customized beyond these Axes-level helpers. An introduction to these methods can be found in :ref:`users_axis`, or the API reference for `.axis.Axis`. + +Axes layout +----------- + +Sometimes it is important to set the aspect ratio of a plot in data space, which we can do with `~.axes.Axes.set_aspect`: + +.. plot:: + :include-source: + + fig, axs = plt.subplots(ncols=2, figsize=(7, 2.5), layout='constrained') + np.random.seed(19680801) + t = np.arange(200) + x = np.cumsum(np.random.randn(200)) + axs[0].plot(t, x) + axs[0].set_title('aspect="auto"') + + axs[1].plot(t, x) + axs[1].set_aspect(3) + axs[1].set_title('aspect=3') diff --git a/galleries/users_explain/axes/index.rst b/galleries/users_explain/axes/index.rst index 8bcf51add979..a4df627c0671 100644 --- a/galleries/users_explain/axes/index.rst +++ b/galleries/users_explain/axes/index.rst @@ -1,7 +1,6 @@ -################## -Axes (or Subplots) -################## - ++++++++++++++++++ +Axes and subplots ++++++++++++++++++ Matplotlib `~.axes.Axes` are the gateway to creating your data visualizations. Once an Axes is placed on a figure there are many methods that can be used to @@ -9,29 +8,7 @@ add data to the Axes. An Axes typically has a pair of :doc:`Axis <../axis/index> Artists that define the data coordinate system, and include methods to add annotations like x- and y-labels, titles, and legends. -.. _anatomy_local: - -.. figure:: /_static/anatomy.png - :width: 80% - - Anatomy of a Figure - -In the picture above, the Axes object was created with ``ax = fig.subplots()``. -Everything else on the figure was created with methods on this ``ax`` object, -or can be accessed from it. If we want to change the label on the x-axis, we -call ``ax.set_xlabel('New Label')``, if we want to plot some data we call -``ax.plot(x, y)``. Indeed, in the figure above, the only Artist that is not -part of the Axes is the Figure itself, so the `.axes.Axes` class is really the -gateway to much of Matplotlib's functionality. - -Note that Axes are so fundamental to the operation of Matplotlib that a lot of -material here is duplicate of that in :ref:`quick_start`. - -Creating Axes -------------- - .. plot:: - :include-source: import matplotlib.pyplot as plt import numpy as np @@ -48,144 +25,18 @@ Creating Axes fig.suptitle('plt.subplots()') -Axes are added using methods on `~.Figure` objects, or via the `~.pyplot` interface. These methods are discussed in more detail in :ref:`creating_figures` and :doc:`arranging_axes`. However, for instance `~.Figure.add_axes` will manually position an Axes on the page. In the example above `~.pyplot.subplots` put a grid of subplots on the figure, and ``axs`` is a (2, 2) array of Axes, each of which can have data added to them. - -There are a number of other methods for adding Axes to a Figure: - -* `.Figure.add_axes`: manually position an Axes. ``fig.add_axes([0, 0, 1, - 1])`` makes an Axes that fills the whole figure. -* `.pyplot.subplots` and `.Figure.subplots`: add a grid of Axes as in the example - above. The pyplot version returns both the Figure object and an array of - Axes. Note that ``fig, ax = plt.subplots()`` adds a single Axes to a Figure. -* `.pyplot.subplot_mosaic` and `.Figure.subplot_mosaic`: add a grid of named - Axes and return a dictionary of axes. For ``fig, axs = - plt.subplot_mosaic([['left', 'right'], ['bottom', 'bottom']])``, - ``axs['left']`` is an Axes in the top row on the left, and ``axs['bottom']`` - is an Axes that spans both columns on the bottom. - -See :doc:`arranging_axes` for more detail on how to arrange grids of Axes on a -Figure. - - -Axes plotting methods ---------------------- - -Most of the high-level plotting methods are accessed from the `.axes.Axes` -class. See the API documentation for a full curated list, and -:ref:`plot_types` for examples. A basic example is `.axes.Axes.plot`: - -.. plot:: - :include-source: - - fig, ax = plt.subplots(figsize=(4, 3)) - np.random.seed(19680801) - t = np.arange(100) - x = np.cumsum(np.random.randn(100)) - lines = ax.plot(t, x) - -Note that ``plot`` returns a list of *lines* Artists which can subsequently be -manipulated, as discussed in :ref:`users_artists`. - -A very incomplete list of plotting methods is below. Again, see :ref:`plot_types` -for more examples, and `.axes.Axes` for the full list of methods. - -========================= ================================================== -:ref:`basic_plots` `~.axes.Axes.plot`, `~.axes.Axes.scatter`, - `~.axes.Axes.bar`, `~.axes.Axes.step`, -:ref:`arrays` `~.axes.Axes.pcolormesh`, `~.axes.Axes.contour`, - `~.axes.Axes.quiver`, `~.axes.Axes.streamplot`, - `~.axes.Axes.imshow` -:ref:`stats_plots` `~.axes.Axes.hist`, `~.axes.Axes.errorbar`, - `~.axes.Axes.hist2d`, `~.axes.Axes.pie`, - `~.axes.Axes.boxplot`, `~.axes.Axes.violinplot` -:ref:`unstructured_plots` `~.axes.Axes.tricontour`, `~.axes.Axes.tripcolor` -========================= ================================================== - -Axes labelling and annotation ------------------------------ - -Usually we want to label the Axes with an xlabel, ylabel, and title, and often we want to have a legend to differentiate plot elements. The `~.axes.Axes` class has a number of methods to create these annotations. - -.. plot:: - :include-source: - - fig, ax = plt.subplots(figsize=(5, 3), layout='constrained') - np.random.seed(19680801) - t = np.arange(200) - x = np.cumsum(np.random.randn(200)) - y = np.cumsum(np.random.randn(200)) - linesx = ax.plot(t, x, label='Random walk x') - linesy = ax.plot(t, y, label='Random walk y') - - ax.set_xlabel('Time [s]') - ax.set_ylabel('Distance [km]') - ax.set_title('Random walk example') - ax.legend() - -These methods are relatively straight-forward, though there are a number of :ref:`text_props` that can be set on the text objects, like *fontsize*, *fontname*, *horizontalalignment*. Legends can be much more complicated; see :ref:`legend_guide` for more details. - -Note that text can also be added to axes using `~.axes.Axes.text`, and `~.axes.Axes.annotate`. This can be quite sophisticated: see :ref:`text_props` and :ref:`annotations` for more information. - - -Axes limits, scales, and ticking --------------------------------- - -Each Axes has two (or more) `~.axis.Axis` objects, that can be accessed via :attr:`~matplotlib.axes.Axes.xaxis` and :attr:`~matplotlib.axes.Axes.yaxis` properties. These have substantial number of methods on them, and for highly customizable Axis-es it is useful to read more about that API (:doc:`../axis/index`). However, the Axes class offers a number of helpers for the most common of these methods. Indeed, the `~.axes.Axes.set_xlabel`, discussed above, is a helper for the `~.Axis.set_label_text`. - -Other important methods set the extent on the axes (`~.axes.Axes.set_xlim`, `~.axes.Axes.set_ylim`), or more fundamentally the scale of the axes. So for instance, we can make an Axis have a logarithmic scale, and zoom in on a sub-portion of the data: - -.. plot:: - :include-source: - - fig, ax = plt.subplots(figsize=(4, 2.5), layout='constrained') - np.random.seed(19680801) - t = np.arange(200) - x = 2**np.cumsum(np.random.randn(200)) - linesx = ax.plot(t, x) - ax.set_yscale('log') - ax.set_xlim([20, 180]) - -The Axes class also has helpers to deal with Axis ticks and their labels. Most straight-forward is `~.axes.Axes.set_xticks` and `~.axes.Axes.set_yticks` which manually set the tick locations and optionally their labels. Minor ticks can be toggled with `~.axes.Axes.minorticks_on` or `~.axes.Axes.minorticks_off`. - -Many aspects of Axes ticks and tick labeling can be adjusted using `~.axes.Axes.tick_params`. For instance, to label the top of the axes instead of the bottom,color the ticks red, and color the ticklabels green: - -.. plot:: - :include-source: - - fig, ax = plt.subplots(figsize=(4, 2.5)) - ax.plot(np.arange(10)) - ax.tick_params(top=True, labeltop=True, color='red', axis='x', - labelcolor='green') - - -More fine-grained control on ticks, setting scales, and controlling the Axis can be highly customized beyond these Axes-level helpers. An introduction to these methods can be found in :ref:`users_axis`, or the API reference for `.axis.Axis`. - -Axes layout ------------ - -Sometimes it is important to set the aspect ratio of a plot in data space, which we can do with `~.axes.Axes.set_aspect`: - -.. plot:: - :include-source: - - fig, axs = plt.subplots(ncols=2, figsize=(7, 2.5), layout='constrained') - np.random.seed(19680801) - t = np.arange(200) - x = np.cumsum(np.random.randn(200)) - axs[0].plot(t, x) - axs[0].set_title('aspect="auto"') +.. toctree:: + :maxdepth: 2 - axs[1].plot(t, x) - axs[1].set_aspect(3) - axs[1].set_title('aspect=3') + axes_intro .. toctree:: :maxdepth: 1 arranging_axes colorbar_placement - In depth: Autoscaling axes - In depth: Legends - In depth: Subplot mosaic - In depth: Constrained layout guide - In depth: Tight layout guide (mildly discouraged) + Autoscaling axes + Legends + Subplot mosaic + Constrained layout guide + Tight layout guide (mildly discouraged) diff --git a/galleries/users_explain/figure/figure_intro.rst b/galleries/users_explain/figure/figure_intro.rst new file mode 100644 index 000000000000..9eda8acc92a1 --- /dev/null +++ b/galleries/users_explain/figure/figure_intro.rst @@ -0,0 +1,257 @@ + +.. redirect-from:: /users/explain/figure + +.. _figure_explanation: + ++++++++++++++++++++++++ +Introduction to Figures ++++++++++++++++++++++++ + +.. plot:: + :include-source: + + fig = plt.figure(figsize=(2, 2), facecolor='lightskyblue', + layout='constrained') + fig.suptitle('Figure') + ax = fig.add_subplot() + ax.set_title('Axes', loc='left', fontstyle='oblique', fontsize='medium') + +When looking at Matplotlib visualization, you are almost always looking at +Artists placed on a `~.Figure`. In the example above, the figure is the +blue region and `~.Figure.add_subplot` has added an `~.axes.Axes` artist to the +`~.Figure` (see :ref:`figure_parts`). A more complicated visualization can add +multiple Axes to the Figure, colorbars, legends, annotations, and the Axes +themselves can have multiple Artists added to them +(e.g. ``ax.plot`` or ``ax.imshow``). + +.. contents:: :local: + + +.. _viewing_figures: + +Viewing Figures +================ + +We will discuss how to create Figures in more detail below, but first it is +helpful to understand how to view a Figure. This varies based on how you are +using Matplotlib, and what :ref:`Backend ` you are using. + +Notebooks and IDEs +------------------ + +.. figure:: /_static/FigureInline.png + :alt: Image of figure generated in Jupyter Notebook with inline backend. + :width: 400 + + Screenshot of a `Jupyter Notebook `_, with a figure + generated via the default `inline + `_ backend. + + +If you are using a Notebook (e.g. `Jupyter `_) or an IDE +that renders Notebooks (PyCharm, VSCode, etc), then they have a backend that +will render the Matplotlib Figure when a code cell is executed. One thing to +be aware of is that the default Jupyter backend (``%matplotlib inline``) will +by default trim or expand the figure size to have a tight box around Artists +added to the Figure (see :ref:`saving_figures`, below). If you use a backend +other than the default "inline" backend, you will likely need to use an ipython +"magic" like ``%matplotlib notebook`` for the Matplotlib :ref:`notebook +` or ``%matplotlib widget`` for the `ipympl +`_ backend. + +.. figure:: /_static/FigureNotebook.png + :alt: Image of figure generated in Jupyter Notebook with notebook + backend, including a toolbar. + :width: 400 + + Screenshot of a Jupyter Notebook with an interactive figure generated via + the ``%matplotlib notebook`` magic. Users should also try the similar + `widget `_ backend if using `JupyterLab + `_. + + +.. seealso:: + :ref:`interactive_figures`. + +Standalone scripts and interactive use +-------------------------------------- + +If the user is on a client with a windowing system, there are a number of +:ref:`Backends ` that can be used to render the Figure to +the screen, usually using a Python Qt, Tk, or Wx toolkit, or the native MacOS +backend. These are typically chosen either in the user's :ref:`matplotlibrc +`, or by calling, for example, +``matplotlib.use('QtAgg')`` at the beginning of a session or script. + +.. figure:: /_static/FigureQtAgg.png + :alt: Image of figure generated from a script via the QtAgg backend. + :width: 370 + + Screenshot of a Figure generated via a python script and shown using the + QtAgg backend. + +When run from a script, or interactively (e.g. from an +`iPython shell `_) the Figure +will not be shown until we call ``plt.show()``. The Figure will appear in +a new GUI window, and usually will have a toolbar with Zoom, Pan, and other tools +for interacting with the Figure. By default, ``plt.show()`` blocks +further interaction from the script or shell until the Figure window is closed, +though that can be toggled off for some purposes. For more details, please see +:ref:`controlling-interactive`. + +Note that if you are on a client that does not have access to a windowing +system, the Figure will fallback to being drawn using the "Agg" backend, and +cannot be viewed, though it can be :ref:`saved `. + +.. seealso:: + :ref:`interactive_figures`. + +.. _creating_figures: + +Creating Figures +================ + +By far the most common way to create a figure is using the +:ref:`pyplot ` interface. As noted in +:ref:`api_interfaces`, the pyplot interface serves two purposes. One is to spin +up the Backend and keep track of GUI windows. The other is a global state for +Axes and Artists that allow a short-form API to plotting methods. In the +example above, we use pyplot for the first purpose, and create the Figure object, +``fig``. As a side effect ``fig`` is also added to pyplot's global state, and +can be accessed via `~.pyplot.gcf`. + +Users typically want an Axes or a grid of Axes when they create a Figure, so in +addition to `~.pyplot.figure`, there are convenience methods that return both +a Figure and some Axes. A simple grid of Axes can be achieved with +`.pyplot.subplots` (which +simply wraps `.Figure.subplots`): + +.. plot:: + :include-source: + + fig, axs = plt.subplots(2, 2, figsize=(4, 3), layout='constrained') + +More complex grids can be achieved with `.pyplot.subplot_mosaic` (which wraps +`.Figure.subplot_mosaic`): + +.. plot:: + :include-source: + + fig, axs = plt.subplot_mosaic([['A', 'right'], ['B', 'right']], + figsize=(4, 3), layout='constrained') + for ax_name in axs: + axs[ax_name].text(0.5, 0.5, ax_name, ha='center', va='center') + +Sometimes we want to have a nested layout in a Figure, with two or more sets of +Axes that do not share the same subplot grid. +We can use `~.Figure.add_subfigure` or `~.Figure.subfigures` to create virtual +figures inside a parent Figure; see +:doc:`/gallery/subplots_axes_and_figures/subfigures` for more details. + +.. plot:: + :include-source: + + fig = plt.figure(layout='constrained', facecolor='lightskyblue') + fig.suptitle('Figure') + figL, figR = fig.subfigures(1, 2) + figL.set_facecolor('thistle') + axL = figL.subplots(2, 1, sharex=True) + axL[1].set_xlabel('x [m]') + figL.suptitle('Left subfigure') + figR.set_facecolor('paleturquoise') + axR = figR.subplots(1, 2, sharey=True) + axR[0].set_title('Axes 1') + figR.suptitle('Right subfigure') + +It is possible to directly instantiate a `.Figure` instance without using the +pyplot interface. This is usually only necessary if you want to create your +own GUI application or service that you do not want carrying the pyplot global +state. See the embedding examples in :ref:`user_interfaces` for examples of +how to do this. + +Figure options +-------------- + +There are a few options available when creating figures. The Figure size on +the screen is set by *figsize* and *dpi*. *figsize* is the ``(width, height)`` +of the Figure in inches (or, if preferred, units of 72 typographic points). *dpi* +are how many pixels per inch the figure will be rendered at. To make your Figures +appear on the screen at the physical size you requested, you should set *dpi* +to the same *dpi* as your graphics system. Note that many graphics systems now use +a "dpi ratio" to specify how many screen pixels are used to represent a graphics +pixel. Matplotlib applies the dpi ratio to the *dpi* passed to the figure to make +it have higher resolution, so you should pass the lower number to the figure. + +The *facecolor*, *edgecolor*, *linewidth*, and *frameon* options all change the appearance of the +figure in expected ways, with *frameon* making the figure transparent if set to *False*. + +Finally, the user can specify a layout engine for the figure with the *layout* +parameter. Currently Matplotlib supplies +:ref:`"constrained" `, +:ref:`"compressed" ` and +:ref:`"tight" ` layout engines. These +rescale axes inside the Figure to prevent overlap of ticklabels, and try and align +axes, and can save significant manual adjustment of artists on a Figure for many +common cases. + +Adding Artists +-------------- + +The `~.FigureBase` class has a number of methods to add artists to a `~.Figure` or +a `~.SubFigure`. By far the most common are to add Axes of various configurations +(`~.FigureBase.add_axes`, `~.FigureBase.add_subplot`, `~.FigureBase.subplots`, +`~.FigureBase.subplot_mosaic`) and subfigures (`~.FigureBase.subfigures`). Colorbars +are added to Axes or group of Axes at the Figure level (`~.FigureBase.colorbar`). +It is also possible to have a Figure-level legend (`~.FigureBase.legend`). +Other Artists include figure-wide labels (`~.FigureBase.suptitle`, +`~.FigureBase.supxlabel`, `~.FigureBase.supylabel`) and text (`~.FigureBase.text`). +Finally, low-level Artists can be added directly using `~.FigureBase.add_artist` +usually with care being taken to use the appropriate transform. Usually these +include ``Figure.transFigure`` which ranges from 0 to 1 in each direction, and +represents the fraction of the current Figure size, or ``Figure.dpi_scale_trans`` +which will be in physical units of inches from the bottom left corner of the Figure +(see :ref:`transforms_tutorial` for more details). + + +.. _saving_figures: + +Saving Figures +============== + +Finally, Figures can be saved to disk using the `~.Figure.savefig` method. +``fig.savefig('MyFigure.png', dpi=200)`` will save a PNG formatted figure to +the file ``MyFigure.png`` in the current directory on disk with 200 dots-per-inch +resolution. Note that the filename can include a relative or absolute path to +any place on the file system. + +Many types of output are supported, including raster formats like PNG, GIF, JPEG, +TIFF and vector formats like PDF, EPS, and SVG. + +By default, the size of the saved Figure is set by the Figure size (in inches) and, for the raster +formats, the *dpi*. If *dpi* is not set, then the *dpi* of the Figure is used. +Note that *dpi* still has meaning for vector formats like PDF if the Figure includes +Artists that have been :doc:`rasterized `; the +*dpi* specified will be the resolution of the rasterized objects. + +It is possible to change the size of the Figure using the *bbox_inches* argument +to savefig. This can be specified manually, again in inches. However, by far +the most common use is ``bbox_inches='tight'``. This option "shrink-wraps", trimming +or expanding as needed, the size of the figure so that it is tight around all the artists +in a figure, with a small pad that can be specified by *pad_inches*, which defaults to +0.1 inches. The dashed box in the plot below shows the portion of the figure that +would be saved if ``bbox_inches='tight'`` were used in savefig. + +.. plot:: + + import matplotlib.pyplot as plt + from matplotlib.patches import FancyBboxPatch + + fig, ax = plt.subplots(figsize=(4, 2), facecolor='lightskyblue') + ax.set_position([0.1, 0.2, 0.8, 0.7]) + ax.set_aspect(1) + bb = ax.get_tightbbox() + bb = bb.padded(10) + fancy = FancyBboxPatch(bb.p0, bb.width, bb.height, fc='none', + ec=(0, 0.0, 0, 0.5), lw=2, linestyle='--', + transform=None, clip_on=False) + ax.add_patch(fancy) diff --git a/galleries/users_explain/figure/index.rst b/galleries/users_explain/figure/index.rst index 5e2ecc17d2c1..4433246e4074 100644 --- a/galleries/users_explain/figure/index.rst +++ b/galleries/users_explain/figure/index.rst @@ -1,270 +1,36 @@ - -.. redirect-from:: /users/explain/figure -.. _figure_explanation: - -+++++++++++++++++ -Figures -+++++++++++++++++ - -.. plot:: - :include-source: - - fig = plt.figure(figsize=(2, 2), facecolor='lightskyblue', - layout='constrained') - fig.suptitle('Figure') - ax = fig.add_subplot() - ax.set_title('Axes', loc='left', fontstyle='oblique', fontsize='medium') +++++++++++++++++++++ +Figures and backends +++++++++++++++++++++ When looking at Matplotlib visualization, you are almost always looking at -Artists placed on a `~.Figure`. In the example above, the figure is the +Artists placed on a `~.Figure`. In the example below, the figure is the blue region and `~.Figure.add_subplot` has added an `~.axes.Axes` artist to the `~.Figure` (see :ref:`figure_parts`). A more complicated visualization can add multiple Axes to the Figure, colorbars, legends, annotations, and the Axes themselves can have multiple Artists added to them (e.g. ``ax.plot`` or ``ax.imshow``). -.. contents:: :local: - - -.. _viewing_figures: - -Viewing Figures -================ - -We will discuss how to create Figures in more detail below, but first it is -helpful to understand how to view a Figure. This varies based on how you are -using Matplotlib, and what :ref:`Backend ` you are using. - -Notebooks and IDEs ------------------- - -.. figure:: /_static/FigureInline.png - :alt: Image of figure generated in Jupyter Notebook with inline backend. - :width: 400 - - Screenshot of a `Jupyter Notebook `_, with a figure - generated via the default `inline - `_ backend. - - -If you are using a Notebook (e.g. `Jupyter `_) or an IDE -that renders Notebooks (PyCharm, VSCode, etc), then they have a backend that -will render the Matplotlib Figure when a code cell is executed. One thing to -be aware of is that the default Jupyter backend (``%matplotlib inline``) will -by default trim or expand the figure size to have a tight box around Artists -added to the Figure (see :ref:`saving_figures`, below). If you use a backend -other than the default "inline" backend, you will likely need to use an ipython -"magic" like ``%matplotlib notebook`` for the Matplotlib :ref:`notebook -` or ``%matplotlib widget`` for the `ipympl -`_ backend. - -.. figure:: /_static/FigureNotebook.png - :alt: Image of figure generated in Jupyter Notebook with notebook - backend, including a toolbar. - :width: 400 - - Screenshot of a Jupyter Notebook with an interactive figure generated via - the ``%matplotlib notebook`` magic. Users should also try the similar - `widget `_ backend if using `JupyterLab - `_. - - -.. seealso:: - :ref:`interactive_figures`. - -Standalone scripts and interactive use --------------------------------------- - -If the user is on a client with a windowing system, there are a number of -:ref:`Backends ` that can be used to render the Figure to -the screen, usually using a Python Qt, Tk, or Wx toolkit, or the native MacOS -backend. These are typically chosen either in the user's :ref:`matplotlibrc -`, or by calling, for example, -``matplotlib.use('QtAgg')`` at the beginning of a session or script. - -.. figure:: /_static/FigureQtAgg.png - :alt: Image of figure generated from a script via the QtAgg backend. - :width: 370 - - Screenshot of a Figure generated via a python script and shown using the - QtAgg backend. - -When run from a script, or interactively (e.g. from an -`iPython shell `_) the Figure -will not be shown until we call ``plt.show()``. The Figure will appear in -a new GUI window, and usually will have a toolbar with Zoom, Pan, and other tools -for interacting with the Figure. By default, ``plt.show()`` blocks -further interaction from the script or shell until the Figure window is closed, -though that can be toggled off for some purposes. For more details, please see -:ref:`controlling-interactive`. - -Note that if you are on a client that does not have access to a windowing -system, the Figure will fallback to being drawn using the "Agg" backend, and -cannot be viewed, though it can be :ref:`saved `. - -.. seealso:: - :ref:`interactive_figures`. - -.. _creating_figures: - -Creating Figures -================ - -By far the most common way to create a figure is using the -:ref:`pyplot ` interface. As noted in -:ref:`api_interfaces`, the pyplot interface serves two purposes. One is to spin -up the Backend and keep track of GUI windows. The other is a global state for -Axes and Artists that allow a short-form API to plotting methods. In the -example above, we use pyplot for the first purpose, and create the Figure object, -``fig``. As a side effect ``fig`` is also added to pyplot's global state, and -can be accessed via `~.pyplot.gcf`. - -Users typically want an Axes or a grid of Axes when they create a Figure, so in -addition to `~.pyplot.figure`, there are convenience methods that return both -a Figure and some Axes. A simple grid of Axes can be achieved with -`.pyplot.subplots` (which -simply wraps `.Figure.subplots`): - -.. plot:: - :include-source: - - fig, axs = plt.subplots(2, 2, figsize=(4, 3), layout='constrained') - -More complex grids can be achieved with `.pyplot.subplot_mosaic` (which wraps -`.Figure.subplot_mosaic`): - -.. plot:: - :include-source: - - fig, axs = plt.subplot_mosaic([['A', 'right'], ['B', 'right']], - figsize=(4, 3), layout='constrained') - for ax_name in axs: - axs[ax_name].text(0.5, 0.5, ax_name, ha='center', va='center') - -Sometimes we want to have a nested layout in a Figure, with two or more sets of -Axes that do not share the same subplot grid. -We can use `~.Figure.add_subfigure` or `~.Figure.subfigures` to create virtual -figures inside a parent Figure; see -:doc:`/gallery/subplots_axes_and_figures/subfigures` for more details. - .. plot:: :include-source: - fig = plt.figure(layout='constrained', facecolor='lightskyblue') - fig.suptitle('Figure') - figL, figR = fig.subfigures(1, 2) - figL.set_facecolor('thistle') - axL = figL.subplots(2, 1, sharex=True) - axL[1].set_xlabel('x [m]') - figL.suptitle('Left subfigure') - figR.set_facecolor('paleturquoise') - axR = figR.subplots(1, 2, sharey=True) - axR[0].set_title('Axes 1') - figR.suptitle('Right subfigure') - -It is possible to directly instantiate a `.Figure` instance without using the -pyplot interface. This is usually only necessary if you want to create your -own GUI application or service that you do not want carrying the pyplot global -state. See the embedding examples in :ref:`user_interfaces` for examples of -how to do this. - -Figure options --------------- - -There are a few options available when creating figures. The Figure size on -the screen is set by *figsize* and *dpi*. *figsize* is the ``(width, height)`` -of the Figure in inches (or, if preferred, units of 72 typographic points). *dpi* -are how many pixels per inch the figure will be rendered at. To make your Figures -appear on the screen at the physical size you requested, you should set *dpi* -to the same *dpi* as your graphics system. Note that many graphics systems now use -a "dpi ratio" to specify how many screen pixels are used to represent a graphics -pixel. Matplotlib applies the dpi ratio to the *dpi* passed to the figure to make -it have higher resolution, so you should pass the lower number to the figure. - -The *facecolor*, *edgecolor*, *linewidth*, and *frameon* options all change the appearance of the -figure in expected ways, with *frameon* making the figure transparent if set to *False*. - -Finally, the user can specify a layout engine for the figure with the *layout* -parameter. Currently Matplotlib supplies -:ref:`"constrained" `, -:ref:`"compressed" ` and -:ref:`"tight" ` layout engines. These -rescale axes inside the Figure to prevent overlap of ticklabels, and try and align -axes, and can save significant manual adjustment of artists on a Figure for many -common cases. - -Adding Artists --------------- - -The `~.FigureBase` class has a number of methods to add artists to a `~.Figure` or -a `~.SubFigure`. By far the most common are to add Axes of various configurations -(`~.FigureBase.add_axes`, `~.FigureBase.add_subplot`, `~.FigureBase.subplots`, -`~.FigureBase.subplot_mosaic`) and subfigures (`~.FigureBase.subfigures`). Colorbars -are added to Axes or group of Axes at the Figure level (`~.FigureBase.colorbar`). -It is also possible to have a Figure-level legend (`~.FigureBase.legend`). -Other Artists include figure-wide labels (`~.FigureBase.suptitle`, -`~.FigureBase.supxlabel`, `~.FigureBase.supylabel`) and text (`~.FigureBase.text`). -Finally, low-level Artists can be added directly using `~.FigureBase.add_artist` -usually with care being taken to use the appropriate transform. Usually these -include ``Figure.transFigure`` which ranges from 0 to 1 in each direction, and -represents the fraction of the current Figure size, or ``Figure.dpi_scale_trans`` -which will be in physical units of inches from the bottom left corner of the Figure -(see :ref:`transforms_tutorial` for more details). - - -.. _saving_figures: - -Saving Figures -============== - -Finally, Figures can be saved to disk using the `~.Figure.savefig` method. -``fig.savefig('MyFigure.png', dpi=200)`` will save a PNG formatted figure to -the file ``MyFigure.png`` in the current directory on disk with 200 dots-per-inch -resolution. Note that the filename can include a relative or absolute path to -any place on the file system. - -Many types of output are supported, including raster formats like PNG, GIF, JPEG, -TIFF and vector formats like PDF, EPS, and SVG. - -By default, the size of the saved Figure is set by the Figure size (in inches) and, for the raster -formats, the *dpi*. If *dpi* is not set, then the *dpi* of the Figure is used. -Note that *dpi* still has meaning for vector formats like PDF if the Figure includes -Artists that have been :doc:`rasterized `; the -*dpi* specified will be the resolution of the rasterized objects. - -It is possible to change the size of the Figure using the *bbox_inches* argument -to savefig. This can be specified manually, again in inches. However, by far -the most common use is ``bbox_inches='tight'``. This option "shrink-wraps", trimming -or expanding as needed, the size of the figure so that it is tight around all the artists -in a figure, with a small pad that can be specified by *pad_inches*, which defaults to -0.1 inches. The dashed box in the plot below shows the portion of the figure that -would be saved if ``bbox_inches='tight'`` were used in savefig. - -.. plot:: - - import matplotlib.pyplot as plt - from matplotlib.patches import FancyBboxPatch + fig = plt.figure(figsize=(4, 2), facecolor='lightskyblue', + layout='constrained') + fig.suptitle('A nice Matplotlib Figure') + ax = fig.add_subplot() + ax.set_title('Axes', loc='left', fontstyle='oblique', fontsize='medium') - fig, ax = plt.subplots(figsize=(4, 2), facecolor='lightskyblue') - ax.set_position([0.1, 0.2, 0.8, 0.7]) - ax.set_aspect(1) - bb = ax.get_tightbbox() - bb = bb.padded(10) - fancy = FancyBboxPatch(bb.p0, bb.width, bb.height, fc='none', - ec=(0, 0.0, 0, 0.5), lw=2, linestyle='--', - transform=None, clip_on=False) - ax.add_patch(fancy) +.. toctree:: + :maxdepth: 2 -More reading -============ + Introduction to figures .. toctree:: :maxdepth: 1 - Concept: Output backends - Concept: Matplotlib Application Interfaces (APIs) - In depth: Interacting with figures - In depth: Interactive figures and asynchronous programming - In depth: Event handling - In depth: Writing a backend -- the pyplot interface + Output backends + Matplotlib Application Interfaces (APIs) + Interacting with figures + Interactive figures and asynchronous programming + Event handling + Writing a backend -- the pyplot interface