Note

Go to the endto download the full example code.

Artist tutorial#

Using Artist objects to render on the canvas.

There are three layers to the Matplotlib API.

  • thematplotlib.backend_bases.FigureCanvas is the area onto whichthe figure is drawn

  • thematplotlib.backend_bases.Renderer is the object which knows howto draw on thematplotlib.backend_bases.FigureCanvas

  • and thematplotlib.artist.Artist is the object that knows how to usea renderer to paint onto the canvas.

Thematplotlib.backend_bases.FigureCanvas andmatplotlib.backend_bases.Renderer handle all the details oftalking to user interface toolkits likewxPython or drawing languages like PostScript®, andtheArtist handles all the high level constructs like representingand laying out the figure, text, and lines. The typical user willspend 95% of their time working with theArtists.

There are two types ofArtists: primitives and containers. The primitivesrepresent the standard graphical objects we want to paint onto our canvas:Line2D,Rectangle,Text,AxesImage, etc., andthe containers are places to put them (Axis,Axes andFigure). Thestandard use is to create aFigure instance, usetheFigure to create one or moreAxesinstances, and use theAxes instancehelper methods to create the primitives. In the example below, we create aFigure instance usingmatplotlib.pyplot.figure(), which is aconvenience method for instantiatingFigure instances and connecting themwith your user interface or drawing toolkitFigureCanvas. As we willdiscuss below, this is not necessary -- you can work directly with PostScript,PDF Gtk+, or wxPythonFigureCanvas instances, instantiate yourFiguresdirectly and connect them yourselves -- but since we are focusing here on theArtist API we'll letpyplot handle some of those detailsfor us:

importmatplotlib.pyplotaspltfig=plt.figure()ax=fig.add_subplot(2,1,1)# two rows, one column, first plot

TheAxes is probably the most importantclass in the Matplotlib API, and the one you will be working with mostof the time. This is because theAxes is the plotting area intowhich most of the objects go, and theAxes has many special helpermethods (plot(),text(),hist(),imshow()) to create the most commongraphics primitives (Line2D,Text,Rectangle,AxesImage, respectively). These helper methodswill take your data (e.g.,numpy arrays and strings) and createprimitiveArtist instances as needed (e.g.,Line2D), add them tothe relevant containers, and draw them when requested. If you want to createanAxes at an arbitrary location, simply use theadd_axes() method which takes a listof[left,bottom,width,height] values in 0-1 relative figurecoordinates:

fig2=plt.figure()ax2=fig2.add_axes((0.15,0.1,0.7,0.3))

Continuing with our example:

importnumpyasnpt=np.arange(0.0,1.0,0.01)s=np.sin(2*np.pi*t)line,=ax.plot(t,s,color='blue',lw=2)

In this example,ax is theAxes instance created by thefig.add_subplot call above and when you callax.plot, it creates aLine2D instance andadds it to theAxes. In the interactiveIPythonsession below, you can see that theAxes.lines list is length one andcontains the same line that was returned by theline,=ax.plot... call:

In [101]:ax.lines[0]Out[101]:<matplotlib.lines.Line2D at 0x19a95710>In [102]:lineOut[102]:<matplotlib.lines.Line2D at 0x19a95710>

If you make subsequent calls toax.plot (and the hold state is "on"which is the default) then additional lines will be added to the list.You can remove a line later by calling itsremove method:

line=ax.lines[0]line.remove()

The Axes also has helper methods to configure and decorate the x-axisand y-axis tick, tick labels and axis labels:

xtext=ax.set_xlabel('my xdata')# returns a Text instanceytext=ax.set_ylabel('my ydata')

When you callax.set_xlabel,it passes the information on theTextinstance of theXAxis. EachAxesinstance contains anXAxis and aYAxis instance, which handle the layout anddrawing of the ticks, tick labels and axis labels.

Try creating the figure below.

importmatplotlib.pyplotaspltimportnumpyasnpfig=plt.figure()fig.subplots_adjust(top=0.8)ax1=fig.add_subplot(211)ax1.set_ylabel('Voltage [V]')ax1.set_title('A sine wave')t=np.arange(0.0,1.0,0.01)s=np.sin(2*np.pi*t)line,=ax1.plot(t,s,color='blue',lw=2)# Fixing random state for reproducibilitynp.random.seed(19680801)ax2=fig.add_axes((0.15,0.1,0.7,0.3))n,bins,patches=ax2.hist(np.random.randn(1000),50,facecolor='yellow',edgecolor='yellow')ax2.set_xlabel('Time [s]')plt.show()
A sine wave

