Last active
August 5, 2020 18:07
-
-
Save pklaus/9ef636cb9a80de2af4f7 to your computer and use it in GitHub Desktop.
Plotting with gnuplot via Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
""" | |
This example shows how to call gnuplot from Python | |
It uses Popen() from the subprocess module. | |
The function run_gnuplot() takes care of it and returns the | |
resulting image as bytes. If you run this code on a web server, | |
the result could be returned to the client without storing | |
a file on the disk. In this example it is saved to a file in the end. | |
""" | |
from subprocess import Popen, PIPE | |
import sys | |
from os import linesep as nl | |
import logging | |
import itertools | |
import random | |
logger = logging.getLogger(__name__) | |
logging.basicConfig(level=logging.WARNING) | |
def run_gnuplot(commands, data, persist=True): | |
""" Return the output of a gnuplot command """ | |
args = ["gnuplot", ] | |
if persist: | |
args.append("-persist") | |
args.append("-e") | |
args.append("; ".join([str(c) for c in commands])) | |
logger.info('args: {}'.format(args)) | |
in_pipe, out_pipe, err_pipe = PIPE, PIPE, PIPE | |
gnuplot = Popen(args, stdin=in_pipe, stdout=out_pipe, stderr=err_pipe) | |
logger.info('data: {}'.format(nl.join(data).encode('ascii'))) | |
out, err = gnuplot.communicate(nl.join(data).encode('ascii')) | |
logger.debug('out: {}'.format(out)) | |
if err: | |
logger.error('err: {}'.format(err)) | |
if err: | |
raise NameError('There was a problem with the gnuplot commands or data: ' + err.decode('ascii')) | |
if gnuplot.returncode != 0: | |
raise NameError('The returncode of gnuplot was not zero but {}. There was a problem with the gnuplot commands or data.'.format(gnuplot.returncode)) | |
return out | |
def gnuplot_scope(all_data, context): | |
""" | |
all_data contains the list of data sets (list of lists) | |
context is a dictionary with contextual information for the plot | |
""" | |
commands = [ | |
"set title '{title}'", | |
"set term {format} size {size}", | |
"set key left", | |
"set yrange [{ymin}:{ymax}]", | |
"set xrange [0:1200]", | |
"set xtics {tics}", | |
"set xlabel ' Time {timescale} {tu} per div'", | |
"set ylabel ' Voltage in V'", | |
"set grid", | |
"set object 1 rect from screen 0, 0, 0 to screen 1, 1, 0 behind", | |
"set object 1 rect fc rgb {bgcolor} fillstyle solid 1.0", | |
"set datafile separator ','", | |
"set output", | |
] | |
commands = [cmd.format(**context) for cmd in commands] | |
data_lines = [] | |
i = 0 | |
plot_commands = [] | |
for chan_data in all_data: | |
logger.info('preparing {} - {}'.format(i, context['channels'][i])) | |
plot_commands.append("'{source}' using 1 with lines title '{name}'".format(source=('-' if i==0 else ''), name=context['channels'][i])) | |
data_lines += [str(val) for val in chan_data] + ['e'] | |
i += 1 | |
commands += ['plot' + ', '.join(str(c) for c in plot_commands)] | |
return (commands, data_lines) | |
if __name__ == "__main__": | |
context = {} | |
context['title'] = 'Your Scope' | |
context['channels'] = ['CHAN1', 'CHAN2'] | |
context['format'] = 'png' # or 'svg' | |
context['size'] = '1000,640' | |
context['bgcolor'] = '"white"' # or '"gray"' | |
alldata = [] | |
for channel in context['channels']: | |
values = itertools.accumulate([random.uniform(-0.05, 0.05) for i in range(1200)]) | |
alldata.append(list(values)) | |
min_value = min(min(samples) for samples in alldata) | |
max_value = max(max(samples) for samples in alldata) | |
context['ymin'] = min_value - 0.1 * (max_value - min_value) | |
context['ymax'] = max_value + 0.2 * (max_value - min_value) | |
context['tics'] = '(' + ', '.join(str(i*100) for i in range(1, 12)) + ')' | |
context['timescale'] = float('100e-6') | |
context['tu'] = 's' | |
(commands, data_lines) = gnuplot_scope(alldata, context) | |
gnuplot_output = run_gnuplot(commands, data_lines, persist=False) | |
filename = 'tmp.png' | |
with open(filename, 'wb') as f: | |
f.write(gnuplot_output) | |
print("Wrote {}!".format(filename)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment