“Artist” in Matplotlib — something I wanted to know before spending tremendous hours on googling how-tos.

Recently, I noticed that an official tutorial about Artist objects is very informative and helpful to understand what is going on when we plot with matplotlib and to reduce a large amount of time spent for tweaking¹..As you see in Pyplot tutorial, it gives a nice figure if your plot is not so complicated..This hierarchy makes simple examples above even clearer.# example 1fig, ax = plt.subplots()# make Figure and Axes which belongs to 'fig'# example 2fig = plt.figure()# make Figureax = fig.add_subplot(1,1,1)# make Axes belonging to fig Taking a further look at attributes of fig and ax helps you understand the hierarchy more.fig = plt.figure()ax = fig.add_subplot(1,1,1) # make a blank plotting areaprint('fig.axes:', fig.axes)print('ax.figure:', ax.figure)print('ax.xaxis:', ax.xaxis)print('ax.yaxis:', ax.yaxis)print('ax.xaxis.axes:', ax.xaxis.axes)print('ax.yaxis.axes:', ax.yaxis.axes)print('ax.xaxis.figure:', ax.xaxis.figure)print('ax.yaxis.figure:', ax.yaxis.figure)print('fig.xaxis:', fig.xaxis)Output:fig.axes: [<matplotlib.axes._subplots.AxesSubplot object at 0x1167b0630>]ax.figure: Figure(432×288)ax.xaxis: XAxis(54.000000,36.000000)ax.yaxis: YAxis(54.000000,36.000000)ax.xaxis.axes: AxesSubplot(0.125,0.125;0.775×0.755)ax.yaxis.axes: AxesSubplot(0.125,0.125;0.775×0.755)ax.xaxis.figure: Figure(432×288)ax.yaxis.figure: Figure(432×288)—————————————————————————AttributeError Traceback (most recent call last)<ipython-input-21-b9f2d5d9fe09> in <module>() 9 print('ax.xaxis.figure:', ax.xaxis.figure) 10 print('ax.yaxis.figure:', ax.yaxis.figure)—> 11 print('fig.xaxis:', fig.xaxis)AttributeError: 'Figure' object has no attribute 'xaxis'From these results, we can expect following rules about the hierarchy of Figure, Axes, and Axis.Figure knows Axes but not Axis.Axes knows Figure and Axis both.Axis knows Axes and Figure both.Figure can contain multiple Axes because fig.axes is a list of Axes.Axes can belong to only single Figure because ax.figure is not a list.Axes can have one XAxis and YAxis respectively for similar reason.XAxis and YAxis can belong to single Axes and, accordingly, single Figure.Everything in your plot is an ArtistInstead of a figure explaining the hierarchical structure, Usage Guide in the current doc has “Anatomy of a figure”²explaining all components in a figure which is also informative³.From lines and points which represent data to minor ticks and text labels for them on X axis, every single component in a figure is an Artist object⁴..For example, an Axes object, ax, just after instantation has an empty list ax.lines..Frequently-used command ax.plot adds a Line2D object in the list and does other accompanying settings silently.x = np.linspace(0, 2*np.pi, 100)fig = plt.figure()ax = fig.add_subplot(1,1,1)print('ax.lines before plot:..', ax.lines) # empty list# add Line2D in ax.linesline1, = ax.plot(x, np.sin(x), label='1st plot') print('ax.lines after 1st plot:..', ax.lines)ax.legend()print('line1:', line1)print('line2:', line2)Output:ax.lines before plot: []ax.lines after 1st plot: [<matplotlib.lines.Line2D object at 0x1171ca748>]ax.lines after 2nd plot: [<matplotlib.lines.Line2D object at 0x1171ca748>, <matplotlib.lines.Line2D object at 0x117430550>]line1: Line2D(1st plot)line2: Line2D(2nd plot) wFollowing sections summarize four containers..ax.transAxes')figAxesThe matplotlib.axes.Axes is the center of the matplotlib universeThis is a quote from Artist tutorial..This is very true because important parts of data visualization in matplotlib all come from Axes methods.Frequently-used commands such as ax.plot and ax.scatter are called "helper methods" which add corresponding Artists in appropriate containers and do other miscellaneous jobs.This example shows ax.plot and ax.scatter add Line2D and PathCollection objects in corresponding lists.x = np.linspace(0, 2*np.pi, 100)fig = plt.figure()ax = fig.add_subplot(1,1,1)# empty Axes.linesprint('ax.lines before plot:..', ax.lines)# add another Line2Dline2, = ax.plot(x, np.sin(x+np.pi/8), label='2nd plot') print('ax.lines after 2nd plot:..', ax.collections)ax.legend()print('line1:', line1)print('line2:', line2)print('scat:', scat)ax.set_xlabel('x value')ax.set_ylabel('y value')Output:ax.lines before plot: []ax.lines after 1st plot: [<matplotlib.lines.Line2D object at 0x1181d16d8>]ax.lines after 2nd plot: [<matplotlib.lines.Line2D object at 0x1181d16d8>, <matplotlib.lines.Line2D object at 0x1181d1e10>]ax.collections before scatter: []ax.collections after scatter: [<matplotlib.collections.PathCollection object at 0x1181d74a8>]line1: Line2D(1st plot)line2: Line2D(2nd plot)scat: <matplotlib.collections.PathCollection object at 0x1181d74a8>Reusing a plotted object is not recommendedAfter knowing that plotted objects are contained in lists, you probably come up with an idea to reuse those objects in an Axes.lines by appending it to another Axes.lines list for faster plotting..You are probably trying to re-use an artist in more than one Axes which is not supportedThis error message indicates that an Artist, container or primitive, cannot be contained in multiple containers, which is consistent with the fact that each Artist holds the parent container as a bare object, not in a listprint('fig:', id(fig)) print('ax1:', id(ax1))print('line.fig:', id(line.figure))print('line.axes:', id(line.axes))Output:fig: 4707121584ax1: 4707121136line.fig: 4707121584line.axes: 4707121136It might be possible if you do all the necessary stuff in a proper way, but this is far from the first idea to just append an object to a list and is enough reason not to do it.AxisWhile Axis, appeared as XAxis or YAxis, only contains Artists related to ticks and labels, it often requires some googling for minor tweaking, occasionally for an hour..I hope this section helps you get the job done quick.As Artist tutorial doesn’t have a table like other containers, I made a similar table.We used ax.set_xlabel and ax.set_ylabel in the example for Axes container.. More details

Leave a Reply