Signals often contain peaks that you aren't interested in. This guide will show you how to filter peaks you don't want.

How to filter peaks by peak spacing

Real data typically has noise that can create lots of closely spaced, unwanted peaks.

T = 1/25
t = 0:T:23

multisin(t) = 3sinpi(0.1t) + 2sinpi(0.2t) + sinpi(0.6t)

y = multisin.(t) .+ 0.1rand(length(t))

pks = findmaxima(y)
plotpeaks(t, y; peaks=pks.indices)
Example block output

The simplest way to remove those peaks (assuming the signal is already filtered) is by setting the window w argument in findmaxima and friends:

pks = findmaxima(y, 15)
f = plotpeaks(t, y; peaks=pks.indices)
Example block output

If only the peaks circled in blue are wanted, then setting the window w too wide won't work, since there are larger peaks that would become dominant.

Example block output

How to filter peaks by peak characteristics

Every peak-characteristic finding function can optionally filter the newly calculated characteristics using the keyword arguments min and max.

Plotting all the peak characteristics and/or looking at the characteristic values can help show which characteristics should be filtered to remove all the unwanted peaks.

plotpeaks!(f, t, y; peaks=pks.indices, prominences=true, widths=true)
Example block output
DataFrame(pks[Not(:data)])
7×5 DataFrame
Rowindicesheightspromswidthsedges
Int64Float64Float64Float64Tuple…
1373.39830.34976819.0733(28.6219, 47.6952)
21025.068835.0532111.484(18.3513, 129.835)
31801.264540.6099224.5815(169.131, 193.712)
42731.32682.542344.1711(251.305, 295.477)
5347-0.5590510.62743623.1592(332.166, 355.326)
6446-2.941210.34075420.0388(436.069, 456.108)
75343.380410.33191616.6846(528.124, 544.809)

Looking at the figure and the characteristic values, we can list the usefulness of each characteristic for filtering:

  • Peak height?
    • There are other peaks around the same height as the peaks we want, so applying a min or max height filter would remove peaks we want, or allow peaks we don't want.
  • Peak prominence?
    • All the peaks we want have similarly small prominences (<1) and the other peaks have much larger prominences (>2). This would be a good filtering option, using peakproms(pks; max=1).
  • Peak width?
    • The peaks we want have fairly similar widths (~15-25 elements wide), and the other peaks have larger widths (>40 elements wide). This would be a good filter, using peakwidths(pks; max=30).

In this case, filtering by peak prominence would be the better choice, because calculating peak widths depends on prominences, so filtering by peak prominence would do the job while avoiding unnecessary work.

In many cases, the desired peaks aren't very different from many other peaks in any one peak characteristic. In these situations, it may be necessary to filter multiple times based on different peak characteristics or different min/max thresholds. There is also a filterpeaks! function which allows you to give a filter predicate and filter by multiple characteristics at once.