Emil Loer dot com

Plotting command line output

Posted on July 09, 2011

Consider the following piece of Python code:

import math

class RCFilter:
    def __init__(self, decaytime):
        self.output = 0.0
        self.coeff = 1.0 - math.exp(-1.0 / decaytime)

    def apply(self, input):
        self.output += self.coeff * (input - self.output)
        return self.output

This is a simple one-pole lowpass RC-filter, frequently used as a smoother for parameters that change over time but should never be changed instantly. You instantiate the class with a time coefficient which indicates how many samples it it should take to reach a ratio of 1 / e between the old and the new value. After that you can call apply to smooth out an input signal.

Now, we want to test the behaviour of this filter with a given signal. This can be done as follows:

filter = RCFilter(10.0)

for i in xrange(40):
    print filter.apply(1.0)
for i in xrange(80):
    print filter.apply(0.0)

Now we have generated 120 samples, but from the numbers alone it is hard to see what is happening. However, we can use some command line magicks to turn this into a plot. For this we are going to use Gnuplot, which should be available in your favourite package manager.

In order to make the plotting as simple as possible, we want to invoke it as a command line script that reads numbers from standard input and presents a plot on screen. This way we can pipe any program we write directly to our plot script.

The hard part is getting Gnuplot to read stuff from the standard input stream of the invoking script. This is not trivial because Gnuplot flushes its own input stream and assumes that standard input is the same stream as the one that is used to enter the plot commands. That means we can only get this working if we concatenate the script and standard input. The Gnuplot commands to plot data from what Gnuplot considers the input stream are like this:

set term pdfcairo enhanced color solid \
    font "Helvetica Neue,8" lw 5 size 8,6;
plot "-" with lines title "";

These commands tell Gnuplot to produce a PDF file which has been rendered using Cairo. This gives us the best visual result. If you want to use PNG output you can use the pngcairo engine instead, although I recommend using a tool like ImageMagick for the conversion because it generates better antialiased results and can handle transparency if you need it. We also set some good looking appearance settings, such as font, line width and output size (in inches at 72 dpi). The second line is the actual plot line and can of course be modified if you want a bar chart instead of a line chart or whatever.

Using these commands directly will not work because we have not yet concatenated anything. To do that we will wrap the Gnuplot commands in a Bash script, like this:

#/bin/bash
(
    echo "
        set term pdfcairo enhanced color solid \
            font \"Helvetica Neue,8\" lw 5 size 8,6; 
        plot \"-\" with lines title \"\""; 
    cat -
) | gnuplot | open -f -a Preview

Now we have our plot commands concatenated with the script’s standard input and pipe that to Gnuplot. This produces a PDF file in standard output which we can pipe to our favourite display program. The open command is Mac OS X specific and giving it the -f -a Preview argument tells it to write standard input to a temporary file and open that file with Preview. For Linux you can use display, xdg-open, eog or whatever.

Now when we run our Python filter script and pipe it to this plot script we get the following window:

Because the generated PDF file contains a vector representation of the plot, you can resize the plot to whatever size you need without any loss of detail.