没有中间文件的gnuplot?

时间:2016-12-07 09:12:18

标签: php python svg gnuplot cgi-bin

我得到了类似这样的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"])

这就像魅力一样。但是如何在Python(或语言)中使用gnuplot创建图表而不使用临时文件' data.txt'和' plotfile.plt'?

每分钟,每小时,每年每分钟执行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(&#34; gnuplot $ plottext&#34;,$ out)来称呼它;所以我可以跳过文件plotfile.plt,因为如果两个人同时尝试访问绘制的图形,这个设置可能搞砸了,因为每个人都使用了plotfile.plt这不是最好的解决方案。我们可以为每个http请求使用一个长的随机名称,但跟踪那些临时文件并删除它们并不优雅。

2 个答案:

答案 0 :(得分:0)

使用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代码中,因此可以将其用于Web应用程序中的动态图像。

答案 1 :(得分:0)

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

正如@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:

enter image description here