-
Notifications
You must be signed in to change notification settings - Fork 18
Get a variable from gnuplot #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
pi = gp.get('pi')
Returns a string
|
Thank you very much for the contribution! The problem comes with the "Popen.communicate()" function, as it terminates the pipe after usage: https://stackoverflow.com/questions/25754045/python-subprocess-i-o-operation-on-closed-file |
Oh, I'm sorry, I hurried. import sys
from subprocess import PIPE, Popen
from threading import Thread
try:
from queue import Queue, Empty
except ImportError:
from Queue import Queue, Empty # python 2.x
ON_POSIX = 'posix' in sys.builtin_module_names
def enqueue_std(out, queue):
for line in iter(out.readline, ''):
queue.put(line)
out.close()
class Gnuplot(object):
"""docstring for Gnuplot"""
def __init__(self):
self.p = Popen(['gnuplot', '-p'], stdin=PIPE, stderr=PIPE, stdout=PIPE, bufsize=1,
close_fds=ON_POSIX, shell=False, universal_newlines=True)
self.q_err = Queue()
self.t_err = Thread(target=enqueue_std, args=(self.p.stderr, self.q_err))
self.t_err.daemon = True # thread dies with the program
self.t_err.start()
self.q_out = Queue()
self.t_out = Thread(target=enqueue_std, args=(self.p.stdout, self.q_out))
self.t_out.daemon = True # thread dies with the program
self.t_out.start()
def c(self, command):
self.p.stdin.write(command + '\n') # \n 'send return in python 2.7'
self.p.stdin.flush() # send the command in python 3.4+
def get(self, variable, timeout=0.1):
self.p.stdin.write('print ' + variable + '\n')
# read line without blocking
try:
line = self.q_err.get(timeout=timeout) # or .get_nowait()
return line
except Empty:
return NoneUse library: #!/usr/bin/env python3
from gnuplot import Gnuplot as gp
figure1 = gp()
figure1.c('set terminal postscript eps color enhanced "Helvetica" 30')
figure1.c('set output "%s"' % 'result.ps')
figure1.c('set size 1.25,1.33')
figure1.c('set pointsize 2')
figure1.c('set nokey')
figure1.c('set linestyle 1 linetype -1 linewidth 1')
figure1.c('set xlabel "Detector"')
figure1.c('set ylabel "Calibration Quantity"')
figure1.c('set title "Title"')
figure1.c('plot sin(x)')
my_pi = figure1.get('pi')
print(my_pi)And: |
|
Thanks again, This is a good find, and seems to work. In fact, the communicate function also seems use a thread for the readout I will experiment with the options a little and see what works best. |
|
I will use your suggested code since it is very clean and works very well! |
|
I made small edits. import sys
from subprocess import PIPE, Popen
from threading import Thread
try:
from queue import Queue, Empty
except ImportError:
from Queue import Queue, Empty # python 2.x
ON_POSIX = 'posix' in sys.builtin_module_names
class Gnuplot(object):
"""docstring for Gnuplot"""
def __init__(self):
self.p = Popen(['gnuplot', '-p'], stdin=PIPE, stderr=PIPE, stdout=PIPE, bufsize=1,
close_fds=ON_POSIX, shell=False, universal_newlines=True)
self.q_err = Queue()
self.t_err = Thread(target=self.enqueue_std, args=(self.p.stderr, self.q_err))
self.t_err.daemon = True # thread dies with the program
self.t_err.start()
self.q_out = Queue()
self.t_out = Thread(target=self.enqueue_std, args=(self.p.stdout, self.q_out))
self.t_out.daemon = True # thread dies with the program
self.t_out.start()
def enqueue_std(self, out, queue):
for line in iter(out.readline, ''):
queue.put(line)
out.close()
def c(self, command):
self.p.stdin.write(command + '\n') # \n 'send return in python 2.7'
self.p.stdin.flush() # send the command in python 3.4+
def get_c(self, vtype=str, timeout=0.1):
# read line without blocking
lines = []
while True:
try:
line = self.q_err.get(timeout=timeout) # or .get_nowait()
lines.append(vtype(line.strip()))
except Empty:
break
return lines
def get(self, variable, vtype=float, timeout=0.1):
# clean buffer before put command
self.get_c()
self.p.stdin.write('print ' + variable + '\n')
# read line without blocking
try:
line = self.q_err.get(timeout=timeout) # or .get_nowait()
return vtype(line.strip())
except Empty:
return Noneuse: #!/usr/bin/env python3
from gnuplot import Gnuplot as gp
figure1 = gp()
figure1.c('set terminal postscript eps color enhanced "Helvetica" 30')
figure1.c('set output "%s"' % 'result.ps')
figure1.c('set size 1.25,1.33')
figure1.c('set pointsize 2')
figure1.c('set nokey')
figure1.c('set linestyle 1 linetype -1 linewidth 1')
figure1.c('set xlabel "Detector"')
figure1.c('set ylabel "Calibration Quantity"')
figure1.c('set title "Title"')
figure1.c('set fit logfile "/dev/null"')
figure1.c('set fit quiet')
figure1.c('FIT_LIMIT = 1e-6')
figure1.c('f(x) = m*x**2 + b')
figure1.c('fit f(x) "calibration.data" using 1:2 via m, b')
figure1.c('plot "calibration.data" using 1:2, f(x) w l')
# !!! wrong command !!!
figure1.c('wrong command')
log = figure1.get_c()
print("\n".join(log))
m = figure1.get('m')
b = figure1.get('b')
m_err = figure1.get('m_err')
b_err = figure1.get('b_err')
print("m = {0}".format(m))
print("b = {0}".format(b))
print("m_err = {0}".format(m_err))
print("b_err = {0}".format(b_err))I do not know how to check the result of the execution of each command. The timeout is now used, since the execution of a command in gnuplot may take some time. If you check after each command, it will be very slow. |
|
I also found it very strange: gnuplot does not use stdout. It sends the entire message (data output or error messages) to strerr! |
|
Wow! Just need to read the documentation. To separate messages into errors and data, you need to say in the object's constructor: self.c('set print "-"') |
|
Thats actually explains a lot, also why my earlier attempts to just read stdout failed. |
Sometimes it is required to get the values of variables from gnuplot. For example after:
Now from Python you can access these variables.