comparison saitools/findpeaks.c @ 0:5242703e91d3 tip

Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author tomwalters
date Fri, 20 May 2011 15:19:45 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:5242703e91d3
1 /*
2 Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
3 ===========================================================================
4
5 Permission to use, copy, modify, and distribute this software without fee
6 is hereby granted for research purposes, provided that this copyright
7 notice appears in all copies and in all supporting documentation, and that
8 the software is not redistributed for any fee (except for a nominal
9 shipping charge). Anyone wanting to incorporate all or part of this
10 software in a commercial product must obtain a license from the Medical
11 Research Council.
12
13 The MRC makes no representations about the suitability of this
14 software for any purpose. It is provided "as is" without express or
15 implied warranty.
16
17 THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
18 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
19 THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
20 OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
21 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
22 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23 SOFTWARE.
24 */
25
26 /*--------------------------------------------------------------------------*/
27
28 /* findpeaks.c
29 * -------------
30 *
31 * Part of the temporal regularity programs
32 *
33 * M.Akeroyd. Summer 1993. Revised Winter 1994.
34 */
35
36
37 #include <stdio.h>
38 #include <string.h>
39 #include <stdlib.h>
40
41 #include "tip.h"
42
43
44
45
46 /*--------------------------------------------------------------------------*/
47
48
49 int findpeaksreverse()
50 {
51 /* What this code does:
52 * Its primary job is to find out where the tops of local maxima ("peaks")
53 * are. Its secondary job is to define the edges of those peaks.
54 * The locations and heights of the peaks are held in the peak[n] structure,
55 * where n is the number of the peak. The edges are held in the
56 * nextevent[n] structure.
57 *
58 * Its called 'findpeaksreverse' because it traverses the array from 'right'
59 * (ie, +ve Image Time) to 'left' (-ve Image Time): peaks get numbered
60 * accordingly. eg, if nwidth = 0, then the TriggerPeak is peak 1.
61 *
62 * Edge defintions:
63 * for a peak n
64 * nextevent[n] is the LEFT edge (because we are going right-to-left
65 * on samples);
66 * nextevent[n-1] the RIGHT edge.
67 *
68 * Peak definitions:
69 * simple peak: f(sample - 1 ) < f(sample) > f(sample + 1)
70 * complex peak is a plateau: hopefully the code finds the middle, or
71 * the leftedge of the middle (if the middle is an
72 * even number of samples)
73 *
74 * Nextevents definitions:
75 * minima: f(sample - 1 ) > f(sample) < f(sample + 1)
76 * rightzero: the first f(sample) = 0 to the Right of a peak
77 * leftzero: ... ... ... Left ...
78 * (so, because we're going backwards, the RIGHTZERO of a
79 * peak is actually held in nextevent[n-1], the LEFTZERO
80 * in nextevent[n]).
81 *
82 *
83 * The first and last samples of a channel are dealt with differently,
84 * if only because the inequalities will crash if the (sample-1) or
85 * (sample+1) (respectively) don't exist. But I'm not sure if they work
86 * properly. I'm pretty certain they don't: so, they are just ignored.
87 *
88 * Finally, the number of peaks found is RETURNed.
89 *
90 *
91 * Version of 21 May 1993. Revised slighlty Winter 1994.
92 */
93
94
95 /*---------------------------*/
96
97 extern short inputdata[MAX_DATA];
98 extern struct Peak peak[MAX_PEAKS];
99 extern struct NextEvent nextevent[MAX_NEXTEVENTS];
100 extern char progname[MAX_STRING_LENGTH];
101 extern int framewidth_samples; /* pwidth + nwidth * samplerate */
102
103 int sample; /* left to right */
104 int n = 0; /* peak counter: right to left */
105 int zeroflag = OFF; /* used within nextevents */
106 int localsample, flat_top, truesample; /* All 3 used in finding the
107 centre of a plateau */
108
109 /* WARNING: goes from right to left ... */
110
111 /*---------------------------*/
112
113 /* do peak check for first sample: its framewidth - 1, because the channel
114 * starts at 0 */
115 /* NB: removed 18th June 1993*/
116
117 /* if (inputdata[framewidth_samples - 1] > inputdata[framewidth_samples -2]){
118 * peak[++n].sample = framewidth_samples - 1;
119 * peak[n].mag = inputdata[framewidth_samples-1];}
120 */
121
122 /*---------------------------*/
123
124 /* for the rest of the samples */
125 for (sample=framewidth_samples - 2; sample >= 1; sample--) {
126
127 /* simple peak ? */
128 if ((inputdata[sample] > inputdata[sample - 1]) &&
129 (inputdata[sample] > inputdata[sample + 1])){
130 peak[++n].sample = sample;
131 peak[n].mag = inputdata[sample];
132 continue;}
133
134 /* complicated peak? ie, a plateau to it */
135 /* but plateaus on the sides of big peaks don't count ... */
136 if ((inputdata[sample] >= inputdata[sample - 1]) &&
137 (inputdata[sample] > inputdata[sample + 1])){
138 localsample = sample; /* counter to leftedge of the plateau */
139 flat_top = 1; /* width, in samples, of the top */
140 truesample = sample;
141 while (inputdata[--localsample] == inputdata[sample])
142 flat_top ++; /* find out the width of the plateau */
143
144 /* is this plateau a mere bump on the edge of a real peak?
145 * If so, its not a peak.
146 * localsample is just off the leftedge of the plateau */
147 if (inputdata[localsample] > inputdata[localsample+1])
148 continue;
149
150 truesample = sample - (int) (flat_top / 2);
151 /* I think this ensures it is a leftward as possible */
152 peak[++n].sample = truesample;
153 peak[n].mag = inputdata[truesample];
154 continue;}
155
156 /*---------------------------*/
157
158 /* nextevents ... */
159
160 /* This is an errorcheck ...
161 * If we've reached a LEFTZERO, but the current nextevent is a
162 * RIGHTZERO, then something has gone very wrong ...
163 * we should have hit a peak on the way, so incrementing the counter */
164 if ((inputdata[sample] == 0) && nextevent[n].type == RIGHTEDGE) {
165 fprintf(stderr, " %s : something's gone wrong: didn't find a peak between two zeros.\n", progname);
166 exit(-1); }
167
168 if ((inputdata[sample] == 0) && (zeroflag == OFF)) {
169 nextevent[n].type = LEFTZERO;
170 nextevent[n].sample = sample;
171 nextevent[n].mag = inputdata[sample];
172 zeroflag = ON;
173 continue;}
174
175 if ((inputdata[sample] != 0) && (zeroflag == ON)) {
176 nextevent[n].type = RIGHTZERO;
177 nextevent[n].sample = sample+1; /* +1 because you can only notice
178 * such an event when you are off it,
179 * and because we are moving
180 * in reverse */
181 nextevent[n].mag = inputdata[sample+1];
182 zeroflag = OFF;
183 continue;}
184
185 /* This next bit removed at some stage */
186 /*
187 * if ((inputdata[sample] <= inputdata[sample +1]) &&
188 * (inputdata[sample] < inputdata[sample -1]) &&
189 * (nextevent[n].type == NULL)) {
190 */
191
192 if ((inputdata[sample] <= inputdata[sample +1]) &&
193 (inputdata[sample] < inputdata[sample -1])) {
194 nextevent[n].type = MINIMUM;
195 nextevent[n].sample = sample;
196 nextevent[n].mag = inputdata[sample];
197 continue;}
198
199 } /* sample */
200
201 /*-----------------------------*/
202
203 /* repeat for last sample*/
204
205 /* peak ? */
206 /*NB: Removed 18th June 1993 */
207
208 /* if (inputdata[0] > inputdata[1] ){
209 * peak[++n].sample = 0;
210 * peak[n].mag = inputdata[0];}
211 */
212
213
214 /* nextevents ... */
215
216 if (inputdata[0] == 0 && zeroflag == OFF) {
217 nextevent[n].type = LEFTZERO;
218 nextevent[n].sample = 0;
219 nextevent[n].mag = inputdata[0];
220 zeroflag = ON;}
221
222
223 if (inputdata[0] != 0 && zeroflag == ON) {
224 nextevent[n].type = RIGHTZERO;
225 nextevent[n].sample = 0; /* -1 because you only notice such an event
226 * when you've gone past*/
227 nextevent[n].mag = inputdata[0];
228 zeroflag = OFF;}
229
230 if (inputdata[0] < inputdata[1]){
231 nextevent[n].type = MINIMUM;
232 nextevent[n].sample = 0;
233 nextevent[n].mag = inputdata[0]; }
234
235 if (nextevent[n].type == UNSET) {
236 nextevent[n].type = END_OF_WIDTH;
237 nextevent[n].sample = 0;
238 nextevent[n].mag = inputdata[0]; }
239
240 return n; /* total number of peaks found, starting at 1 */
241 }
242
243
244
245
246 /* The End */
247 /*--------------------------------------------------------------------------*/
248
249
250
251
252
253
254
255
256