Matplotlib objects

Till now, we have used the pyplot module of matplotlib. This module makes it easy for us to use the most important plot commands directly. Mostly, we are interested in creating a figure and display it immediately. Sometimes, though, we want to generate a figure that should be modified later by changing some of its attributes. This requires us to work with graphical objects in an object-oriented way. In this section, we will present some basic steps to modify figures. For a more sophisticated object oriented approach to plotting in Python, you have to leave pyplot and have to dive directly into matplotlib with its extensive documentation.

The axes object

When creating a plot that should be modified later, we need references to a figure and an axes object. For this we have to create a figure first and then define some axes and their location in the figure. And we should not forget to assign these objects to a variable:

fig = figure()
ax = subplot(111)

A figure can have several axes objects depending on the use of subplot. In a second step plots are associated with a given axes object:

fig = figure(1)
ax = subplot(111)
x = linspace(0,2*pi,100) 
# We set up a function that modulates the amplitude of the sin function
amod_sin = lambda x: (1.-0.1*sin(25*x))*sin(x)
# and plot both...
ax.plot(x,sin(x),label = 'sin') 
ax.plot(x, amod_sin(x), label = 'modsin')

Here we used an anonymous function indicated by the lambda keyword . We will explain this construct later in section Anonymous functions - the lambda keyword in Chapter 7, Functions. In fact, these two plot commands fill the list ax.lines with two Lines2D objects:

ax.lines #[<matplotlib.lines.Line2D at ...>, <matplotlib.lines.Line2D at ...>]

It is a good practice to use labels so that we can later identify objects in an easy way:

for il,line in enumerate(ax.lines):
    if line.get_label() == 'sin':
       break

We set up now things in a way that allows further modifications. The figure we got so far is shown in preceding figure (Figure 6.11, left).

Modifying line properties

We just identified a particular line object by its label. It is an element of the list ax.lines list with the index  il . All its properties are collected in a dictionary

dict_keys(['marker', 'markeredgewidth', 'data', 'clip_box', 'solid_capstyle', 'clip_on', 'rasterized', 'dash_capstyle', 'path', 'ydata', 'markeredgecolor', 'xdata', 'label', 'alpha', 'linestyle', 'antialiased', 'snap', 'transform', 'url', 'transformed_clip_path_and_affine', 'clip_path', 'path_effects', 'animated', 'contains', 'fillstyle', 'sketch_params', 'xydata', 'drawstyle', 'markersize', 'linewidth', 'figure', 'markerfacecolor', 'pickradius', 'agg_filter', 'dash_joinstyle', 'color', 'solid_joinstyle', 'picker', 'markevery', 'axes', 'children', 'gid', 'zorder', 'visible', 'markerfacecoloralt'])

which can be obtained by the command:

ax.lines[il].properties()

They can be changed by corresponding setter methods. Let us change the line style of the sine - curve:

ax.lines[il].set_linestyle('-.')
ax.lines[il].set_linewidth(2)

We can even modify the data, as shown:

ydata=ax.lines[il].get_ydata()
ydata[-1]=-0.5
ax.lines[il].set_ydata(ydata)

The result is shown in the next figure (Figure 6.11, right):

 

Modifying line properties

Figure 6.11: The amplitude modulated sine-function (left) and a curve with the last data point corrupted (right).

Annotations

One useful axes method is annotate. It sets an annotation at a given position and points, with an arrow, to another position in the drawing. The arrow can be given properties in a dictionary:

annot1=ax.annotate('amplitude modulated
 curve', (2.1,1.0),(3.2,0.5),
       arrowprops={'width':2,'color':'k', 'connectionstyle':'arc3,rad=+0.5', 
                   'shrink':0.05},
       verticalalignment='bottom', horizontalalignment='left',fontsize=15, 
                   bbox={'facecolor':'gray', 'alpha':0.1, 'pad':10})
annot2=ax.annotate('corrupted data', (6.3,-0.5),(6.1,-1.1),
       arrowprops={'width':0.5,'color':'k','shrink':0.1},
       horizontalalignment='center', fontsize=12)

In the first annotation example above, the arrow points to a point with the coordinates (2.1, 1.0) and the left bottom coordinate of the text is (3.2, 0.5). If not otherwise specified, the coordinates are given in the convenient data-coordinate system, which refers to the data used to generate the plots.

Furthermore, we demonstrated a couple of arrow properties specified by the arrowprop  dictionary. You can scale the arrow by the shrink key. The setting 'shrink':0.05 reduces the arrow size by 5% to keep a distance to the curve it points to. You can let the arrow follow a spline arc or give it other shapes using the connectionstyle key.

Text properties or even a bounding box around the text can be made by extra keyword arguments to the annotate method, refer to the following figure (Figure 6.12, left):

Experimenting with annotations requires sometimes to remove attempts that we would like to reject. Therefore we assigned the annotate object to a variable, which allows us to remove the annotation by its remove method:

annot1.remove()

Filling areas between curves

Filling is an ideal tool to highlight differences between curves, such as noise on top of expected data, approximations versus exact functions, and so on.

Filling is done by the axis method

ax.fill_between(x,y1,y2)

For the next figure we used:

axf = ax.fill_between(x, sin(x), amod_sin(x), facecolor='gray')

 where is a very convenient parameter that needs a Boolean array to specify the additional filling conditions.

axf = ax.fill_between(x, sin(x), amod_sin(x),where=amod_sin(x)-sin(x) > 0, facecolor=’gray’)

The Boolean array which selects the regions to fill is amod_sin(x)-sin(x) > 0.

The next figure shows the curve with both variants of filling areas:

   

Filling areas between curves

Figure 6.12: The amplitude modulated sin-function with annotations and filled areas(left) and a modified figure with only partially filled areas by using the where parameter (right).

If you test these commands yourself, do not forget to remove the complete filling before you try out the partial filling, otherwise you will not see any change:

axf.remove()

Related filling commands are fill and fill_betweenx.

Ticks and ticklabels

Figures in talks, posters, and publications look much nicer if they are not overloaded with unnecessary information. You want to direct the spectator to those parts that contain the message. In our example, we clean up the picture by removing ticks from the x-axis and y-axis and by introducing problem related tick labels:

Ticks and ticklabels

Figure 6.13: The completed example of the amplitude modulated sine - function with annotations and filled areas and modified ticks and tick labels.

ax.set_xticks(array([0,pi/2,pi,3/2*pi,2*pi]))
ax.set_xticklabels(('$0$','$pi/2$','$pi$','$3/2 pi$','$2 pi$'),fontsize=18)
ax.set_yticks(array([-1.,0.,1]))
ax.set_yticklabels(('$-1$','$0$','$1$'),fontsize=18)

Note that we used LaTeX formatting in the strings to represent Greek letters, to set formulas correctly, and to use a LaTeX font. It is also a good practice to increase the font size so that the resulting figure can be scaled down into a text document without affecting the readability of the axes. The final result of this guiding example is shown in the previous figure (Figure 6.13).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.69.199