# $Id: gp_java.py 291 2006-03-03 08:58:48Z mhagger $
# Copyright (C) 2002-2003 Michael Haggerty <mhagger@alum.mit.edu>
#
# This file is licensed under the GNU Lesser General Public License
# (LGPL). See LICENSE.txt for details.
"""gp_java -- an interface to gnuplot used under Jython/Java.
This file implements a low-level interface to a gnuplot program run
via Jython/Java. This file should be imported through gp.py, which in
turn should be imported via 'import Gnuplot' rather than these
low-level interfaces.
"""
# ############ Configuration variables: ################################
class GnuplotOpts:
"""The configuration options for gnuplot on generic platforms.
Store the options in a class to make them easy to import and
modify en masse. If you want to modify the options from the
command line or within a running program, do something like the
following::
import Gnuplot
Gnuplot.GnuplotOpts.gnuplot_command = '/bin/mygnuplot'
"""
gnuplot_command = 'gnuplot'
recognizes_persist = 1
prefer_persist = 0
recognizes_binary_splot = 1
prefer_inline_data = 0
support_fifo = 0
prefer_fifo_data = 0
default_term = 'x11'
default_lpr = '| lpr'
prefer_enhanced_postscript = 1
# ############ End of configuration options ############################
import sys
from java.lang import Thread
from java.lang import Runtime
def test_persist():
"""Determine whether gnuplot recognizes the option '-persist'.
"""
return GnuplotOpts.recognizes_persist
class OutputProcessor(Thread):
"""In a separate thread, read from one InputStream and output to a file.
"""
def __init__(self, name, input, output):
self.input = input
self.output = output
Thread.__init__(self, name)
self.setDaemon(1)
def run(self):
while 1:
self.output.write(chr(self.input.read()))
class GnuplotProcess:
"""Unsophisticated interface to a running gnuplot program.
This represents a running gnuplot program and the means to
communicate with it at a primitive level (i.e., pass it commands
or data). When the object is destroyed, the gnuplot program exits
(unless the 'persist' option was set). The communication is
one-way; gnuplot's text output just goes to stdout with no attempt
to check it for error messages.
Members:
Methods:
'__init__' -- start up the program.
'__call__' -- pass an arbitrary string to the gnuplot program,
followed by a newline.
'write' -- pass an arbitrary string to the gnuplot program.
'flush' -- cause pending output to be written immediately.
"""
def __init__(self, persist=None):
"""Start a gnuplot process.
Create a 'GnuplotProcess' object. This starts a gnuplot
program and prepares to write commands to it.
Keyword arguments:
'persist=1' -- start gnuplot with the '-persist' option,
(which leaves the plot window on the screen even after
the gnuplot program ends, and creates a new plot window
each time the terminal type is set to 'x11'). This
option is not available on older versions of gnuplot.
"""
if persist is None:
persist = GnuplotOpts.prefer_persist
command = [GnuplotOpts.gnuplot_command]
if persist:
if not test_persist():
raise ('-persist does not seem to be supported '
'by your version of gnuplot!')
command.append('-persist')
# This is a kludge: distutils wants to import everything it
# sees when making a distribution, and if we just call exec()
# normally that causes a SyntaxError in CPython because "exec"
# is a keyword. Therefore, we call the exec() method
# indirectly.
#self.process = Runtime.getRuntime().exec(command)
exec_method = getattr(Runtime.getRuntime(), 'exec')
self.process = exec_method(command)
self.outprocessor = OutputProcessor(
'gnuplot standard output processor',
self.process.getInputStream(), sys.stdout
)
self.outprocessor.start()
self.errprocessor = OutputProcessor(
'gnuplot standard error processor',
self.process.getErrorStream(), sys.stderr
)
self.errprocessor.start()
self.gnuplot = self.process.getOutputStream()
def close(self):
# ### Does this close the gnuplot process under Java?
if self.gnuplot is not None:
self.gnuplot.close()
self.gnuplot = None
def __del__(self):
self.close()
def write(self, s):
self.gnuplot.write(s)
def flush(self):
self.gnuplot.flush()
def __call__(self, s):
"""Send a command string to gnuplot, followed by newline."""
self.write(s + '\n')
self.flush()
|