Wavelets for non-stationary signals

Today let's understand wavelets for non-stationary signals, using 128 vibration readings from a conveyor motor's startup ramp as the running example.

Riverside Bearing Co. mounted a sensor on a conveyor motor and logged 128 vibration readings during a startup ramp, one reading per sample. The motor's cycle genuinely shrinks over that ramp: about 16 samples per swing near the start, about 4 samples per swing near the end. Here is the whole trace, in the order it happened.

Toggle between line and point and look at how tight the wobble gets by the end compared to the start. Early on, one full up and down swing takes about 16 samples. By the end, the same swing takes about 4. A single frequency cannot describe a cycle that keeps shrinking like this, and this lesson is about the tool built for exactly that problem: the wavelet.

Build the startup vibration trace, then run one periodogram over it

Before anything else, build Riverside Bearing Co.'s trace in R exactly as described, then run a periodogram over it the same way you would on any series: one pass over all 128 points, reporting how much of the trace's variation, its ordinate, sits at each frequency, with period equal to 1 divided by that frequency, in samples.

RInteractive R
# Build 128 vibration readings from a chirp that speeds up over the run, then run one periodogram over all of them set.seed(42) n <- 128 t <- 0:(n - 1) f0 <- 1 / 16 # cycle length near 16 samples at the start f1 <- 1 / 4 # cycle length near 4 samples at the end phase <- 2 * pi * (f0 * t + (f1 - f0) / (2 * 127) * t^2) vibration <- round(3 * sin(phase) + rnorm(128, 0, 0.6), 2) round(mean(vibration), 3) round(sd(vibration), 3) pg <- spec.pgram(ts(vibration), taper = 0, detrend = FALSE, demean = TRUE, fast = FALSE, plot = FALSE) top5 <- order(pg$spec, decreasing = TRUE)[1:5] data.frame( freq = round(pg$freq[top5], 5), period = round(1 / pg$freq[top5], 2), ordinate = round(pg$spec[top5], 2) ) #> [1] 0.027 #> [1] 2.138 #> freq period ordinate #> 1 0.22656 4.41 22.47 #> 2 0.21875 4.57 21.71 #> 3 0.18750 5.33 16.38 #> 4 0.17188 5.82 15.34 #> 5 0.12500 8.00 14.51

  

phase is what is called a chirp: a sine wave whose own frequency does not stay fixed but climbs steadily as t runs from 0 to 127, from f0 = 1/16 cycles a sample up to f1 = 1/4 cycles a sample. Adding rnorm(128, 0, 0.6) puts a little real sensor noise on top. vibration averages 0.027 with a standard deviation of 2.138, matching the running example.

A plain periodogram assumes each frequency it checks runs the same way for the whole series it is given. That assumption is false here, since the true cycle length is moving the entire time.

Look at the top 5 ordinates: they sit at periods running from 8.00 samples down to 4.41 samples, five different periods bunched close together, with no single ordinate towering over the rest the way a fixed, unchanging cycle would. The periodogram cannot settle on one period because there is no one period to settle on. Its output spreads across a moving target instead of landing on it.