2016-04-15 44 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