Mercurial > hg > aim92
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 |