lambertmular
lambertmular

Reputation: 107

Find local maximum of data files in gnuplot

I have a list of data (two columns) and I want to plot in gnuplot only the value for which my second column has a local maximum.

To do so I would like to see if the second column of the ith row is bigger than the (i-1) and (i+1)th rows.

Upvotes: 4

Views: 4492

Answers (2)

theozh
theozh

Reputation: 25749

A simple gnuplot peak finder

Comparing 3 consecutive data points is a simple way to look for maxima/peaks.

if y(i-1) < y(i) > y(i+1) then you have a maximum/peak at x(i).

However, if you have noisy curves (like experimental spectra typically are) you will get too many "peaks".

The script below basically calculates for each peak a specific number which is a measure for the "independence" of a peak (see Topographic prominence). Note that a high peak intensity does not necessarily mean high prominence. For the script gnuplot>=5.2 is required since it uses datablocks and plot ... with table. With some adaptions, it can maybe run with older versions.

You can give "threshold" to show only a certain number of peaks. Unfortunately, gnuplot does not have an easy internal feature for sorting datablocks, with this one could have easily shown the first N most prominent peaks. Hence, here it is done differently: Threshold=100 means show all peaks, Threshold=0 means show only the global maximum. Note that the threshold values and number of shown peaks are not linear between 0 and 100 since it depends on the spectral shape.

Comments and improvements are welcome.

Data: SO28173128.dat

# x    y
6.02   3.33
9.59   4.03
9.59   4.03
9.59   4.03
9.83   3.66
10.58   3.22
10.62   3.85
11.32   2.33
11.53   3.67
11.88   3.27
13.28   3.97
13.42   4.35
14.56   2.99
14.75   3.50
15.23   3.91
15.59   3.58
16.56   3.85
16.70   4.49
16.97   3.98
17.23   4.49
17.37   3.73
17.90   4.24
17.93   4.91
18.80   4.23
18.83   4.64
20.37   3.59
20.48   3.99
21.70   3.19
22.29   4.36
22.41   3.38
23.34   5.04
23.41   5.38
24.38   4.71
24.58   4.96
25.40   5.13
25.41   4.70
26.20   4.21
26.36   4.84
26.55   4.11
26.79   4.73
27.02   4.13
27.54   4.51
27.55   5.17
28.08   5.42
28.33   4.97
28.61   5.17
29.06   5.10
29.12   4.26
29.61   3.61
30.03   4.84
30.58   5.30
30.68   4.72
31.21   5.82
31.99   5.83
32.58   6.56
33.03   6.23
33.51   6.79
33.73   8.88
34.00   7.85
34.17   9.82
34.32   11.24
34.55   10.78
34.85   12.58
35.14   13.84
35.50   18.07
35.85   18.40
36.55   30.70
36.75   29.27
37.16   28.78
38.15   18.93
38.29   20.52
38.83   14.96
39.63   11.39
40.17   8.67
40.48   9.22
40.88   9.75
40.95   8.77
41.45   10.86
41.58   10.33
41.84   11.12
42.51   12.83
43.33   15.09
43.43   14.20
43.63   14.56
44.22   14.76
44.92   12.58
45.71   9.40
45.98   9.84
47.03   7.01
47.53   7.15
47.95   5.48
48.08   6.21
48.56   4.51
48.64   5.11
49.14   3.69
49.31   4.27
49.86   4.71
50.14   4.13
50.33   5.83
50.37   5.36
51.00   4.60
51.37   4.75
52.00   4.91
52.01   4.34
54.28   3.83
54.46   4.33
54.83   3.19
55.58   5.30
55.86   4.95
55.92   6.48
56.40   5.89
56.59   5.16
57.56   5.96
57.64   5.21
58.31   5.36
58.38   6.08
58.92   5.84
59.00   5.28
59.57   5.96
59.94   5.37
61.31   6.07
61.32   6.78
61.96   7.34
62.37   6.89
63.14   9.45
63.54   9.51
63.80   11.03
63.93   11.56
64.17   11.12
64.84   12.38
65.14   16.28
65.64   18.07
66.22   19.06
66.42   17.70
66.56   18.40
67.10   17.20
67.24   18.00
67.77   16.82
68.04   15.80
68.15   16.88
68.43   14.98
68.86   16.28
69.33   16.55
70.43   29.11
70.93   48.16
71.62   58.09
72.01   66.42
72.43   73.37
72.79   76.74
72.84   81.24
73.07   79.85
73.15   72.04
73.32   74.49
73.58   61.26
73.71   65.36
73.98   51.60
73.98   58.75
74.25   52.93
74.53   39.70
74.90   34.01
75.18   34.80
76.67   23.29
77.05   23.82
77.15   20.94
77.27   27.13
77.52   25.20
77.70   29.76
78.17   29.96
78.36   33.33
78.73   37.05
78.86   34.67
79.03   39.90
79.38   39.70
79.59   40.62
79.88   39.17
80.59   36.52
80.60   33.61
81.26   27.53
81.67   23.69
82.07   23.69
82.90   15.37
83.94   14.04
84.25   14.42
85.01   11.26
85.22   12.18
85.77   11.19
85.89   9.97
86.46   10.72
86.56   11.78
87.06   10.56
87.19   11.53
87.74   9.60
87.89   10.64
88.30   8.74
88.56   9.27
88.98   8.08
89.25   8.70
90.12   9.15
90.14   8.34
90.99   9.59
91.06   8.86
91.72   9.01
91.74   8.48
92.43   7.68
92.48   8.34
93.15   7.68
93.54   8.34
93.72   7.61
94.20   8.00
94.39   8.64
94.82   7.83
95.00   8.40
95.43   6.77
95.66   7.39
95.81   5.44
95.84   6.25
96.53   7.70
96.55   6.70
97.22   9.14
97.47   8.13
97.53   6.75
98.57   7.83
98.85   7.40
98.92   8.45
99.35   8.25
99.40   7.77
100.04   8.33
100.14   7.91
101.00   8.30
101.04   7.80
101.94   7.48
102.02   8.20
102.53   6.56
102.58   7.84
103.23   7.75
103.38   6.82
103.39   8.93
103.75   8.60
104.05   9.26
104.30   8.14
104.55   8.56
104.85   7.15
105.17   10.09
105.21   8.41
105.52   11.78
105.80   10.00
105.92   10.86
106.11   9.54
106.31   9.93
106.86   10.99
107.20   10.88
107.42   12.05
107.62   10.33
107.80   11.16
108.39   9.90
108.79   12.25
109.08   11.85
109.46   13.77
109.73   13.42
109.96   15.16
111.02   20.08
111.30   23.56
111.69   23.56
112.35   30.08
112.61   39.04
112.89   43.53
113.28   43.67
113.81   60.73
113.94   56.63
114.20   63.11
114.46   69.60
115.00   80.44
115.12   86.95
115.27   84.68
115.78   88.78
116.11   89.57
116.40   88.51
116.43   89.90
117.90   80.31
118.18   71.32
118.42   72.51
118.70   67.48
118.83   61.13
119.25   60.34
119.37   54.51
119.65   55.18
120.08   50.28
120.12   48.96
120.84   54.18
120.95   51.87
121.24   56.49
121.50   53.01
121.64   54.44
121.73   51.74
121.84   52.53
122.14   53.72
122.19   52.40
122.44   53.59
122.45   54.91
122.64   51.61
122.76   53.17
123.08   50.79
123.10   50.15
123.34   49.51
123.39   50.81
123.88   50.28
124.25   46.58
124.26   44.06
124.53   43.67
125.18   38.77
125.81   32.16
126.10   32.55
127.32   21.71
127.70   21.18
127.96   18.27
128.22   18.66
128.62   15.71
128.89   16.24
129.30   13.94
129.56   14.47
129.96   12.22
130.21   12.72
130.53   10.83
130.93   10.61
131.15   11.24
131.84   10.06
131.93   11.12
132.71   9.87
133.06   13.17
133.38   12.73
134.17   16.97
134.31   22.37
134.85   30.83
135.38   43.01
135.62   40.09
135.64   50.81
135.75   54.05
136.16   56.10
136.80   50.22
137.21   49.36
138.29   25.41
138.56   26.73
139.98   13.09
140.03   11.92
140.32   14.53
140.55   13.80
140.85   16.25
141.24   15.81
141.45   17.92
141.59   16.51
141.99   20.65
142.25   20.19
142.76   27.79
142.91   24.95
143.72   37.66
143.79   35.37
144.65   29.11
144.91   30.32
145.71   25.74
145.84   24.80
146.54   27.73
146.74   30.57
147.30   31.11
147.42   30.30
148.33   31.23
148.38   30.68
148.93   31.19
149.09   31.74
149.24   28.43
149.49   29.03
149.96   24.55
150.69   23.48
151.83   18.06
151.89   19.39
152.41   18.27
152.96   19.45
153.02   18.53
153.47   19.42
153.71   18.78
153.91   19.44
154.08   17.74
154.54   18.92
154.65   18.20
155.61   18.79
156.78   15.75
157.06   16.08
157.54   12.68
157.84   13.40
158.51   12.73
158.57   11.85
159.45   11.27
159.57   10.33
160.11   8.81
160.24   9.81
160.90   9.27
160.90   8.08
161.17   8.48
161.43   8.10
161.59   8.72
161.83   7.91
162.44   8.48
162.61   7.94
163.41   8.75
163.43   8.19
163.94   8.99
163.96   8.33
164.60   8.23
164.87   8.74
165.81   8.50
166.10   8.08
166.74   8.91
167.02   8.48
167.67   9.68
167.96   9.28
168.90   9.81
168.96   10.34
169.57   9.77
169.76   11.28
170.00   10.75
171.01   13.77
171.12   13.13
171.79   13.71
172.83   19.14
173.19   19.13
173.52   21.06
173.73   20.38
173.87   21.65
174.27   21.90
174.41   25.94
174.94   27.39
175.20   33.48
175.71   35.07
175.84   40.49
176.48   43.27
176.51   46.84
177.34   51.47
177.62   57.30
177.69   55.18
177.87   53.26
178.08   54.46
178.45   49.43
178.76   49.62
179.02   43.53
179.43   42.08
179.96   28.98
180.21   26.40
180.56   26.57
180.57   26.20
181.14   26.43
181.24   25.51
181.68   24.93
181.74   27.13
181.97   28.85
182.05   26.93
182.14   29.78
182.30   27.53
182.59   28.72
182.72   26.93
183.04   27.67
183.21   28.76
183.33   27.92
183.75   29.99
184.06   29.78
184.28   32.07
184.71   32.49
185.40   37.78
185.61   34.01
186.02   33.86
186.20   30.07
186.79   28.72
186.97   25.44
187.34   25.15
188.45   17.65
188.84   16.25
189.08   16.77
189.50   14.08
189.90   13.69
189.92   11.67
190.37   12.04
190.41   12.90
190.90   11.40
190.93   12.58
192.29   9.27
192.33   8.79
193.23   10.21
193.34   9.73
193.78   11.15
194.07   10.20
194.54   10.43
194.93   9.64
195.39   9.82
195.98   10.86
196.08   10.05
196.45   11.78
197.00   8.90
197.03   9.95
197.70   7.15
198.07   10.13
198.10   8.48
198.83   9.67
198.85   10.46
199.27   9.80
199.46   9.46
200.46   11.78
200.73   11.38
201.38   12.37
201.92   9.72
202.06   10.52
203.14   7.67
203.52   7.95
203.93   7.02
204.13   7.55
204.39   6.66
204.63   7.15
206.35   5.53
206.57   6.00
207.21   6.57
207.33   5.76
208.23   7.93
208.52   7.68
208.92   7.15
209.21   7.56
209.41   6.62
209.88   6.89
211.48   4.50
211.70   5.00
212.39   5.37
212.51   4.53
212.84   4.31
212.92   5.17
213.26   4.38
213.44   5.24
213.70   4.57
214.15   4.97
214.24   5.71
215.55   5.20
215.65   6.01
216.28   6.16
216.55   6.87
216.73   5.56
216.95   6.23
217.25   6.03
217.47   5.46
217.93   5.50
218.26   5.83
218.56   5.04
219.31   4.73
219.97   4.72
220.10   5.61
220.79   4.23
220.87   4.94
221.87   4.64
222.07   4.12
222.58   4.47
222.69   5.02
223.21   4.51
223.24   5.22
223.86   4.54
223.90   5.22
224.48   4.29
224.54   5.04
225.22   4.73
225.28   3.86
225.54   4.13
225.76   4.72
225.84   3.93
226.52   4.23
226.60   4.94
226.98   4.02
227.78   3.89
228.29   4.67
228.62   4.29
229.12   4.90
229.46   4.16
229.83   4.48
230.28   3.54
230.50   4.06
230.91   3.03
231.18   3.63
231.79   3.99
231.97   3.45
232.70   4.86

