Skip to content Skip to sidebar Skip to footer

Calling Gnuplot From Python

I've a python script that after some computing will generate two data files formatted as gnuplot input. How do I 'call' gnuplot from python ? I want to send the following python st

Solution 1:

The subprocess module lets you call other programs:

importsubprocessplot= subprocess.Popen(['gnuplot'], stdin=subprocess.PIPE)
plot.communicate("plot '%s' with lines, '%s' with points;" % (eout,nout))

Solution 2:

Subprocess is explained very clearly on Doug Hellemann's Python Module of the Week

This works well:

import subprocess
proc = subprocess.Popen(['gnuplot','-p'], 
                        shell=True,
                        stdin=subprocess.PIPE,
                        )
proc.stdin.write('set xrange [0:10]; set yrange [-2:2]\n')
proc.stdin.write('plot sin(x)\n')
proc.stdin.write('quit\n') #close the gnuplot window

One could also use 'communicate' but the plot window closes immediately unless a gnuplot pause command is used

proc.communicate("""
set xrange [0:10]; set yrange [-2:2]
plot sin(x)
pause 4
""")

Solution 3:

A simple approach might be to just write a third file containing your gnuplot commands and then tell Python to execute gnuplot with that file. Say you write

"plot '%s' with lines, '%s' with points;" % (eout,nout)

to a file called tmp.gp. Then you can use

from os import system, remove
system('gnuplot -persist tmp.gp')
remove('tmp.gp')

Solution 4:

I was trying to do something similar, but additionally I wanted to feed data from within python and output the graph file as a variable (so neither the data nor the graph are actual files). This is what I came up with:

#! /usr/bin/env python

import subprocess
from sys import stdout, stderr
from os import linesep as nl

def gnuplot_ExecuteCommands(commands, data):
    args = ["gnuplot", "-e", (";".join([str(c) for c in commands]))]
    program = subprocess.Popen(\
        args, \
        stdin=subprocess.PIPE, \
        stdout=subprocess.PIPE, \
        stderr=subprocess.PIPE, \
        )
    for line indata:
        program.stdin.write(str(line)+nl)
    return program

def gnuplot_GifTest():
    commands = [\
        "set datafile separator ','",\
        "set terminal gif",\
        "set output",\
        "plot '-' using 1:2 with linespoints, '' using 1:2 with linespoints",\
        ]
    data = [\
        "1,1",\
        "2,2",\
        "3,5",\
        "4,2",\
        "5,1",\
        "e",\
        "1,5",\
        "2,4",\
        "3,1",\
        "4,4",\
        "5,5",\
        "e",\
        ]
    return (commands, data)

if __name__=="__main__":
    (commands, data) = gnuplot_GifTest()
    plotProg = gnuplot_ExecuteCommands(commands, data)
    (out, err) = (plotProg.stdout, plotProg.stderr)
    stdout.write(out.read())

That script dumps the graph to stdout as the last step in main. The equivalent command line (where the graph is piped to 'out.gif') would be:

gnuplot -e "set datafile separator ','; set terminal gif; set output; plot '-' using 1:2 with linespoints, '' using 1:2 with linespoints" > out.gif
1,12,23,54,25,1
e
1,52,43,14,45,5
e

Solution 5:

I went with Ben's suggestion as I was computing charts from a celery job and found that it would lockup when reading from stdout. I redesigned it like so using StringIO to create the file destined for stdin and subprocess.communicate to get the result immediately via stdout, no read required.

from subprocess import Popen, PIPE
from StringIO import StringIO                                            
from os import linesep as nl

defgnuplot(commands, data):                                                    
    """ drive gnuplot, expects lists, returns stdout as string """              

    dfile = StringIO()                                                          
    for line in data:                                                           
        dfile.write(str(line) + nl)                                             

    args = ["gnuplot", "-e", (";".join([str(c) for c in commands]))]            
    p = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE)                       

    dfile.seek(0)                                                               
    return p.communicate(dfile.read())[0]   

defgnuplot_GifTest():
    commands = [\
        "set datafile separator ','",\
        "set terminal gif",\
        "set output",\
        "plot '-' using 1:2 with linespoints, '' using 1:2 with linespoints",\
        ]
    data = [\
        "1,1",\
        "2,2",\
        "3,5",\
        "4,2",\
        "5,1",\
        "e",\
        "1,5",\
        "2,4",\
        "3,1",\
        "4,4",\
        "5,5",\
        "e",\
        ]
    return (commands, data)

if __name__=="__main__":
    (commands, data) = gnuplot_GifTest()
    print gnuplot(commands, data)

Post a Comment for "Calling Gnuplot From Python"