## findModes

Here is a function for finding all of the modes (i.e. peaks), in a set of data.   The return object is a list of the found peaks by their position (x value), along with their height relative to the highest peak.   Plus a lot of other information.   To be clear, in a simple case you can just do something like:

order(table(x), decreasing=TRUE)[1]

But I often come across data that is composed of large sets of (potentially) multi-modal, real value numbers, so that method won’t work.  Hence the following code:

```#
# Examples:
# x = round(runif(1000, min=1, max=23))
# findMode(x)
# findMode(x, smallest.expected=0.5)
#
findMode <- function (data, smallest.expected=0, ...) {

d              = density(data, ...)
maxLocations   = vector()
minLocations   = vector()
maxHeights     = vector()
minDepths      = vector()
maxValue       = max(d\$y)
exactMax       = order(table(data), decreasing=TRUE)[1]

# This will not capture the extreme edges as either a min or a max
wasIncreasing <- TRUE;
for (j in 2:length(d\$y)) {

# Hit a peak
if (wasIncreasing & (d\$y[j] < d\$y[j-1])) {
maxLocations  = c(maxLocations, d\$x[j])
maxHeights    = c(maxHeights, d\$y[j]/maxValue)
wasIncreasing = FALSE

# Hit a valley
} else if (! wasIncreasing & (d\$y[j] > d\$y[j-1])) {
minLocations   = c(minLocations, d\$x[j]);
minDepths      = c(minDepths, d\$y[j]/maxValue);
wasIncreasing  = TRUE;

# In a flat spot
} else if (d\$y[j] == d\$y[j-1]) {
next;
}
}

# In addition to changing the density estimation model (see 'density'),
# one may want to sweep away tiny peaks that are just noise.
if (smallest.expected > 0) {
if (length(minDepths) > 0) {
if (max(minDepths) > 0) {
#            keeperIndex    = ((minDepths / max(minDepths)) > smallest.expected);
keeperIndex    = (minDepths  > smallest.expected);
minDepths      = minDepths[keeperIndex];
minLocations   = minLocations[keeperIndex];
}
}

#        keeperIndex    = ((maxHeights / maxValue) > smallest.expected);
keeperIndex    = (maxHeights > smallest.expected);
maxHeights     = maxHeights[keeperIndex];
maxLocations   = maxLocations[keeperIndex];
}

# Collect these features for this channel of the flowFrame
modeList            = list();
modeList\$exactMax   = exactMax
modeList\$maximum    = d\$x[d\$y == max(d\$y)][1];
modeList\$maxima     = maxLocations;
modeList\$maxHeights = maxHeights;
modeList\$minima     = minLocations;
modeList\$minDepths  = minDepths;
return(modeList);
}
```