Edit: revised and simplified

Script: (works with gnuplot>=5.2.0)

### a simple gnuplot peak finder
reset session

FILE = "SO28173128.dat"
colX = 1
colY = 2

# extract all peaks
set table $Temp
    plot y2=y1=x2=x1=NaN FILE u (x0=x1,x1=x2,x2=column(colX), \
                                 y0=y1,y1=y2,y2=column(colY), \
                                 y0<y1 && y1>=y2 ? sprintf("%g %g",x1,y1) : '') w table
set table $Peaks        # remove empty lines and store first values in x0,y0 for later use
    plot $Temp u (column(-2)==0 && $0==0?x0=$1:$1):(column(-2)==0 && $0==0?y0=$2:$2) w table
unset table

isNaN(v) = v!=v         # check if value is NaN
min(a,b) = isNaN(a) && isNaN(b) ? NaN : isNaN(a) ? b : isNaN(b) ? a  : a<b ? a : b   # get minimum incl. NaN

# create prominence table
set print $Prominence
    do for [n0=0:|$Peaks|-1]  {
        xn = yn = xp = yp = NaN
        stats $Peaks u ($0<n0 && $2>y0 ? (xn=$1,yn=$2) : 0, \
                        $0>n0 && $2>y0 && yp!=yp ? (xp=$1,yp=$2) : 0, \
                        $0==n0+1 ? (x1=$1, y1=$2) : 0 ) nooutput
        print sprintf("%g %g %g",x0,y0, min(x0-xn,xp-x0))
        x0=x1
        y0=y1
    }
set print

set key noautotitle
set offsets 0,0,1,0
set grid y

# filter Peaks
stats $Prominence u 3 name "P" nooutput      # get min, max
Filter(col,t) = (!valid(col) ? 0 : (1-(column(col)-P_min)/(P_max-P_min))*99+1)<=t ? $2 : NaN

Threshold = 100
set label 1 at graph 0.02,0.95 sprintf("Threshold: %g",Threshold)

plot FILE u colX:colY w l lc rgb "blue" ti "Spectrum", \
     $Prominence u 1:(Filter(3,Threshold)) w impulses lc rgb "red", \
     $Prominence u 1:(Filter(3,Threshold)):1 w labels offset 0,1
### end of script

Results: (for different thresholds)

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

Upvotes: 6

Miguel
Miguel

Reputation: 7627

It can be done and I was bored enough to do it. I generated the following set of random data:

5191
29375
23222
32118
3185
32355
17173
8734
28850
20811
5956
6950
28560
25770
4630
28272
10035
7209
19428
26187
30784
20326
12865
23288
20924

Plotting the values against their position in the list looks like this:

enter image description here

You can spot the local maxima right away from the graph above. Now I can process the data points storing the two previous values (both x and y coordinates) in temporary variables, when I identify a maximum, I plot the data point:

# Select the columns of your data file that contain x and y data
# (usually 1 and 2 respectively)
xcolumn=0
ycolumn=1

plot "data" u (column(xcolumn)):(column(ycolumn)) w l, \
"data" u (column(0)==0 ? (last2y=column(ycolumn), \
last2x=column(xcolumn), 1/0) : column(0)==1 ? (lasty=column(ycolumn), \
lastx=column(xcolumn), 1/0) : lastx) \
: \
( column(0) < 2 ? 1/0 : (last2y < lasty && \
column(ycolumn) < lasty) ? (value=lasty, last2y=lasty, last2x=lastx, \
lasty=column(ycolumn), lastx=column(xcolumn), value) : (last2y=lasty, \
last2x=lastx, lasty=column(ycolumn), lastx=column(xcolumn), 1/0)) pt 7

enter image description here

Upvotes: 6

Related Questions