microcoded
Plotting with IPython

Visualizing your data can be both fun and useful. One simple yet powerful tool for doing this is IPython. I recently got set up with this framework and this post is sort of a brain dump of that process.

First, make sure you have pip installed. If you use python, at some point you’ll need this package installer. Next, install IPython:

pip install ipython

You’ll also need matplotlib for rendering all those nice graphs. This one is a bit of a pain to build from source, so I suggest grabbing the binary unless you like epic build system adventures. matplotlib also requires the dateutil and pyparsing packages:

pip install python-dateutil

pip install pyparsing

We’re now good to go. You can launch IPython with the —pylab argument to import a set of useful symbols into the global scope.

ipython —pylab

This will launch IPython in the console, opening a separate window for the plots when the relevant functions are called.

We can plot a simple sine like this:

plot(sin(linspace(0,2*pi, 100)))

image

Here linspace(a, b, c) creates a set of c evenly spaced numbers in the interval [a, b]. IPython is real handy in this case. Appending a ? after an object will give you a man page for it. The introductory tutorial is a good place to start.

image

It’s worth studying the matplotlib docs too. At first glance the library looks like it can create simple graphs but you can do some serious visualization with it. Not to mention it can do xkcd style renders. The matplotlib tags on stackoverflow are also a pretty good resource.

Let’s try something fancier. We can plot a square wave by creating a piecewise function.

x = linspace(0, 2 * pi, 100)
f = piecewise(x, [x < pi, x >= pi], [1, -1])
axis([0, 2 * pi, -1.5, 1.5])
plot(x, f)

x holds our discrete horizontal axis and piecewise gives us the values satisfying the piecewise conditions for our vertical axis.

image

We can also approximate this signal by accumulating the non-zero Fourier coefficients of its Fourier series.

num_coeffs = 4
fs = sum((4 / pi) * array([sin((2 * n + 1) * x) / (2 * n + 1) for n in range(num_coeffs)]), 0)
plot(x, fs)

image

How about doing something useful to computer graphics. Let’s say you need to create a random sampling pattern. The following snippet generates a set of six random pairs sampled from the unit square.

num_samples = 6
taps = rand(num_samples * 2) * 2 - 1
taps = append(taps, [-1 * a for a in taps])
axis([-1.5, 1.5, -1.5, 1.5])
scatter(taps[0::2], taps[1::2], 40, ‘bgrcmybgrcmy’)

image

In some cases you tend to rotate the sample kernel to simulate a larger amount of different samples. In that case it’s useful to see what kind of sampling coverage we get from the rotation.

def rot(x, y, a):
    cs = cos(a)
    sn = sin(a)
    px = x * cs - y * sn
    py = x * sn + y * cs
    return px, py

res = 32
for f in range(res):
    x, y = rot(taps[0::2], taps[1::2], (f+1)*2*pi/res)
    scatter(x, y, 40, ‘bgrcmybgrcmy’)

image

I recommend installing the Python Imaging Library, if you don’t already have it. matplotlib has support for png and with PIL you get pretty much all the other image formats too. There’s no dxt support as far as I know, but there’s loaders to be found if you don’t want to write your own. With an image loaded there’s loads of fun operations that can be done. Diffing two versions for example.

import matplotlib.image as mpimg
l0 = mpimg.imread(‘path_to_img_0’)
l1 = mpimg.imread(‘path_to_img_1’)
imshow(l0-l1);

That wasn’t that fun, but it could be useful. l0 is this jpg and l1 is the same image after having been opened with Paint.NET and re-saved as a max quality jpg. This is the difference:

image

And here’s the difference between the original and the same image after having been opened and re-saved another three times.

image

It gets way worse! The file format is lossy, but you’d think not changing the image wouldn’t cause it to be re-compressed on a save.

Another handy feature of IPython is the interactive web-based notebook environment. You can launch it with

ipython notebook —pylab inline

inline tells it to display the plots inline instead of launching a separate window.

These notebooks can be saved as static html pages or displayed with the awesome Computable app on your iPad. You can also export them as json (.ipynb) and put them in a Gist and view them with the nbviewer.

Here’s the notebook with all of the above snippets as an example. Have fun plotting!