Mercurial > hg > aim92
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/saitools/findpeaks.c Fri May 20 15:19:45 2011 +0100 @@ -0,0 +1,256 @@ +/* + Copyright (c) Applied Psychology Unit, Medical Research Council. 1993 + =========================================================================== + + Permission to use, copy, modify, and distribute this software without fee + is hereby granted for research purposes, provided that this copyright + notice appears in all copies and in all supporting documentation, and that + the software is not redistributed for any fee (except for a nominal + shipping charge). Anyone wanting to incorporate all or part of this + software in a commercial product must obtain a license from the Medical + Research Council. + + The MRC makes no representations about the suitability of this + software for any purpose. It is provided "as is" without express or + implied warranty. + + THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES + OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + SOFTWARE. +*/ + +/*--------------------------------------------------------------------------*/ + +/* findpeaks.c +* ------------- +* +* Part of the temporal regularity programs +* +* M.Akeroyd. Summer 1993. Revised Winter 1994. +*/ + + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "tip.h" + + + + +/*--------------------------------------------------------------------------*/ + + +int findpeaksreverse() +{ + /* What this code does: + * Its primary job is to find out where the tops of local maxima ("peaks") + * are. Its secondary job is to define the edges of those peaks. + * The locations and heights of the peaks are held in the peak[n] structure, + * where n is the number of the peak. The edges are held in the + * nextevent[n] structure. + * + * Its called 'findpeaksreverse' because it traverses the array from 'right' + * (ie, +ve Image Time) to 'left' (-ve Image Time): peaks get numbered + * accordingly. eg, if nwidth = 0, then the TriggerPeak is peak 1. + * + * Edge defintions: + * for a peak n + * nextevent[n] is the LEFT edge (because we are going right-to-left + * on samples); + * nextevent[n-1] the RIGHT edge. + * + * Peak definitions: + * simple peak: f(sample - 1 ) < f(sample) > f(sample + 1) + * complex peak is a plateau: hopefully the code finds the middle, or + * the leftedge of the middle (if the middle is an + * even number of samples) + * + * Nextevents definitions: + * minima: f(sample - 1 ) > f(sample) < f(sample + 1) + * rightzero: the first f(sample) = 0 to the Right of a peak + * leftzero: ... ... ... Left ... + * (so, because we're going backwards, the RIGHTZERO of a + * peak is actually held in nextevent[n-1], the LEFTZERO + * in nextevent[n]). + * + * + * The first and last samples of a channel are dealt with differently, + * if only because the inequalities will crash if the (sample-1) or + * (sample+1) (respectively) don't exist. But I'm not sure if they work + * properly. I'm pretty certain they don't: so, they are just ignored. + * + * Finally, the number of peaks found is RETURNed. + * + * + * Version of 21 May 1993. Revised slighlty Winter 1994. + */ + + +/*---------------------------*/ + + extern short inputdata[MAX_DATA]; + extern struct Peak peak[MAX_PEAKS]; + extern struct NextEvent nextevent[MAX_NEXTEVENTS]; + extern char progname[MAX_STRING_LENGTH]; + extern int framewidth_samples; /* pwidth + nwidth * samplerate */ + + int sample; /* left to right */ + int n = 0; /* peak counter: right to left */ + int zeroflag = OFF; /* used within nextevents */ + int localsample, flat_top, truesample; /* All 3 used in finding the + centre of a plateau */ + + /* WARNING: goes from right to left ... */ + +/*---------------------------*/ + + /* do peak check for first sample: its framewidth - 1, because the channel + * starts at 0 */ + /* NB: removed 18th June 1993*/ + +/* if (inputdata[framewidth_samples - 1] > inputdata[framewidth_samples -2]){ +* peak[++n].sample = framewidth_samples - 1; +* peak[n].mag = inputdata[framewidth_samples-1];} +*/ + +/*---------------------------*/ + + /* for the rest of the samples */ + for (sample=framewidth_samples - 2; sample >= 1; sample--) { + + /* simple peak ? */ + if ((inputdata[sample] > inputdata[sample - 1]) && + (inputdata[sample] > inputdata[sample + 1])){ + peak[++n].sample = sample; + peak[n].mag = inputdata[sample]; + continue;} + + /* complicated peak? ie, a plateau to it */ + /* but plateaus on the sides of big peaks don't count ... */ + if ((inputdata[sample] >= inputdata[sample - 1]) && + (inputdata[sample] > inputdata[sample + 1])){ + localsample = sample; /* counter to leftedge of the plateau */ + flat_top = 1; /* width, in samples, of the top */ + truesample = sample; + while (inputdata[--localsample] == inputdata[sample]) + flat_top ++; /* find out the width of the plateau */ + + /* is this plateau a mere bump on the edge of a real peak? + * If so, its not a peak. + * localsample is just off the leftedge of the plateau */ + if (inputdata[localsample] > inputdata[localsample+1]) + continue; + + truesample = sample - (int) (flat_top / 2); + /* I think this ensures it is a leftward as possible */ + peak[++n].sample = truesample; + peak[n].mag = inputdata[truesample]; + continue;} + + /*---------------------------*/ + + /* nextevents ... */ + + /* This is an errorcheck ... + * If we've reached a LEFTZERO, but the current nextevent is a + * RIGHTZERO, then something has gone very wrong ... + * we should have hit a peak on the way, so incrementing the counter */ + if ((inputdata[sample] == 0) && nextevent[n].type == RIGHTEDGE) { + fprintf(stderr, " %s : something's gone wrong: didn't find a peak between two zeros.\n", progname); + exit(-1); } + + if ((inputdata[sample] == 0) && (zeroflag == OFF)) { + nextevent[n].type = LEFTZERO; + nextevent[n].sample = sample; + nextevent[n].mag = inputdata[sample]; + zeroflag = ON; + continue;} + + if ((inputdata[sample] != 0) && (zeroflag == ON)) { + nextevent[n].type = RIGHTZERO; + nextevent[n].sample = sample+1; /* +1 because you can only notice + * such an event when you are off it, + * and because we are moving + * in reverse */ + nextevent[n].mag = inputdata[sample+1]; + zeroflag = OFF; + continue;} + + /* This next bit removed at some stage */ + /* + * if ((inputdata[sample] <= inputdata[sample +1]) && + * (inputdata[sample] < inputdata[sample -1]) && + * (nextevent[n].type == NULL)) { + */ + + if ((inputdata[sample] <= inputdata[sample +1]) && + (inputdata[sample] < inputdata[sample -1])) { + nextevent[n].type = MINIMUM; + nextevent[n].sample = sample; + nextevent[n].mag = inputdata[sample]; + continue;} + + } /* sample */ + +/*-----------------------------*/ + + /* repeat for last sample*/ + + /* peak ? */ + /*NB: Removed 18th June 1993 */ + + /* if (inputdata[0] > inputdata[1] ){ + * peak[++n].sample = 0; + * peak[n].mag = inputdata[0];} + */ + + + /* nextevents ... */ + + if (inputdata[0] == 0 && zeroflag == OFF) { + nextevent[n].type = LEFTZERO; + nextevent[n].sample = 0; + nextevent[n].mag = inputdata[0]; + zeroflag = ON;} + + + if (inputdata[0] != 0 && zeroflag == ON) { + nextevent[n].type = RIGHTZERO; + nextevent[n].sample = 0; /* -1 because you only notice such an event + * when you've gone past*/ + nextevent[n].mag = inputdata[0]; + zeroflag = OFF;} + + if (inputdata[0] < inputdata[1]){ + nextevent[n].type = MINIMUM; + nextevent[n].sample = 0; + nextevent[n].mag = inputdata[0]; } + + if (nextevent[n].type == UNSET) { + nextevent[n].type = END_OF_WIDTH; + nextevent[n].sample = 0; + nextevent[n].mag = inputdata[0]; } + + return n; /* total number of peaks found, starting at 1 */ +} + + + + +/* The End */ +/*--------------------------------------------------------------------------*/ + + + + + + + + +