2016-04-15 20 views
0

我有一个看起来像这样的数据文件:多个数据块和一个图+标记每个块

"curve 0" 
0 0.7800 
10 0.333 
12 0.5136 
24 0.2096 
26 -0.066 
40 -0.674 
42 -1.123 


"curve 1" 
0 0.876 
2 0.73 
4 0.693 
6 0.672 
10 0.70 
12 0.88 
16 0.95 
148 -0.75 


"curve 2" 
8 2.2305 
10 2.144 
12 2.13 
76 1.26 
78 0.39 
98 -0.97 

我想独立于其他绘制每个数据块使用gnuplot的。这里是我用于此目的的代码:

plot 'file' i 0 u 1:2 w lines title columnheader(1),\ 
'file' i 1 u 1:2 w lines title columnheader(1),\ 
'file' i 2 u 1:2 w lines title columnheader(1),\ 
'file' i 3 u 1:2 w lines title columnheader(1) 

它工作正常。

现在,我想在每个数据块中确定具有最大y值的点(x,y),并用与该数据块对应的曲线具有相同颜色的标记绘制它。我试图用

max_y = GPVAL_DATA_Y_MAX 
replot 'file' u ($2 == max_y ? $2 : 1/0):1 

以前的代码之后,但似乎这个发现在整个第二列包括所有块最大。

我想要做的第二件事是:对于每个数据块和具有不同形状但颜色(曲线)的颜色与最大标记相同的标记,请绘制第一行块。

这两个任务可能与gnuplot和我绘制曲线(columnheader)的方式?

回答

2

这可以做到。它将广泛使用stats命令和一个临时文件。在gnuplot 5中,可以使用命名数据块在内存中创建临时文件(请参阅help datablocks)。

此外,由于你的绘图命令主要是重复的,你可以使用情节语法

plot for[in=0:2] 'file' i in u 1:2 w lines t columnheader(1) 

将使用值0重复绘图命令通过2对变量(您提供的命令使用四个数据块,但您提供的数据文件只有3)。

下面的脚本将完成你想要的:

stats 'file' u 1:2 nooutput 
blocks = STATS_blocks 

set print 'tempfile' 

first_y = "" 
first_x = "" 
do for[i=0:blocks-1] { 
    stats 'file' index i u (first_x=($0==1)?sprintf("%s %f",first_x,$1):first_x,first_y=($0==1)?sprintf("%s %f",first_y,$2):first_y,$1):2 nooutput 
    print sprintf("%f %f",STATS_pos_max_y,STATS_max_y) 
} 

print "" 
print "" 
do for[i=1:blocks] { 
    print sprintf("%s %s",word(first_x,i),word(first_y,i)) 
} 
set print 

plot for[i=0:blocks-1] 'file' i i u 1:2 w lines title columnheader(1),\ 
    for[i=0:1] 'tempfile' i i u 1:2:($0+1) w points pt (i==0?7:9) lc variable not 

这将产生(与您提供的数据文件)

enter image description here

在曲线0和2,第一和最大的情况下,点是相同的,所以符号被遮蔽。

重新绘制这个,但改变规范将第一个点标记向上移动0.1,我们可以看到它们出现在他们应该在的地方。

enter image description here


本节将是漫长的,但我会分解代码,并详细解释一下,尽可能接近于线尽可能线,因为有一些微妙的东西这里。

前两行

stats 'file' u 1:2 nooutput 
blocks = STATS_blocks 

运行的stats命令在该文件。由于命名的列标题,如果我们不指定使用规范,统计函数将失败,所以我们给它u 1:2规范。 nooutput选项告诉stats命令捕获结果,但不输出它们。这里我们只关心获取块的数量。我们将此存储在变量(随后的统计命令将覆盖该变量)。我们可以给一个指定的前缀,但是这样可以保存所有变量,并且没有理由这样做。代替这两个命令,在正好3个块的情况下,我们可以用下面的所有出现的代替值3,但是这样块的数量不是硬编码的。

接下来,我们使用set print 'tempfile'将打印命令重定向到临时文件。我们将建立一个包含最大点和第一点的新数据文件。

的代码

first_y = "" 
first_x = "" 
do for[i=0:blocks-1] { 
    stats 'file' index i u (first_x=($0==1)?sprintf("%s %f",first_x,$1):first_x,first_y=($0==1)?sprintf("%s %f",first_y,$2):first_y,$1):2 nooutput 
    print sprintf("%f %f",STATS_pos_max_y,STATS_max_y) 
} 

下一个部分是最困难的,也有最多的奇迹发生。我们将创建我们的临时文件以拥有两个数据块。第一个是最大值,第二个是第一个值。我们将计算内存中的第一个点并在创建第一个数据块后添加它们。 x坐标和y坐标将存储在空格分隔的字符串变量中。

我们遍历所有数据块并为其计算一个统计命令。表达

(first_x=($0==1)?sprintf("%s %f",first_x,$1):first_x,first_y=($0==1)?sprintf("%s %f",first_y,$2):first_y,$1) 

重新分配用于读取的每个点处的两个字符串变量。为了做到这一点,它首先检查点是在系列中的第一个($ 0的值将是1,因为0值对应于标题行)。如果是,则通过向其添加第一列的值(并且类似于y坐标)来重建字符串变量。否则,它只是将同样的事情重新分配给变量。最后,它返回第一列中的值。当表达式被放在圆括号和逗号分隔像这样,每个表达式依次评估,并返回最终值。

因此,统计命令的行为就像是

stats 'file' index i u 1:2 nooutput 

但这个小动作可以让我们读出的第一行的值,并将其储存,当他们进来,最后与最大y值的点被打印出来。这将进入临时文件。

现在我们需要将第一个点添加到临时文件中作为新的数据块。因此,首先我们打印两个空行,然后我们再次遍历运行的块数

print sprintf("%s %s",word(first_x,i),word(first_y,i)) 

对于每个块(其中i是块的编号)。单词函数将字符串变量视为空格分隔的单词列表并拉出所请求的单词。在这一点上我们的字符串变量看起来像

0.000000 0.000000 8.000000 # first_x 
0.780000 0.876000 2.230500 # first_y 

最后,我们发出set print其恢复打印命令打印到控制台。现在,我们已经建立了一个临时文件,它看起来像

0.000000 0.780000 
16.000000 0.950000 
8.000000 2.230500 


0.000000 0.780000 
0.000000 0.876000 
8.000000 2.230500 

其中第一个数据块都与最大y值和第二数据块的点是第一点。

最后,我们用

plot for[i=0:blocks-1] 'file' i i u 1:2 w lines title columnheader(1),\ 
    for[i=0:1] 'tempfile' i i u 1:2:($0+1) w points pt (i==0?7:9) lc variable not 

的这个第一部分是相同的前绘制,只是用来代替硬编码块的数目可变的块。

接下来我们使用索引0和索引1绘制两次临时文件。根据行号(此例中为0到2),行颜色是可变的。我们添加一个强制通常基于0的行号为1到3.这将与之前的数据块相对应。我们绘制点并根据我们绘制的数据块选择点类型。在这种情况下,它可以是实心圆(最大值)或实心三角形(第一点)。

+0

嗨马修!非常感谢你给出的解释。我只知道gnuplot的基本命令。所以这真的很有帮助。我想你的回复很好地介绍了复杂的gnuplot代码。再次感谢。 – dada