Gnuplot及其与之一起吃



当然,翻阅西方科学出版物的许多人已经看到了精美而简单的图形。也许有些人想知道这些专家如何可视化他们的数据。现在有一个非常漂亮且非常简单的绘图工具,几乎到处都有:Windows,linux,android等,我敢肯定甚至在DOS下也可以。它可靠,简单,并允许您以漂亮的图形形式显示任何文本表格数据。



为什么选择gnuplot?



如果您已经阅读我的文章“在多个LTE调制解调器上同时进行速度测试”,“谐波振荡”,“创建硬件随机数生成器”),那么您可能已经注意到漂亮的图表。





有关随机数生成器的帖子的图形





关于speetest调制解调器的帖子图片图片



简单而酷。gnuplot的最有价值的优点是,要绘制它们,您只需要一个带有原始数据的文本文件,您喜欢的OS(不过是OpenWRT)和您喜欢的vim测试编辑器上的gnuplot



乍一看,gnuplot似乎比MS Excel更难于绘图。但是,只有这样,进入阈值才更高(您不能使用鼠标单击它,需要在此处阅读文档),但实际上,它变得更加容易和方便。我曾经写过一个脚本,并且一生都在使用它。对于我来说,在Exel中绘制所有事物都不合逻辑的图形比在gnuplot中绘制图形要困难得多。 gnuplot的主要优点是您可以将其嵌入到程序中并实时显示数据。 gnuplot还能从30 GB的统计数据文件中构建出没有任何问题的图形,而Exel只是崩溃而无法打开它。



gnuplot的优点包括它可以轻松地以标准编程语言集成到代码中的事实。有许多语言的现成库,我个人遇到过php和python。因此,您可以直接从程序中生成图形。



例如,我会说我的好朋友在写论文时精通gnuplot(在我的建议下)。她从来都不是一个技术人员,但是她在一晚上弄清楚了。之后,她仅在此处建立图形,并且在使用Excel的同事的背景下,她的工作水平开始出现明显的差异。就我个人而言,科学程序高质量的指标是专门程序构建的图形。



因此,gnuplot简单,易用且美观。让我们走得更远。



gnuplot-应用



使用gnuplot有两种方法:命令模式和脚本执行模式。我建议立即使用第二种模式,因为它是最方便,最快的。而且,功能绝对相同。



但是首先,我们在命令模式下运行gnuplot。从命令行或以操作系统可用的方式运行gnuplot。您甚至可以不阅读本文,而是直接从第一个帮助命令开始培训。她将提供出色的帮助,您可以继续做下去。但是,我们将重点介绍。



该图由plot命令绘制。作为命令参数,您可以指定函数或数据文件的名称。以及要使用的数据列以及如何连接这些点,如何表示它们,等等。让我们说明一下。



gnuplot> plot sin(x)







执行该命令后,将打开一个窗口,在该窗口中将有一个带有默认签名的正弦图。让我们改进此图并同时找出一些其他选项。

让我们签署轴。



set xlabel "X"


指定横坐标轴的标签。



set ylabel "Y"


指定纵坐标的标签。



让我们添加一个网格以显示图形的构建位置。



set grid


我不喜欢纵坐标轴上的正弦曲线位于图的末端这一事实,因此我们将设置图将限于的值的限制。



set yrange [-1.1:1.1] 


因此,该图将从最小值-1.1到最大值1.1绘制。

同样,我设置横坐标的范围,以便仅显示一个正弦周期。



set xrange[-pi:pi]


我们需要在日程安排中添加标题,以便一切都是风水。



set title "Gnuplot for habr" font "Helvetica Bold, 20"


请注意,您可以设置字体及其大小。有关可以使用哪些字体,请参见gnuplot文档。



最后,除了图形上的正弦外,我们还绘制余弦,并设置线型及其颜色。并添加图例,我们要绘制什么。



plot sin(x) title "sinux" lc rgb "red", cos(x)  title "cosinus" lc rgb "green"


在这里,我们在一张画布上绘制了两个红色和绿色的图形。通常,线条(虚线,描边,实线),线条宽度,颜色有很多选项。以及点的类型。我的目标只是演示各种可能性。让我们将所有命令集中在一起并按顺序执行它们。要重置先前的设置,请输入重置。



reset
set xlabel "X" 
set ylabel "Y"
set grid
set yrange [-1.1:1.1]
set xrange[-pi:pi]
set title "Gnuplot for habr" font "Helvetica Bold, 20"
plot sin(x) title "sinux"  lc rgb "red", cos(x)  title "cosinus" lc rgb "green"


结果,我们得到了如此美丽。





在科学期刊上发布时间表不再是可耻的。



