#this is just for -pi %load_ext gist
I (Paul Ivanov) polled the class, and it seemed like people were unfamiliar with just basic plotting, so we started off with that.
I started off by explaining that, by default, matplotlib's pyplot interface is imported when we enable IPython's %pylab mode.
%pylab inline
Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.kernel.zmq.pylab.backend_inline]. For more information, type 'help(pylab)'.
import matplotlib
Here's how you can do that in your python scripts (without IPython's pylab mode)
import matplotlib.pyplot as plt
I opened up the Matplotlib website, and in particular, the Matplotlib Gallery...
plt
<module 'matplotlib.pyplot' from '/home/pi/.local/lib/python2.7/site-packages/matplotlib-1.3.x-py2.7-linux-x86_64.egg/matplotlib/pyplot.pyc'>
We grabbed a link of some example code we found in the gallery, just to play with it interactively
%load http://matplotlib.org/mpl_examples/api/histogram_demo.py
x, y = np.arange(10), np.sin(np.arange(10))
plt.plot(x, y, 'ro')
[<matplotlib.lines.Line2D at 0x5971c90>]
plt.scatter(x, y, s=np.cos(x)*100, c=)
<matplotlib.collections.PathCollection at 0x6223490>
p = patches[0]
p.get_facecolor()
(0.0, 0.0, 1.0, 1.0)
R, G, B, A
p.set_facecolor('g')
counts, locs, patches = plt.hist(np.random.randn(5000), bins=100)
for x in range(25, 75):
p = patches[x]
p.set_facecolor('g')
p
<matplotlib.patches.Rectangle at 0x7abcd90>
This example shows us how to make changes to a plot based on keyboard input. This does not work if our matplotlib backend is set to inline, since that just generates static images. Set the backend to an interactive one (qt, tk, wx, or macosx)
%pylab qt
Welcome to pylab, a matplotlib-based Python environment [backend: Qt4Agg]. For more information, type 'help(pylab)'.
%load http://matplotlib.sourceforge.net/examples/event_handling/keypress_demo.py
#!/usr/bin/env python
"""
Show how to connect to keypress events
"""
from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt
import sys
def press(event):
print('press', event.key)
sys.stdout.flush()
if event.key=='x':
visible = xl.get_visible()
xl.set_visible(not visible)
fig.canvas.draw()
fig = plt.figure()
ax = fig.add_subplot(111)
fig.canvas.mpl_connect('key_press_event', press)
ax.plot(np.random.rand(12), np.random.rand(12), 'go')
xl = ax.set_xlabel('easy come, easy go')
plt.show()
x press alt press alt press a press a press a press a press a press b press b press p press p press x press x press x press x press alt
Now modify the example above to pan left and right the width of the current view using ,
and .
keys
plt.plot(np.sin(np.arange(100)))
[<matplotlib.lines.Line2D at 0x3dc0d10>]
%load http://matplotlib.sourceforge.net/examples/event_handling/keypress_demo.py
ax = plt.gca()
ax.get_xlim()
(7.5219586089047414, 12.161979327136788)
ax.set_xlim(7, 20)
plt.draw()
#!/usr/bin/env python
"""
Show how to connect to keypress events
"""
from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt
def press(event):
x0, x1 = ax.get_xlim()
dx = x1 - x0
if event.key==',':
ax.set_xlim(x0-dx, x1-dx)
plt.draw()
if event.key=='.':
ax.set_xlim(x0+dx, x1+dx)
plt.draw()
fig = plt.figure()
ax = fig.add_subplot(111)
fig.canvas.mpl_connect('key_press_event', press)
ax.plot(np.sin(np.arange(100)), 'go--')
plt.show()
Here's some code I (pi) wrote to do basic, interactive orthogonal slicer.
We will go through the code to understand the individual parts, running the next cell will create a file called orthoslicer.py
on your machine. If you get an error, you are using at older version of IPython where the %%file
magic was not available
%%file orthoslicer.py
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.image import AxesImage
import numpy as np
# assuming the following layout
# <-- y --> <-- z -->
# ^ +---------+ ^ +---------+
# | | | | | |
# | | | |
# x | | x | |
# | | | |
# | | | | | |
# v +---------+ v +---------+
#
# <-- z -->
# ^ +---------+
# | | |
# | |
# y | |
# | |
# | | |
# v +---------+
#
class OrthoSlicer3D(object):
"""Orthogonal-plane slicer.
OrthoSlicer3d expects 3-dimensional data, and creates a figure with 3
axes for each slice orientation. Moving the mouse in any one axes will
select out the corresponding slices in the other two. Clicking the right
mouse button toggles mouse following and triggers a full redraw (to update
the ticks, for example). Scrolling up and down moves that slice up and
down.
Example
-------
import numpy as np
a = np.sin(np.linspace(0,np.pi,20))
b = np.sin(np.linspace(0,np.pi*5,20))
data = np.outer(a,b)[..., np.newaxis]*a
OrthoSlicer3D(data)
"""
def __init__(self, data, axes=None, aspect_ratio=np.array((1,1,1))):
"""
Parameters
----------
data : ndarray (3d)
The data that will be displaced by the slicer
axes : mpl.Axes (3)
3 axes instances for the Z, Y, and X slices, or None (default)
aspect_ratio : ndarray (length 3)
stretch factors for X,Y,Z directions (default: 1,1,1)
"""
if axes is None:
fig = plt.figure()
x,y,z = data.shape * aspect_ratio
maxw = float(z+y)
maxh = float(y+x)
zw = y / maxw
zh = x / maxh
yw = z / maxw
ax1 = fig.add_axes((0, 1.0-zh, zw, zh))
ax2 = fig.add_axes((zw, 1.0-zh, yw, zh))
ax3 = fig.add_axes((zw, 0.0 , yw, 1.0-zh))
axes = (ax1, ax2, ax3)
else:
ax1, ax2, ax3 = axes
self.data = data
kw = dict(vmin=data.min(), vmax=data.max(), picker=True,
aspect='auto')
im1 = ax1.imshow(data[...,0], **kw)
im2 = ax2.imshow(data[:,0,:], **kw)
im3 = ax3.imshow(data[0,...], **kw)
# idx will be used to slice in to the data with the appropriate
# slicing scheme
im1.idx = im2.idx = im3.idx = 0
# set the maximum dimensions for i%dim indexing
im1.size = data.shape[-1]
im2.size = data.shape[-2]
im3.size = data.shape[-3]
im1.get_slice = lambda i: (slice(None), slice(None), i)
im2.get_slice = lambda i: (slice(None), i, slice(None))
im3.get_slice = lambda i: (i, slice(None), slice(None))
# setup pairwise connections between the slice dimensions
im1.imx = im2
im1.imy = im3
im2.imx = im1
im2.imy = im3
im3.imx = im1
im3.imy = im2
self.toggle_update = True
self.figs = set([ax.figure for ax in axes])
for fig in self.figs:
#fig.canvas.mpl_connect('pick_event', self.on_pick)
fig.canvas.mpl_connect('motion_notify_event', self.on_pick)
plt.show()
def on_pick(self, event):
# Here we do a bit of a hack to make mousemovement events fit the mold
# of a pick event
if hasattr(event,'inaxes') and event.inaxes:
artist = event.inaxes.images[0]
me = event
me.button = 1 if self.toggle_update else 0
elif hasattr(event, 'artist'):
artist = event.artist
me = event.mouseevent
else:
return
if isinstance(artist, AxesImage):
im = artist
ax = artist.axes
imx,imy = im.imx, im.imy
if me.button == 1: # or self.toggle_update:
#if me.button == 1:
# self.toggle_update = not self.toggle_update
x,y = np.round((me.xdata, me.ydata)).astype(int)
imx.set_data(self.data[imx.get_slice(x)])
imy.set_data(self.data[imy.get_slice(y)])
imx.idx = x
imy.idx = y
for i in imx, imy:
ax = i.axes
ax.draw_artist(i)
ax.figure.canvas.blit(ax.bbox)
return
if me.button == 3:
self.toggle_update = not self.toggle_update
# the axes might be in different figures, redraw all of them
#for fig in self.figs:
# fig.canvas.draw() # redraw the ticks which don't get blitted
plt.draw()
return
if me.button not in ('up', 'down'):
return
if me.button == 'up':
im.idx += 1
elif me.button == 'down':
im.idx -= 1
im.idx %= im.size
im.set_data(self.data[im.get_slice(im.idx)])
ax.draw_artist(im)
ax.figure.canvas.blit(ax.bbox)
if __name__ == '__main__':
import numpy as np
a = np.sin(np.linspace(0,np.pi,20))
b = np.sin(np.linspace(0,np.pi*5,20))
data = np.outer(a,b)[..., np.newaxis]*a
# all slices
OrthoSlicer3D(data)
# broken out into three separate figures
f, ax1 = plt.subplots()
f, ax2 = plt.subplots()
f, ax3 = plt.subplots()
OrthoSlicer3D(data, axes=(ax1, ax2, ax3))
Overwriting orthoslicer.py
run orthoslicer.py