benschneider / pygnuplot Goto Github PK
View Code? Open in Web Editor NEWPython interface to gnuplot
License: MIT License
Python interface to gnuplot
License: MIT License
The easiest way I found is the following:
from PyGnuplot import gp
from IPython.display import Image
def set_jpeg(g0, out_file):
g0.default_term = 'jpeg'
g0.file = out_file
g0.c('set out "' + str(g0.file) + '"')
g0.c('set term ' + g0.default_term)
return g0.a()
g1 = gp()
set_jpeg(g1, 'g1.jpeg')
g1.a('plot sin(x)') # gnuplot writes plot to 'g1.jpeg'
Image(g1.file) # shows the plot for g1 (g1.jpeg)
>>> import PyGnuplot as gp
>>> gp.c('plot sin(x)')
>>> gp.pdf('graph.pdf')
>>>
gnuplot> set term pdf enhanced size 14cm, 9cm color solid fsize 12 fname 'Helvetica';
^
line 0: unrecognized terminal option
Note: I have x11, aqua, and pdfcario terminals but not plain pdf. It looks as though pdfcario can't handle the "fsize and fname" arguments. It does accept: "font 'Helvetica,12"
Not working:
gnuplot> set term pdf enhanced size 14cm, 9cm color solid fsize 12 fname 'Helvetica'
Terminal type is now 'pdfcairo'
^
unrecognized terminal option
gnuplot> set term pdf enhanced size 14cm, 9cm color solid fname 'Helvetica'
Terminal type is now 'pdfcairo'
^
unrecognized terminal option
gnuplot> set term pdf enhanced size 14cm, 9cm color solid
Terminal type is now 'pdfcairo'
Options are ' transparent enhanced fontscale 0.5 size 14.00cm, 9.00cm '
This works:
gnuplot> set term pdf enhanced size 14cm, 9cm color solid font 'Helvetica,12'
Terminal type is now 'pdfcairo'
Options are ' transparent enhanced font "Helvetica,12" fontscale 0.5 size 14.00cm, 9.00cm '
First of all, thanks for the awesome library PyGnuplot!
I got a cryptic error message upon starting python (2.7) and trying to "import PyGnuplot":
$ python
Python 2.7.13 (default, Aug 22 2020, 10:03:02)
[GCC 6.3.0 20170516] on linux2
Type "help", "copyright", "credits" or "license" for more information.
import PyGnuplot
Traceback (most recent call last):
File "", line 1, in
File "/home/pi/.local/lib/python2.7/site-packages/PyGnuplot.py", line 112, in
fl = _FigureList()
File "/home/pi/.local/lib/python2.7/site-packages/PyGnuplot.py", line 30, in init
proc = _Popen(['gnuplot', '-p'], shell=False, stdin=_PIPE, universal_newlines=True) # persitant -p
File "/usr/lib/python2.7/subprocess.py", line 390, in init
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1024, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
Not a very informative error message, right? It turned out (after I did a lot of head scratching and searching the internet) that the problem was that gnuplot itself was not installed on my machine! (It's a raspberry pi running Linux 4.19.66-v7+ ) Installing gnuplot fixed it.
I know this is not really the fault of PyGnuplot per se, but it could save some more head scratching by others if PyGnuplot checked that the gnuplot binary was installed and accessible. :-)
Or, hopefully if I put the error message here others will find it.
Thanks again for the great library.
Hello,
isn't it possible to close the running gnuplot process via PyGnuplot? By calling it through a subprocess without PyGnuplot it is, but using PyGnuplot I couldn't manage.
The background is to implement a routine for me which plots live data and saves a pdf/jpg at request. As seperated scripts both (saving and plotting) can easily be done with PyGnuplot, but whenever I try to do both in one script gnuplot dangles. (I think ending one gnuplot session before the next one will start would fix the issue)
Greetings
Franz
The routine PyGnuplot.s for storing data in a file has 2 major restrictions:
So when you try to use a series of integers for the X-axis, you get messy results:
Not sure if there are any long term implications, but the data is also stored with comma separators. Gnuplot documentation does state that whitespace is the default separator. There are options to choose comma or other characters. You may be relying on gnuplot currently being tolerant in its input parsers. Its not obvious that this is guaranteed to stay that way going forward.
There's a small issue, which is that "gnuplot" isn't a name that works in cmd and popen can't find it.
I would suggest having a "gnuplot_adress" at top to make it easier to change. The below works for me on win10
from subprocess import Popen as _Popen, PIPE as _PIPE
default_term = 'wxt' # change this if you use a different terminal
gnuplot_address = r"C:\Program Files\gnuplot\bin\gnuplot.exe"
class _FigureList(object):
def __init__(self):
proc = _Popen([gnuplot_address, '-p'], shell=False, stdin=_PIPE, universal_newlines=True) # persitant -p
self.instance = {0 : [proc, default_term]} # {figure number : [process, terminal type]}
self.n = 0 # currently selected Figure
# Format:
# instance[self.n][0] = process
# instance[self.n][1] = terminal
def figure(number=None):
'''Make Gnuplot plot in a new Window or update a defined one figure(num=None, term='x11'):
>>> figure(2) # would create or update figure 2
>>> figure() # simply creates a new figure
returns the new figure number
'''
if not isinstance(number, int): # create new figure if no number was given
number = max(fl.instance) + 1
if number not in fl.instance: # number is new
proc = _Popen([gnuplot_address, '-p'], shell=False, stdin=_PIPE, universal_newlines=True)
fl.instance[number] = [proc, default_term]
fl.n = number
c('set term ' + str(fl.instance[fl.n][1]) + ' ' + str(fl.n))
return number
First of all, thanks for the library. That is pretty much what I was looking for - a simple interface to gnuplot.
However, I was a bit unsatisfied with the figure handling. After I had plotted multiple figures and I wanted to zoom into one of them, after zooming out it replotted the last figure instead of the active figure. For example, after plotting data in 3 different figures, I want to zoom into figure(2). When I want to zoom out again, I hit "a", but instead of zooming out, it replotted figure(3). I checked and this is indeed a problem with Gnuplot, and not with your script. Also, all changes with PyGnuplot.c() are valid for all figures later on, which is sometimes annoying.
Therefore, I have updated your script so that for each figure a new Gnuplot-subprocess is started. Now, PyGnuplot.figure() switches between completely independent Gnuplot sessions.
The parts that I have changed:
class _emptyClass(object):
def __init__(self):
self.figNum = [1]
self.figNum[0] = 1
self.proc = [1]
self.proc[0] = _Popen(['gnuplot', '-p'], shell=False, stdin=_PIPE) # persitant -p
`_vc = _emptyClass()` `proc = _vc.proc[0]`
def figure(number=None, term='x11'):
'''Make Gnuplot plot in a new Window or update a defined one
figure(num=None, term='x11'):
>>> figure(2) # would create or update figure 2
>>> figure() # simply creates a new figure
returns the new figure number
'''
global proc
if not isinstance(number, int):
number = _vc.figNum[-1]+1
if number not in _vc.figNum:
_vc.proc.append(_Popen(['gnuplot', '-p'], shell=False, stdin=_PIPE)) # persitant -p
_vc.figNum.append(number)
_vc.figNum.sort()
proc = _vc.proc[_vc.figNum.index(number)]
c('set term '+str(term)+' '+str(number))
return number
`
Hello,
I'm using this library for a work project that needs to run on Linux and Windows with Gnuplot 5.4.8
I'm currently trying to produce an SVG from a gnuplot script generated with jinja, but I immediately noted that I was getting no response from gnuplot, "r" and "a" functions always returned an empty list.
First I tested the script obtained from jinja, using it directly from command line, and it worked.
So i digged a bit and I figured out that gnuplot was outputting on stdout, instead PyGnuplot was reading stderr.
I fixed the code by changing line 89 in PyGnuplot.py from:
line = self.q_err.get(timeout=timeout)
to:
line = self.q_out.get(timeout=timeout)
It works for me, both on linux and windows, but i don't know if it works on every platform this library supports, and since it was made differently I'd like to ask more about this issue and if my fix could be a valid solution.
Is PyGnuplot supported on Python 3.6.1 on Windows 7?
Loosely following the example in the online help text, the PyGnuplot.p and PyGnuplot.c functions are getting the error :
File "C:\WinPython\python-3.6.1.amd64\lib\site-packages\PyGnuplot.py", line 63, in c
proc.stdin.write(command + '\n') # \n 'send return'
TypeError: a bytes-like object is required, not 'str'
Yes, Gnuplot 5.2.0 is correctly installed and PATH variable updated for gnuplot/bin
Here is my actual code:
import PyGnuplot
print ("Setup data for graph")
x = [] ; y = []; z = [] ; w = [];# empty lists
for i in (range (17)):
x.append(i)
y.append(i*3)
z.append(i**2)
w.append(-i)
print ("x:", x, type(x))
print ("y:",y ,type(y))
print ("z:",z ,type(z))
print ("w:", w, type(w))
import sys
self=sys.argv[0]
import os
file = os.path.basename(self)
(fn, ft) = os.path.splitext(file)
print ("\nself:", self, "file:", file, "fn:", fn, "ft:", ft)
dat_fn = fn+".dat"
fmt="png"
out_fn = fn+"."+fmt
trc_fn = fn+".gnu" ;# save gnuplot commands for debugging
print ("dat_fn:", dat_fn, "fmt:", fmt, "out_fn:", out_fn, "trc_fn:",trc_fn)
print ("\nSave data to:", dat_fn)
rc = PyGnuplot.s([x, y, z, w], filename=dat_fn)
print ("s rc:", rc, type(rc))
import traceback
try:
rc = PyGnuplot.p(filename=out_fn)
print ("p rc:", rc, type(rc))
except:
(x,y,z)=sys.exc_info()
print("x=",x,"\ny=",y,"\nz=",z)
traceback.print_exc()
cmd_setup = ""
cmd_plot = 'plot dat_fn u 1:2 w lp'
cmd_cleanup = ""
cmd = cmd_setup+"\n"+cmd_plot+"\n"+cmd_cleanup
print ("gnuplot cmd:", cmd)
try:
rc = PyGnuplot.c('plot "tmp.dat" u 1:2 w lp')
print ("c rc:", rc, type(rc))
except:
(x,y,z)=sys.exc_info()
print("x=",x,"\ny=",y,"\nz=",z)
traceback.print_exc()
Here is the runtime output:
================= RESTART: C:\JOHN_MIS\PY_EX\pygnuplot_ex.py =================
Setup data for graph
x: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] <class 'list'>
y: [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48] <class 'list'>
z: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256] <class 'list'>
w: [0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16] <class 'list'>
self: C:\JOHN_MIS\PY_EX\pygnuplot_ex.py file: pygnuplot_ex.py fn: pygnuplot_ex ft: .py
dat_fn: pygnuplot_ex.dat fmt: png out_fn: pygnuplot_ex.png trc_fn: pygnuplot_ex.gnu
Save data to: pygnuplot_ex.dat
s rc: None <class 'NoneType'>
x= <class 'TypeError'>
y= a bytes-like object is required, not 'str'
z= <traceback object at 0x0000000003C2CD88>
Traceback (most recent call last):
File "C:\JOHN_MIS\PY_EX\pygnuplot_ex.py", line 51, in
rc = PyGnuplot.p(filename=out_fn)
File "C:\WinPython\python-3.6.1.amd64\lib\site-packages\PyGnuplot.py", line 86, in p
str(fontsize) + " font 'Calibri';")
File "C:\WinPython\python-3.6.1.amd64\lib\site-packages\PyGnuplot.py", line 63, in c
proc.stdin.write(command + '\n') # \n 'send return'
TypeError: a bytes-like object is required, not 'str'
gnuplot cmd:
plot dat_fn u 1:2 w lp
x= <class 'TypeError'>
y= a bytes-like object is required, not 'str'
z= <traceback object at 0x0000000003C32248>
Traceback (most recent call last):
File "C:\JOHN_MIS\PY_EX\pygnuplot_ex.py", line 65, in
rc = PyGnuplot.c('plot "tmp.dat" u 1:2 w lp')
File "C:\WinPython\python-3.6.1.amd64\lib\site-packages\PyGnuplot.py", line 63, in c
proc.stdin.write(command + '\n') # \n 'send return'
TypeError: a bytes-like object is required, not 'str'
hi, is this going to support python3?
As part of debugging prior issues, I learned a trick to get gnuplot to basically send some info back to me at the end of a command set. This was done to diagnose the commands being tested. At the end of the command set, I would add the following:
cmd_cleanup = "show output; unset output"
The show output would give me the filename of where the png/jpeg file was going to be stored. The unset would tell gnuplot to flush the output and release file system locks on it. If I got a different message, that gave me a clue that the most recent command I had sent was malformed and needded work.
Anyway, PyGnuplot does not currently turn on stdout or stderr as part of the instantiation command.
You would need something like:
proc = _Popen(['gnuplot', '-p'], shell=False, stdin=_PIPE, stdout=_PIPE, stderr=_PIPE) # persitant -p
and later on in .c method do: out,err = proc.communicate() ;# gives a tuple
Maybe .c method could return out,err? Also print them to the console?
While having the --persist flag as a default for GnuPlot is nice, it would be great to be able to turn it off in some situations, along with sending additional arguments to gnuplot.
hello,
is there a way to output as a png or jpg format. ps or pdf I cannot use for web usage.
tried to convert ps to png/jpg but its not usable for this.
maybe its already exportable? but how
Thanks
Hello.
using :
gp.c("set xtics format '%d.%m\n%h'")
I'm getting a invalid command. cause of \n . normally this works.
here you can see.
https://stackoverflow.com/questions/25763576/gnuplot-how-to-set-new-line-in-xtics-timefmt
I tried same command with """ """ quoting. no luck.
what can I do?
Thank you!
Hi Ben,
For analyzing data, I often run the same python script in parallel, with slightly different parameters. In this case saving the values to be plotted sometimes cause interferences. It is in this case helpful to pipe data directly into gnuplot instead of saving a file first. Fortunately gnuplot provides the
plot "-"
option.
I have changed the plot-function, so that it can take multiple data points to be plotted and as well as strings with the plot option, such as:
plot([x,y],"u 1:2 w p ls 1",[x2,y2],"u 1:2 w l ls 2")
The plot function:
def plot(data,*args): """ Sends data to gnuplot via pipe """
x,y = data
# identifier necessary to check whether two consecutive arguments are strings
lastdata = 1
# create data string
data_string = ''
for i in range(np.size(x)):
data_string = data_string +('%lf %lf\n'%(x[i],y[i]))
data_string = data_string+'e\n'
# create plot string
plot_string = 'plot "-"'
# Now go through all arguments and check whether it is a data, or a string with plot
# specification
for i in range(len(args)):
arg = args[i]
if type(arg) == str:
if lastdata == 1:
plot_string = plot_string+arg
lastdata=0
else:
print("Error!! Data expected in %d argument!"%i)
break
elif type(arg)==list:
if lastdata==1:
plot_string = plot_string+" u 1:2 notitle w p "
x,y = arg
for i in range(np.size(x)):
data_string = data_string +('%lf %lf\n'%(x[i],y[i]))
data_string = data_string+'e\n'
plot_string = plot_string+', "-"'
lastdata=1
else:
print("Wrong data type in argument %d "%i)
print("Str or List expected, but "+type(arg)+" found!")
break
if lastdata==1:
plot_string = plot_string+" u 1:2 notitle w p "
# Send plot_string to gnuplot
c(plot_string)
# Send data_string to gnuplot
c(data_string)
`
Please, create a Debian package for Debian and Ubuntu and/or vote for the packaging process at Ubuntu, see https://bugs.launchpad.net/ubuntu/+bug/1774773
Running your example.py as is, there are no error messages, the example.out file is created OK, but NO example.pdf output file is created.
I did some experiments to see what sort of error handling/reporting occurs. The line pg.c("plot 'foo.bar'") generates no errors at all. When you give the same command to a gnuplot terminal window, you get:
gnuplot> plot 'foo.bar'
warning: Cannot find or open file "foo.bar"
No data in plot
gnuplot>
My own code sends the following multiple command set as a single line to gnuplot:
set output "pygnuplot_ex.png";set terminal png transparent nocrop enhanced font arial 12 size 400,400;set key autotitle columnhead;set title "Lines Points Example";set xlabel "X-axis Title";set ylabel "Y-axis Title" rotate by 90;set style data linespoints;set xtics rotate by 90;plot "pygnuplot_ex.dat" using 2:xtic(1) , '' using 3 , '' using 4;unset output
When run by PyGnuplot.c, there is no error, but also NO output .png file. The same string pasted into a gnuplot terminal window DOES correctly generate a .png file
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.