如果您老实地重复了所有这些操作,您可能已经注意到,每次手动输入,甚至进行复制,都不免有些麻烦。但这是现成的脚本吗?让我们开始吧!

使用exit命令退出命令模式并创建一个文件:



vim testsin.gpi


#! /usr/bin/gnuplot -persist
set xlabel "X" 
set ylabel "Y"
set grid
set yrange [-1.1:1.1]
set xrange[-pi:pi]
set title "Gnuplot for habr" font "Helvetica Bold, 20"
plot sin(x) title "sinux"  lc rgb "red", cos(x)  title "cosinus" lc rgb "green"


我们使它可执行并运行它。好吧,不要忘记如何退出vim。



chmod +x testsin.gpi
./testsin.gpi


结果,我们得到与图表相同的窗口。如果未在标题中添加“ -persist”,则在脚本执行后窗口将自动关闭。



但是创建窗口通常不是很必要,而且使用它并不总是很方便,并且您可以在没有GUI的操作系统中工作。更多时候,您需要接收图形文件。就我个人而言,我更喜欢后记矢量格式,因为有很多点,您可以放大图形的不同部分而不会损失质量。而且,在更改后记文件时,Linux中的查看器会自动刷新带有图形的窗口,这也非常方便。



为了将数据输出到文件而不是屏幕,您需要重新分配终端。



set terminal png size 800, 600
set output "result.png"


您可能会猜到,我们指出文件类型,其分辨率,然后指出文件名。将这两行添加到脚本的开头,我们将在当前文件夹中获得此图片。







为了保存到脚本,您需要使用以下命令:



set terminal postscript eps enhanced color solid
set output "result.ps"


真实数据



正弦,余弦的绘制当然很酷,但是绘制真实数据仍然有趣得多!让我想起您最近写的一篇文章一项任务-长时间显示Internet速度图。数据格式如下。



操作员;#测试; 日期; 时间; 坐标;下载Mb / s;上传Mb / s; 测试服务器

Rostelecom; 0; 05/21/2020; 09:56:00; NA,NA; 3.7877656948451692; 5.231226008184113; 132.227; MaximaTelecom(莫斯科)[0.12 km]:132.227 ms

Rostelecom; 1; 05/21/2020; 10:01:02 ; NA,NA; 5.274994541394363; 5.1088572634075815; 127.52; MaximaTelecom(Moscow)[0.12 km]:127.52 ms

Rostelecom; 2; 05.21.2020; 10:04:35; NA,NA; 3.61044819424076; 4.624132180211938; 135.456; MaximaTe 0.12 km]:135.456 ms


可以看出,我们有一个分号作为分隔符,我们需要显示下载速度,上传速度取决于时间。而且,如果您注意日期和时间在不同的列中。现在,我告诉您如何解决这个问题。我将立即引用构建图形的脚本。



#! /usr/bin/gnuplot -persist
set terminal postscript eps enhanced color solid
set output "Rostelecom.ps"

#set terminal png size 1024, 768
#set output "Rostelecom.png"
 
set datafile separator ';'
set grid xtics ytics
set xdata time
set timefmt '%d.%m.%Y;%H:%M:%S'

set ylabel "Speed Mb/s"
set xlabel 'Time'
set title "Rostelecom Speed"

plot "Rostelecom.csv" using 3:6 with lines title "Download", '' using 3:7 with lines title "Upload"
 
set title "Rostelecom 2 Ping"
set ylabel "Ping ms"
plot "Rostelecom.csv" using 3:8 with lines title "Ping"


在文件的开头,我们设置后记输出文件(或png,如果需要)。



设置数据文件分隔符“;” -我们设置分隔符。默认情况下,列之间用空格分隔,但是csv文件提供了许多定界符选项,您应该可以使用所有定界符选项。

设置网格xtics ytics-设置网格(您只能沿一个轴设置网格)。

设置xdata时间是重要的一点,我们正在谈论一个事实,即X轴上的数据格式将是时间。

set timefmt'%d。%m。%Y;%H:%M:%S'-设置时间数据格式。请注意,列分隔符(“;”)包含在时间格式中,因此我们将两列视为一列。



我们设置轴和图形的标签。然后我们建立一个图形。



使用标题为“ Download”的3:6绘制“ Rostelecom.csv”,标题为“ Upload”的3:7绘制“ Rostelecom.csv” -我们在一张图上同时绘制了下载速度和上传速度。使用3:6是源数据文件中的列号,即我们从(X:Y)构建的内容。



然后,我们以相同的方式绘制ping图。结果图将如下所示。





这是后记的屏幕截图。图中的直线是由于存在数据间隙这一事实。这是一个非常真实的绘图示例。



和3D ???



您要3D吗?我有他们!



我想了很久,想出什么三维图形的例子,没有想到比可视化图片更好的了。实际上,从本质上讲,图片是三维图,其中像素亮度是z坐标。因此,让我们玩一些流氓。

拍摄爱因斯坦最著名的照片。





让我们来制作一个图形。为此,将其转换为pgm ASCII格式并删除所有空格,并使用一个简单的命令将其替换为换行符。



convert Einstein.jpg  -compress none pgm:- | tr -s '\012\015' ' '  | tr -s ' ' '\012'> outfile.pgm 


对于那些不了解这里发生了什么的人,我向您解释:我们使用imagemagic将图片转换为pgm格式,然后使用tr将换行符替换为换行,然后再将所有空格换成一个回车符,然后将其全部保存到outfile中。 pgm。任何有困难的人都可以使用gimp打开文件并将其导出为pgm-ASCII。



之后,使用我们最喜欢的编辑器vim打开生成的文件,并从中删除标题。就我而言,这是前三行。不要忘记从标题中找出文件分辨率,在这种情况下,分辨率为325x408像素。就是这样,我们得到了一个Z坐标的文本文件!现在我们的任务是添加X和Y坐标,为此,我们将通过Python脚本运行所有这些坐标。



f = open('outfile.pgm')
for x in range(408):
	for y in range(325):
		line = f.readline()
		print ('%d %d %s' % (x, y, line)),
f.close()


将其另存为convert.py并运行:



python convert.py > res.txt


就是这样,现在res.txt包含Einstein ... Hmm的坐标,或者更确切地说,是他图像的坐标。好吧,总的来说,您会得到一个想法:)。





406 317 60

406 318 54

406 319 30

406 320 41

406 321 84

406 322 101

406 323 112

406 324 119

407 407 0 128

407 1 53

407 2 89

407 3 95

407 4 87

...


样本文件。



建立这种美的脚本如下所示。



#! /usr/bin/gnuplot -persist
#set terminal png size 1024, 768
#set output "result.png"
#set grid xtics ytics

#set terminal postscript eps enhanced color solid
#set output "result.ps"

set title "Albert Einstein"
set palette gray
set hidden3d
set pm3d at bs
set dgrid3d 100,100 qnorm 2
set xlabel "X" font "Helvetica Bold	,18"
set ylabel "Y" rotate by 90 font "Helvetica Bold	,18"
set zlabel "Z" font "Helvetica Bold	,18"

set xrange [0:408]
set yrange [0:325]
set zrange [-256:256]
unset key 
splot "./res.txt" with l 


在我们继续分析脚本之前,如果重复此操作,我强烈建议您在命令模式下执行脚本行,以便可以用鼠标旋转图表(当然,无需指定设置的终端)。太酷了!



首先,我们设置输出数据类型以及数据边界。边框是根据图片的大小设置的,从底部开始,我沿着Z轴有256个字符,以便可以看到图片的投影。接下来,我们将图形放在头部,标记轴。使用unset key命令-我禁用图例(图表上不需要)。真正的魔术来了!



将调色板设置为灰色-我们设置调色板。如果保留为默认值,该图将像在热像仪上一样上色。斑点越高,斑点越黄,红色越暗。



设置hidden3d-好像拉动曲面(去除线条),从而形成漂亮的凸面。



将pm3d设置为bs-启用3D数据绘制样式,该样式将以网格坐标和颜色绘制数据。阅读文档中的更多内容,更详细的描述超出了本文的范围。



将dgrid3d设置为100,100 qnorm 2-将网格单元的大小设置为100x100,并在单元之间设置抗锯齿。值100x100已经很大,程序运行缓慢。 qnorm 2是抗锯齿的(单元之间的数据插值)。



用l绘制“ ./res.txt”-绘制结果图。 “带l”表示用线绘制图形。这是一个小技巧,因为这些点在图形上可见(可以设置小点)。



发射后,我们等待一段时间,然后得到一个多边形的“浅浮雕”。尝试尝试这些设置以获得其他渲染选项。





图像旋转后处于命令模式。



立刻想到一个轶事。

如何找到列宁广场?

只有没有受过教育的人才能回答这个问题,那就是必须将列宁的高度乘以列宁的宽度。

受过良好教育的人知道对表面进行积分。


在程序中使用gnuplot



该示例取自我做了一些小改动的stackoverflow



该代码生成一个文本文件,并不断导致图形被重建。我将在扰流板下面附加代码,以免破坏文章。



使用gnuplot的示例C代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


float s=10.;
float r=28.;
float b=8.0/3.0;
/* Definimos las funciones */
float f(float x,float y,float z){
    return s*(y-x);
}
float g(float x,float y,float z){
    return x*(r-z)-y;
}
float h(float x,float y,float z){
    return x*y-b*z;
}
FILE *output;
FILE *gp;