Customizing your objects#

Every element in the figure is represented by a MatplotlibArtist, and each has an extensive list ofproperties to configure its appearance. The figure itself contains aRectangle exactly the size of the figure,which you can use to set the background color and transparency of thefigures. Likewise, eachAxes bounding box(the standard white box with black edges in the typical Matplotlibplot, has aRectangle instance that determines the color,transparency, and other properties of the Axes. These instances arestored as member variablesFigure.patch andAxes.patch("Patch" is a name inherited from MATLAB, and is a 2D "patch"of color on the figure, e.g., rectangles, circles and polygons).Every MatplotlibArtist has the following properties

Property

Description

alpha

The transparency - a scalar from 0-1

animated

A boolean that is used to facilitate animated drawing

axes

The Axes that the Artist lives in, possibly None

clip_box

The bounding box that clips the Artist

clip_on

Whether clipping is enabled

clip_path

The path the artist is clipped to

contains

A picking function to test whether the artist contains the pickpoint

figure

The figure instance the artist lives in, possibly None

label

A text label (e.g., for auto-labeling)

picker

A python object that controls object picking

transform

The transformation

visible

A boolean whether the artist should be drawn

zorder

A number which determines the drawing order

rasterized

Boolean; Turns vectors into raster graphics (for compression &EPS transparency)

Each of the properties is accessed with an old-fashioned setter orgetter (yes we know this irritates Pythonistas and we plan to supportdirect access via properties or traits but it hasn't been done yet).For example, to multiply the current alpha by a half:

a=o.get_alpha()o.set_alpha(0.5*a)

If you want to set a number of properties at once, you can also usetheset method with keyword arguments. For example:

o.set(alpha=0.5,zorder=2)

If you are working interactively at the python shell, a handy way toinspect theArtist properties is to use thematplotlib.artist.getp() function (simplygetp() in pyplot), which lists the propertiesand their values. This works for classes derived fromArtist aswell, e.g.,Figure andRectangle. Here are theFigure rectangleproperties mentioned above:

In [149]:matplotlib.artist.getp(fig.patch)  agg_filter = None  alpha = None  animated = False  antialiased or aa = False  bbox = Bbox(x0=0.0, y0=0.0, x1=1.0, y1=1.0)  capstyle = butt  children = []  clip_box = None  clip_on = True  clip_path = None  contains = None  data_transform = BboxTransformTo(     TransformedBbox(         Bbox...  edgecolor or ec = (1.0, 1.0, 1.0, 1.0)  extents = Bbox(x0=0.0, y0=0.0, x1=640.0, y1=480.0)  facecolor or fc = (1.0, 1.0, 1.0, 1.0)  figure = Figure(640x480)  fill = True  gid = None  hatch = None  height = 1  in_layout = False  joinstyle = miter  label =  linestyle or ls = solid  linewidth or lw = 0.0  patch_transform = CompositeGenericTransform(     BboxTransformTo(   ...  path = Path(array([[0., 0.],        [1., 0.],        [1.,...  path_effects = []  picker = None  rasterized = None  sketch_params = None  snap = None  transform = CompositeGenericTransform(     CompositeGenericTra...  transformed_clip_path_and_affine = (None, None)  url = None  verts = [[  0.   0.]  [640.   0.]  [640. 480.]  [  0. 480....  visible = True  width = 1  window_extent = Bbox(x0=0.0, y0=0.0, x1=640.0, y1=480.0)  x = 0  xy = (0, 0)  y = 0  zorder = 1

The docstrings for all of the classes also contain theArtistproperties, so you can consult the interactive "help" or thematplotlib.artist for a listing of properties for a given object.

Object containers#

Now that we know how to inspect and set the properties of a givenobject we want to configure, we need to know how to get at that object.As mentioned in the introduction, there are two kinds of objects:primitives and containers. The primitives are usually the things youwant to configure (the font of aTextinstance, the width of aLine2D) althoughthe containers also have some properties as well -- for example theAxesArtist is acontainer that contains many of the primitives in your plot, but italso has properties like thexscale to control whether the xaxisis 'linear' or 'log'. In this section we'll review where the variouscontainer objects store theArtists that you want to get at.

Figure container#

The top level containerArtist is thematplotlib.figure.Figure, and it contains everything in thefigure. The background of the figure is aRectangle which is stored inFigure.patch. Asyou add subplots (add_subplot()) andAxes (add_axes()) to the figurethese will be appended to theFigure.axes. These are also returned by themethods that create them:

In [156]:fig=plt.figure()In [157]:ax1=fig.add_subplot(211)In [158]:ax2=fig.add_axes((0.1,0.1,0.7,0.3))In [159]:ax1Out[159]:<Axes:>In [160]:print(fig.axes)[<Axes:>, <matplotlib.axes._axes.Axes object at 0x7f0768702be0>]

Because the figure maintains the concept of the "current Axes" (seeFigure.gca andFigure.sca) to support thepylab/pyplot state machine, you should not insert or remove Axesdirectly from the Axes list, but rather use theadd_subplot() andadd_axes() methods to insert, and theAxes.remove method to delete. You arefree however, to iterate over the list of Axes or index into it to getaccess toAxes instances you want to customize. Here is anexample which turns all the Axes grids on:

foraxinfig.axes:ax.grid(True)

The figure also has its ownimages,lines,patches andtextattributes, which you can use to add primitives directly. When doing so, thedefault coordinate system for theFigure will simply be in pixels (whichis not usually what you want). If you instead use Figure-level methods to addArtists (e.g., usingFigure.text to add text), then the default coordinatesystem will be "figure coordinates" where (0, 0) is the bottom-left of thefigure and (1, 1) is the top-right of the figure.

As with allArtists, you can control this coordinate system by settingthe transform property. You can explicitly use "figure coordinates" bysetting theArtist transform tofig.transFigure:

importmatplotlib.linesaslinesfig=plt.figure()l1=lines.Line2D([0,1],[0,1],transform=fig.transFigure,figure=fig)l2=lines.Line2D([0,1],[1,0],transform=fig.transFigure,figure=fig)fig.lines.extend([l1,l2])plt.show()
artists

Here is a summary of the Artists the Figure contains

Figure attribute

Description

axes

A list ofAxes instances

patch

TheRectangle background

images

A list ofFigureImage patches -useful for raw pixel display

legends

A list of FigureLegend instances(different fromAxes.get_legend())

lines

A list of FigureLine2D instances(rarely used, seeAxes.lines)

patches

A list of FigurePatchs(rarely used, seeAxes.patches)

texts

A list FigureText instances

Axes container#

Thematplotlib.axes.Axes is the center of the Matplotlibuniverse -- it contains the vast majority of all theArtists usedin a figure with many helper methods to create and add theseArtists to itself, as well as helper methods to access andcustomize theArtists it contains. Like theFigure, it contains aPatchmatplotlib.axes.Axes.patch which is aRectangle for Cartesian coordinates and aCircle for polar coordinates; this patchdetermines the shape, background and border of the plotting region:

ax=fig.add_subplot()rect=ax.patch# a Rectangle instancerect.set_facecolor('green')

When you call a plotting method, e.g., the canonicalplot and pass in arrays or lists of values, themethod will create amatplotlib.lines.Line2D instance, update the line withall theLine2D properties passed as keyword arguments, add the line totheAxes, and return it to you:

In [213]:x,y=np.random.rand(2,100)In [214]:line,=ax.plot(x,y,'-',color='blue',linewidth=2)

plot returns a list of lines because you can pass in multiple x, ypairs to plot, and we are unpacking the first element of the lengthone list into the line variable. The line has been added to theAxes.lines list:

In [229]:print(ax.lines)[<matplotlib.lines.Line2D at 0xd378b0c>]

Similarly, methods that create patches, likebar() creates a list of rectangles, willadd the patches to theAxes.patches list:

In [233]:n,bins,rectangles=ax.hist(np.random.randn(1000),50)In [234]:rectanglesOut[234]:<BarContainer object of 50 artists>In [235]:print(len(ax.patches))Out[235]:50

You should not add objects directly to theAxes.lines orAxes.patcheslists, because theAxes needs to do a few things when it creates and addsan object:

  • It sets thefigure andaxes property of theArtist;

  • It sets the defaultAxes transformation (unless one is already set);

  • It inspects the data contained in theArtist to update the datastructures controlling auto-scaling, so that the view limits can beadjusted to contain the plotted data.

You can, nonetheless, create objects yourself and add them directly to theAxes using helper methods likeadd_line andadd_patch. Here is an annotated interactive sessionillustrating what is going on:

In [262]:fig,ax=plt.subplots()# create a rectangle instanceIn [263]:rect=matplotlib.patches.Rectangle((1,1),width=5,height=12)# by default the Axes instance is NoneIn [264]:print(rect.axes)None# and the transformation instance is set to the "identity transform"In [265]:print(rect.get_data_transform())IdentityTransform()# now we add the Rectangle to the AxesIn [266]:ax.add_patch(rect)# and notice that the ax.add_patch method has set the Axes# instanceIn [267]:print(rect.axes)Axes(0.125,0.1;0.775x0.8)# and the transformation has been set tooIn [268]:print(rect.get_data_transform())CompositeGenericTransform(    TransformWrapper(        BlendedAffine2D(            IdentityTransform(),            IdentityTransform())),    CompositeGenericTransform(        BboxTransformFrom(            TransformedBbox(                Bbox(x0=0.0, y0=0.0, x1=1.0, y1=1.0),                TransformWrapper(                    BlendedAffine2D(                        IdentityTransform(),                        IdentityTransform())))),        BboxTransformTo(            TransformedBbox(                Bbox(x0=0.125, y0=0.10999999999999999, x1=0.9, y1=0.88),                BboxTransformTo(                    TransformedBbox(                        Bbox(x0=0.0, y0=0.0, x1=6.4, y1=4.8),                        Affine2D(                            [[100.   0.   0.]                             [  0. 100.   0.]                             [  0.   0.   1.]])))))))# the default Axes transformation is ax.transDataIn [269]:print(ax.transData)CompositeGenericTransform(    TransformWrapper(        BlendedAffine2D(            IdentityTransform(),            IdentityTransform())),    CompositeGenericTransform(        BboxTransformFrom(            TransformedBbox(                Bbox(x0=0.0, y0=0.0, x1=1.0, y1=1.0),                TransformWrapper(                    BlendedAffine2D(                        IdentityTransform(),                        IdentityTransform())))),        BboxTransformTo(            TransformedBbox(                Bbox(x0=0.125, y0=0.10999999999999999, x1=0.9, y1=0.88),                BboxTransformTo(                    TransformedBbox(                        Bbox(x0=0.0, y0=0.0, x1=6.4, y1=4.8),                        Affine2D(                            [[100.   0.   0.]                             [  0. 100.   0.]                             [  0.   0.   1.]])))))))# notice that the xlimits of the Axes have not been changedIn [270]:print(ax.get_xlim())(0.0, 1.0)# but the data limits have been updated to encompass the rectangleIn [271]:print(ax.dataLim.bounds)(1.0, 1.0, 5.0, 12.0)# we can manually invoke the auto-scaling machineryIn [272]:ax.autoscale_view()# and now the xlim are updated to encompass the rectangle, plus marginsIn [273]:print(ax.get_xlim())(0.75, 6.25)# we have to manually force a figure drawIn [274]:fig.canvas.draw()

There are many, manyAxes helper methods for creating primitiveArtists and adding them to their respective containers. The tablebelow summarizes a small sampling of them, the kinds ofArtist theycreate, and where they store them

Axes helper method

Artist

Container

annotate - text annotations

Annotation

ax.texts

bar - bar charts

Rectangle

ax.patches

errorbar - error bar plots

Line2D andRectangle

ax.lines andax.patches

fill - shared area

Polygon

ax.patches

hist - histograms

Rectangle

ax.patches

imshow - image data

AxesImage

ax.images

legend - Axes legend

Legend

ax.get_legend()

plot - xy plots

Line2D

ax.lines

scatter - scatter charts

PolyCollection

ax.collections

text - text

Text

ax.texts

In addition to all of theseArtists, theAxes contains twoimportantArtist containers: theXAxisandYAxis, which handle the drawing of theticks and labels. These are stored as instance variablesmatplotlib.axes.Axes.xaxis andmatplotlib.axes.Axes.yaxis. TheXAxis andYAxiscontainers will be detailed below, but note that theAxes containsmany helper methods which forward calls on to theAxis instances, so you often do not need towork with them directly unless you want to. For example, you can setthe font color of theXAxis ticklabels using theAxes helpermethod:

ax.tick_params(axis='x',labelcolor='orange')

Below is a summary of the Artists that theAxes contains

Axes attribute

Description

artists

AnArtistList ofArtist instances

patch

Rectangle instance for Axes background

collections

AnArtistList ofCollection instances

images

AnArtistList ofAxesImage

lines

AnArtistList ofLine2D instances

patches

AnArtistList ofPatch instances

texts

AnArtistList ofText instances

xaxis

Amatplotlib.axis.XAxis instance

yaxis

Amatplotlib.axis.YAxis instance

The legend can be accessed byget_legend,

Axis containers#

Thematplotlib.axis.Axis instances handle the drawing of thetick lines, the grid lines, the tick labels and the axis label. Youcan configure the left and right ticks separately for the y-axis, andthe upper and lower ticks separately for the x-axis. TheAxisalso stores the data and view intervals used in auto-scaling, panningand zooming, as well as theLocator andFormatter instances which control wherethe ticks are placed and how they are represented as strings.

EachAxis object contains alabel attribute(this is whatpyplot modifies in calls toxlabel andylabel) as well as a list of major and minor ticks. The ticks areaxis.XTick andaxis.YTick instances, which contain the actual line andtext primitives that render the ticks and ticklabels. Because the ticks aredynamically created as needed (e.g., when panning and zooming), you shouldaccess the lists of major and minor ticks through their accessor methodsaxis.Axis.get_major_ticks andaxis.Axis.get_minor_ticks. Althoughthe ticks contain all the primitives and will be covered below,Axisinstances have accessor methods that return the tick lines, tick labels, ticklocations etc.:

artists
array([0. , 0.2, 0.4, 0.6, 0.8, 1. ])
[Text(0.0, 0, '0.0'), Text(0.2, 0, '0.2'), Text(0.4, 0, '0.4'), Text(0.6000000000000001, 0, '0.6'), Text(0.8, 0, '0.8'), Text(1.0, 0, '1.0')]

note there are twice as many ticklines as labels because by default there aretick lines at the top and bottom but only tick labels below the xaxis;however, this can be customized.

<a list of 12 Line2D ticklines objects>

And with the above methods, you only get lists of major ticks back bydefault, but you can also ask for the minor ticks:

<a list of 0 Line2D ticklines objects>

Here is a summary of some of the useful accessor methods of theAxis(these have corresponding setters where useful, such asset_major_formatter().)

Axis accessor method

Description

get_scale

The scale of the Axis, e.g., 'log' or 'linear'

get_view_interval

The interval instance of the Axis view limits

get_data_interval

The interval instance of the Axis data limits

get_gridlines

A list of grid lines for the Axis

get_label

The Axis label - aText instance

get_offset_text

The Axis offset text - aText instance

get_ticklabels

A list ofText instances -keyword minor=True|False

get_ticklines

A list ofLine2D instances -keyword minor=True|False

get_ticklocs

A list of Tick locations -keyword minor=True|False

get_major_locator

Theticker.Locator instance for major ticks

get_major_formatter

Theticker.Formatter instance for majorticks

get_minor_locator

Theticker.Locator instance for minor ticks

get_minor_formatter

Theticker.Formatter instance for minorticks

get_major_ticks

A list ofTick instances for major ticks

get_minor_ticks

A list ofTick instances for minor ticks

grid

Turn the grid on or off for the major or minorticks

Here is an example, not recommended for its beauty, which customizesthe Axes and Tick properties.

# plt.figure creates a matplotlib.figure.Figure instancefig=plt.figure()rect=fig.patch# a rectangle instancerect.set_facecolor('lightgoldenrodyellow')ax1=fig.add_axes((0.1,0.3,0.4,0.4))rect=ax1.patchrect.set_facecolor('lightslategray')forlabelinax1.xaxis.get_ticklabels():# label is a Text instancelabel.set_color('red')label.set_rotation(45)label.set_fontsize(16)forlineinax1.yaxis.get_ticklines():# line is a Line2D instanceline.set_color('green')line.set_markersize(25)line.set_markeredgewidth(3)plt.show()
artists

Tick containers#

Thematplotlib.axis.Tick is the final container object in ourdescent from theFigure to theAxes to theAxisto theTick. TheTick contains the tickand grid line instances, as well as the label instances for the upperand lower ticks. Each of these is accessible directly as an attributeof theTick.

Tick attribute

Description

tick1line

ALine2D instance

tick2line

ALine2D instance

gridline

ALine2D instance

label1

AText instance

label2

AText instance

Here is an example which sets the formatter for the right side ticks withdollar signs and colors them green on the right side of the yaxis.

importmatplotlib.pyplotaspltimportnumpyasnp# Fixing random state for reproducibilitynp.random.seed(19680801)fig,ax=plt.subplots()ax.plot(100*np.random.rand(20))# Use automatic StrMethodFormatterax.yaxis.set_major_formatter('${x:1.2f}')ax.yaxis.set_tick_params(which='major',labelcolor='green',labelleft=False,labelright=True)plt.show()
dollar ticks

Total running time of the script: (0 minutes 1.274 seconds)

Gallery generated by Sphinx-Gallery