没有中间文件的 gnuplot?

gnuplot without intermediary files?

我得到了 python 看起来像这样的代码

import subprocess

outdata = """0 45
1 35
2 45
3 35
4 45
5 35
6 45
7 35
8 45""" # etc... one for every minute of a day
f = open("data.txt", 'w')
f.write(outdata)
f.close()

filename = "graph"
title    = "today"
plottext = """
set terminal svg size 2560,1440 enhanced font 'Arial,40'
set output '""" + filename + """.svg'
set title '""" + title + """'
set xrange [0:1440]
set yrange [0:]
set xtics ("00" 0, "01" 60, "02" 120, "03" 180, "04" 240, "05" 300, "06" 360, "07" 420, "08" 480, "09" 540, "10" 600, "11" 660, "12" 720, "13" 780, "14" 840, "15" 900, "16" 960, "17" 1020, "18" 1080, "19" 1140, "20" 1200, "21" 1260, "22" 1320, "23" 1380, "24" 1440 )
plot 'data.txt' using 1:2 with lines notitle
"""
f = open("plotfile.plt", 'w')
f.write(plottext)
f.close()

p = subprocess.call(["gnuplot", "plotfile.plt"])

这很有魅力。但是,如何在不使用临时文件 'data.txt' 和 'plotfile.plt' 的情况下从 Python(或一种语言)中使用 gnuplot 创建图形?

每分钟、每小时、每年都会执行 30 多次此操作,因此跳过临时文件将节省磁盘时间,因为正在处理的数据量不小。

后续问题,是否也可以跳过out文件并在变量中捕获svg文件的xml?这将进入 cgi-bin,所以我希望能够这样调用它:

<img src="http://www.example.com/cgi-bin/plot.py?table=table1&date=2016-12-07">

编辑:gnuplot 的 Python 模块对我不可用。

Edit2:PHP 中的另一个几乎可以满足我要求的示例是

$outdata="0 33
1 44
2 55
3 44
4 33
5 44
 6 55";

$plottext = "set terminal svg size 2560,1440 enhanced font 'Arial,40'
set term svg size 2560,1440 enhanced font 'Arial,40'
set title ''
set xrange [0:1440]
set yrange [0:]
set xtics ('00' 0, '01' 60, '02' 120, '03' 180, '04' 240, '05' 300, '06' 360, '07' 420, '08' 480, '09' 540, '10' 600, '11' 660, '12' 720, '13' 780, '14' 840, '15' 900, '16' 960, '17' 1020, '18' 1080, '19' 1140, '20' 1200, '21' 1260, '22' 1320, '23' 1380, '24' 1440)
plot '-' using 1:2 with lines notitle\n". $outdata;

file_put_contents("plotfile.plt", $plottext);

exec("gnuplot plotfile.plt", $out);

foreach($out as $line)
{
    print $line."\n";
}

我想用类似 exec("gnuplot $plottext", $out) 的方式来调用它;所以我可以跳过文件 plotfile.plt 因为如果两个人试图同时访问一个绘制的图形,这个设置可能会搞砸,因为每个人都使用 plotfile.plt 这不是最好的解决方案。我们可以为每个 http 请求使用一个长的随机名称,但是跟踪那么多临时文件并删除它们并不优雅。

使用 gnuplot 和 Python 绘制文件不是最好的解决方案。使用 pyplot 会好很多。这样您就可以在 python 代码中输入数据并将图形保存为字符串中的 svg。

import matplotlib.pyplot
import io

plotfile = io.StringIO()
matplotlib.pyplot.plot([1,2,3,4], [1,2,1,4])
matplotlib.pyplot.ylabel('Y-axis')
matplotlib.pyplot.xlabel('X-axis')
matplotlib.pyplot.savefig(plotfile, format="svg", dpi = 100)
plotfile.seek(0)
svgstring = plotfile.read()
print(svgstring)

这正是我在问题中所希望的。盆栽中没有文件 I/O,我将图表保留在 python 代码中,以便它可以用于网络应用程序中的动态图像。

...这是一个品味问题...

正如@Christoph 所写,您还可以使用 gnuplot 在 Python 中创建您的绘图。将您的数据放入数据块并将其与设置和绘图命令一起传递给 gnuplot。不需要中间文件。 像这样的东西(用 Python3.6 测试过)(Python 专业人士可能想改进它...)

from subprocess import Popen, PIPE, STDOUT

settings = '''
reset session
set term svg
'''

# create some data and put it into datablock $Data
data_lines = ['$Data <<EOD']
for i in range(-10,11):
    data_lines.append(str(i) + '\t' + str(i*i))
data_lines.append('EOD\n')
data_str = '\n'.join(data_lines) + '\n'

plot_cmd ='''
plot $Data u 1:2 w lp pt 7
'''

gnuplot_str = settings + data_str + plot_cmd

gnuplot_path = r'C:\Programs\gnuplot\bin\gnuplot.exe'
# plot = Popen([gnuplot_path,'-p'],stdin=PIPE,stdout=PIPE,stderr=PIPE)
plot = Popen([gnuplot_path],stdin=PIPE,stdout=PIPE,stderr=PIPE)
output, error = plot.communicate(gnuplot_str.encode())

print(gnuplot_str)
print(output) # or use it elsewhere

#...

gnuplot 代码:

reset session
set term svg

$Data <<EOD
-10 100
-9  81
-8  64
-7  49
-6  36
-5  25
-4  16
-3  9
-2  4
-1  1
0   0
1   1
2   4
3   9
4   16
5   25
6   36
7   49
8   64
9   81
10  100
EOD

plot $Data u 1:2 w lp pt 7

输出 SVG: