Optimizing simple plots

Simplest plot as shown in Tutorial 1 (just a wrap up...)

In [1]:
from matplotlib import pyplot as plt
import numpy


x=numpy.array([1,2,3,4,5])
y=numpy.array([5,4,7,1,7])

plt.plot(x,y,'ok')
plt.show()

Explicit creation of objects

We discussed in tutorial 1 that it is much better to explicitly create the figure and axis as objects that can be used to modify the appearance of the plot. We change the axis limits here as an example.

In []:
#Initialize figure and axis
fig = plt.figure(figsize=(7,5))
ax = fig.add_axes([0.1,0.1,0.88,0.88])

# plot data
line1 = ax.plot(x,y,'ok')

#modify axes
ax.set_xlim(0,6)
ax.set_ylim(0,8)

#display or savefig
plt.savefig('dummy.pdf', dpi=300)
plt.show()

Use matplotlib configuration file matplotlibrc or online rcParameter changes

Default values for certain parameters can be set in the matplotlibrc file to be used globally to customize the behviour for every plot. You can find details about the location and use of the matplotlibrc file at http://matplotlib.org/users/customizing.html

Alternatively, all those parameters can be set on the fly for a specific python session as shown below. In that example I change the linewith of the axis boundary as well as the size of the major and minor ticks. The two plots are different concerning the axis labels and the use of minor ticks.

In [3]:
#Set global matplotlib parameters in script or in /home/$USER/.matplotlib/matplotlibrc
plt.rcParams['axes.linewidth'] = 1.5
plt.rcParams['xtick.major.size'] = 8
plt.rcParams['xtick.minor.size'] = 4
plt.rcParams['ytick.major.size'] = 6
plt.rcParams['ytick.minor.size'] = 3
plt.rcParams['ytick.minor.size'] = 3

#Initialize figure and axes
fig = plt.figure(figsize=(14,5))
ax1 = fig.add_axes([0.05,0.1,0.43,0.88])
ax2 = fig.add_axes([0.56,0.15,0.43,0.83])

# plot data
line1 = ax1.plot(x,y,'ok')
line2 = ax2.plot(x,y,'ok')

#labels
ax2.set_xlabel('independent values',fontsize=22)
ax2.set_ylabel('dependent values',fontsize=22)

#modify axes
ax1.set_xlim(0,6)
ax1.set_ylim(0,8)

ax2.set_xlim(0.01,5.9)
ax2.set_ylim(0.01,7.9)
ax2.minorticks_on()

plt.show()

Modify appearance on the fly in the code

Beside the global matplotlib parameter settings. One can modify the parameter of the ticks with the function tick_params as shown below. It has a lot of option you can choose one as shown on the right plot, but a "nice" looking one is shown on the right. The tick_params function was added to matplotlib recently. Before one needed to retrieve the object for the major and minor ticks on both axis in a loop and set their individual properties. The code is shown but commented out just for information if needed.

In [9]:
#Initialize figure and axes
fig = plt.figure(figsize=(14,5))
ax1 = fig.add_axes([0.05,0.15,0.43,0.81])
ax2 = fig.add_axes([0.56,0.15,0.43,0.81])

# plot data
line1 = ax1.plot(x,y,'ok')
line2 = ax2.plot(x,y,'ok')

#modify axes
ax1.set_xlim(0,6)
ax1.set_ylim(0,8)
ax1.minorticks_on()
ax1.tick_params(axis='x',which='major',direction='out',length=4,width=4,color='b',pad=10,labelsize=20,labelcolor='g')

ax2.set_xlim(0,6)
ax2.set_ylim(0,8)
ax2.minorticks_on()
ax2.tick_params(axis='both',which='minor',length=5,width=2,labelsize=18)
ax2.tick_params(axis='both',which='major',length=8,width=2,labelsize=18)

#Old version to set tick parameters
#for line in ax2.xaxis.get_ticklines()+ax2.yaxis.get_ticklines()+ax2.xaxis.get_minorticklines()+ax2.yaxis.get_minorticklines():
#    line.set_markeredgewidth(3.0)

plt.show()

Adding a legend

Legends can be added easily to a figure. The standard appearence as shown on the left is usually not optimal with two markers per line, one column format, frame box etc. It is easy to customize the legend with several optional parameters available to the function. A comparison of the default behaviour to an optimized one is shown below.

In [5]:
#Initialize figure and axes
fig = plt.figure(figsize=(14,5))
ax1 = fig.add_axes([0.05,0.1,0.43,0.88])
ax2 = fig.add_axes([0.56,0.15,0.43,0.83])

# plot data
line1 = ax1.plot(x,y,'ok',ms=8,mfc='w',mew=2,label='open')
line2 = ax2.plot(x,y,'ok',ms=8,mfc='w',mew=2,label='open')
line3 = ax1.plot(x+0.5,y/2.0,'-sg',ms=10,label='filled')
line4 = ax2.plot(x+0.5,y/2.0,'-sg',ms=10,label='filled',lw=2,mec='k',mew=2)

# legend
leg1 = ax1.legend()
leg2.draw_frame(True)
leg2 = ax2.legend([line2[0]],['label1'],loc='upper left',numpoints=1,ncol=2,borderaxespad=1, 
                  frameon=True,fontsize=15)

#labels
ax2.set_xlabel('independent values',fontsize=22)
ax2.set_ylabel('dependent values',fontsize=22)

#modify axes
ax1.set_xlim(0,6)
ax1.set_ylim(0,8)

ax2.set_xlim(0,6)
ax2.set_ylim(0,8)
ax2.minorticks_on()
ax2.tick_params(axis='both',which='minor',length=5,width=2,labelsize=18)
ax2.tick_params(axis='both',which='major',length=8,width=2,labelsize=18)

plt.show()

Adding a second axis with different scaling

In [14]:
#Initialize figure and axes
fig = plt.figure(figsize=(7,5))
ax1 = fig.add_axes([0.1,0.15,0.78,0.83])

# plot data
line = ax1.plot(x,y,'ok',ms=8,mfc='w',mew=2,label='open')

#labels
ax1.set_xlabel('independent values',fontsize=22)
ax1.set_ylabel('dependent values',fontsize=22)

#modify axes
ax1.set_xlim(0,6)
ax1.set_ylim(0,8)
ax1.minorticks_on()
ax1.tick_params(axis='both',which='minor',length=5,width=2,labelsize=18)
ax1.tick_params(axis='both',which='major',length=8,width=2,labelsize=18)

#add second y axis on right side
ax2 = ax1.twinx()
ax2.set_ylim([0,8]) ## need to match with limits of ax1 to have the same scaling of the axis to set coressponding lables.
ax2.set_yticks([2,4,8])
ax2.minorticks_on()
ax2.tick_params(axis='y',which='major',length=8,width=3,labelsize=18)
ax2.tick_params(axis='y',which='minor',length=5,width=2,labelsize=18)
ax2.set_ylabel('2nd value axis',fontsize=22)

plt.show()

Adding text to figures

The are several way to add text to a figure/axis. There are usually two kinds of coordinates. The relative coordinates across the figure/axis from 0 to 1 and the data coordinates of the axis. In case text is added to the axis, the data coordinates are used as default. By providing the axis transformation form data to relative coordinates as a paramter, e.g. transform=ax1.transAxes the position of the text will be independent of the data limits.

In [7]:
#Initialize figure and axes
fig = plt.figure(figsize=(7,5))
ax1 = fig.add_axes([0.1,0.15,0.88,0.83])

# plot data
line = ax1.plot(x,y,'ok',ms=8,mfc='w',mew=2,label='open')

#labels
ax1.set_xlabel('independent values',fontsize=22)
ax1.set_ylabel('dependent values',fontsize=22)

#modify axes
ax1.set_xlim(0,6)
ax1.set_ylim(0,8)
ax1.minorticks_on()
ax1.tick_params(axis='both',which='minor',length=5,width=2,labelsize=18)
ax1.tick_params(axis='both',which='major',length=8,width=2,labelsize=18)

#adding some text
ax1.text(1,7,'A',fontsize=15,color='r')
fig.text(0.2,0.9,'B',fontsize=15,color='b')
ax1.text(0.2,0.9,'C',fontsize=15,color='k',transform=ax1.transAxes, rotation=90)
ax1.set_ylim(3,10)
plt.show()
In [7]: