-
Paul McCarthy authoredPaul McCarthy authored
Plotting with python
The main plotting module in python is matplotlib
. There is a lot
that can be done with it - see the webpage
Contents
- Running inside a notebook
- 2D plots
- Histograms and Bar Plots
- Scatter plots
- Subplots
- Displaying Images
- 3D plots
- Running in a standalone script
- Exercise
Inside a notebook
Inside a jupyter notebook you get access to this in a slightly different way, compared to other modules:
%matplotlib inline
This only needs to be done once in a notebook, like for standard imports.
There are also other alternatives, including interactive versions - see the practical on Jupyter notebooks for more information about this.
The library works very similarly to plotting in matlab. Let's start with some simple examples.
2D plots
import matplotlib.pyplot as plt
import numpy as np
plt.style.use('bmh')
x = np.linspace(-np.pi, np.pi, 256)
cosx, sinx = np.cos(x), np.sin(x)
plt.plot(x, cosx)
plt.plot(x, sinx, color='red', linewidth=4, linestyle='-.')
plt.plot(x, sinx**2)
plt.xlim(-np.pi, np.pi)
plt.title('Our first plots')
Note that the
plt.style.use('bmh')
command is not necessary, but it does make nicer looking plots in general. You can useggplot
instead ofbmh
if you want something resembling plots made by R. For a list of options run:print(plt.style.available)
You can also save the objects and interrogate/set their properties, as well as those for the general axes:
hdl = plt.plot(x, cosx)
print(hdl[0].get_color())
hdl[0].set_color('#707010')
hdl[0].set_linewidth(0.5)
plt.grid('off')
Use dir()
or help()
or the online docs to get more info on what
you can do with these.
Histograms and bar charts
For a simple histogram you can do this:
r = np.random.rand(1000)
n,bins,_ = plt.hist((r-0.5)**2, bins=30)
where it also returns the number of elements in each bin, as n
, and
the bin centres, as bins
.
The
_
in the third part on the left hand side is a shorthand for just throwing away the corresponding part of the return structure.
There is also a call for doing bar plots:
samp1 = r[0:10]
samp2 = r[10:20]
bwidth = 0.3
xcoord = np.arange(10)
plt.bar(xcoord-bwidth, samp1, width=bwidth, color='red', label='Sample 1')
plt.bar(xcoord, samp2, width=bwidth, color='blue', label='Sample 2')
plt.legend(loc='upper left')
Scatter plots
It would be possible to use plot()
to create a scatter plot, but
there is also an alternative: scatter()
fig, ax = plt.subplots()
# setup some sizes for each point (arbitrarily example here)
ssize = 100*abs(samp1-samp2) + 10
ax.scatter(samp1, samp2, s=ssize, alpha=0.5)
# now add the y=x line
allsamps = np.hstack((samp1,samp2))
ax.plot([min(allsamps),max(allsamps)],[min(allsamps),max(allsamps)], color='red', linestyle='--')
plt.xlim(min(allsamps),max(allsamps))
plt.ylim(min(allsamps),max(allsamps))
Note that in this case we use the first line return to get a handle to the axis,
ax
, and the figure ,fig
. The axis can be used instead ofplt
in most cases, although thexlim()
andylim()
calls can only be done throughplt
.
In general, figures and subplots can be created in matplotlib in a similar fashion to matlab, but they do not have to be explicitly invoked as you can see from the earlier examples.
Subplots
These are very similar to matlab:
plt.subplot(2, 1, 1)
plt.plot(x,cosx, '.-')
plt.xlim(-np.pi, np.pi)
plt.ylabel('Full sampling')
plt.subplot(2, 1, 2)
plt.plot(x[::30], cosx[::30], '.-')
plt.xlim(-np.pi, np.pi)
plt.ylabel('Subsampled')
Displaying images
The main command for displaying images is imshow()
import nibabel as nib
import os.path as op
nim = nib.load(op.expandvars('${FSLDIR}/data/standard/MNI152_T1_1mm.nii.gz'), mmap=False)
imdat = nim.get_data().astype(float)
imslc = imdat[:,:,70]
plt.imshow(imslc, cmap=plt.cm.gray)
plt.colorbar()
plt.grid('off')
Note that matplotlib will use the voxel data orientation, and that
configuring the plot orientation is your responsibility. To rotate a
slice, simply transpose the data (.T
). To invert the data along along an
axis, you don't need to modify the data - simply swap the axis limits around:
plt.imshow(imslc.T, cmap=plt.cm.gray)
plt.xlim(reversed(plt.xlim()))
plt.ylim(reversed(plt.ylim()))
plt.colorbar()
plt.grid('off')
3D plots
# Taken from https://matplotlib.org/gallery/mplot3d/wire3d.html#sphx-glr-gallery-mplot3d-wire3d-py
from mpl_toolkits.mplot3d import axes3d
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# Grab some test data.
X, Y, Z = axes3d.get_test_data(0.05)
# Plot a basic wireframe.
ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
Surface renderings are many other plots are possible - see 3D examples on the matplotlib webpage
Plotting from standalone scripts
When running from a standalone script, the same matplotlib
import is required,
but the line %matplotlib <backend>
should not be used.
In a script it is also necessary to finish with plt.show()
as
otherwise nothing is actually displayed. For example, the above
examples would setup a plot but the actual graphic would only appear
after the plt.show()
command was executed. Furthermore, control is
not returned to the script immediately as the plot is interactive by default.
Exercise
Find a different type of plot (e.g., boxplot, violin plot, quiver plot, pie chart, etc.), look up the documentation and then write your own code that calls this to create a plot from some data that you create yourself (i.e., don't just blindly copy example code from the docs).
# Make up some data and do the funky plot