int main(){
    gp = popen("gnuplot -","w");
    output = fopen("lorenzgplot.dat","w");
    float t=0.; 
    float dt=0.01;
    float tf=30;
    float x=3.;
    float y=2.;
    float z=0.;
    float k1x,k1y,k1z, k2x,k2y,k2z,k3x,k3y,k3z,k4x,k4y,k4z;
    fprintf(output,"%f %f %f \n",x,y,z);
    fprintf(gp, "splot './lorenzgplot.dat' with lines \n");
/* Ahora Runge Kutta de orden 4 */  
    while(t<tf){
        /* RK4 paso 1 */
        k1x = f(x,y,z)*dt;
        k1y = g(x,y,z)*dt;
        k1z = h(x,y,z)*dt;
        /* RK4 paso 2 */
        k2x = f(x+0.5*k1x,y+0.5*k1y,z+0.5*k1z)*dt;
        k2y = g(x+0.5*k1x,y+0.5*k1y,z+0.5*k1z)*dt;
        k2z = h(x+0.5*k1x,y+0.5*k1y,z+0.5*k1z)*dt;
        /* RK4 paso 3 */
        k3x = f(x+0.5*k2x,y+0.5*k2y,z+0.5*k2z)*dt;
        k3y = g(x+0.5*k2x,y+0.5*k2y,z+0.5*k2z)*dt;
        k3z = h(x+0.5*k2x,y+0.5*k2y,z+0.5*k2z)*dt;
        /* RK4 paso 4 */
        k4x = f(x+k3x,y+k3y,z+k3z)*dt;
        k4y = g(x+k3x,y+k3y,z+k3z)*dt;
        k4z = h(x+k3x,y+k3y,z+k3z)*dt;
        /* Actualizamos las variables y el tiempo */
        x += (k1x/6.0 + k2x/3.0 + k3x/3.0 + k4x/6.0);
        y += (k1y/6.0 + k2y/3.0 + k3y/3.0 + k4y/6.0);
        z += (k1z/6.0 + k2z/3.0 + k3z/3.0 + k4z/6.0);
        /* finalmente escribimos sobre el archivo */

        fprintf(output,"%f %f %f \n",x,y,z);
        fflush(output); 
        usleep(10000);
        fprintf(gp, "replot \n");
        fflush(gp);
        t += dt;
    }
    fclose(gp);
    fclose(output);
    return 0;
}




代码非常简单,我们打开一个管道:



gp = popen("gnuplot -","w");


这与bash中的竖线相似,当我们仅在程序内部编写一个命令之后,再写另一个命令时,便会如此。我们将数据写入lorenzgplot.dat文件。在gnuplot中调用一次splot命令:



fprintf(gp, "splot './lorenzgplot.dat' with lines \n");


然后,在添加新点时,我们将重建图。



fprintf(gp, "replot \n");


结果,我们得到了Lorenz Attractor非常好的慢速构造。以下是将近十年前使用旧相机拍摄的视频,因此请不要发誓。视频中重要的是,这一切都可以在像Nokia N800这样的旧硬件上很好地工作。希望没有声音观看。







重要的是要了解replot命令很好地吞噬了内存和处理器时间,也就是说,这种绘图不会使系统减慢太多。因此,尽管对gnuplot充满了热爱,但这并不是使用它的最佳方法。另一个问题是无法关闭或移动该窗口。



结论



最后,我想展示一个视频,其中收集了数百幅放射性粒子配准的随机对数分布图,这是一项研究的真实数据。可以而且应该通过声音观看视频。







在本文中,我什至无法告诉该绘图仪功能的千分之一,只是我使读者对该程序有所了解。接下来,您应该自己寻找示例,阅读官方网站gnuplot.sourceforge.netwww.gnuplot.info上的文档。一定要看例子,那里有很多有趣和有用的东西。



首先,我还可以推荐gnuplot(rus)简介。令我感到非常惊讶的是,没有在所有的技术大学中都将这种出色的课程与乳胶媲美。由于某种原因,我们学习了MS Excel和Word。



学习gnuplot并不困难,我花了几天的时间试图从头开始解决它。但是,相信本文对您而言一切都会变得更快。现在我已经忘记了任何Exel / Calc作为绘图仪,我只使用gnuplot。而且,我什至不知道绘制图形的所有可能性的十分之一。



我想指出,还有许多其他绘图仪,不比gnuplot差,尤其是因为它已经很老了。但是对我来说,gnuplot证明是最简单,最全面的。另外,它是最常见的绘图仪,并且在网络上有大量使用它的示例。谢谢阅读!






All Articles