# How to detect oscillations/characteristic frequencies in data?

**URL:** https://discourse.julialang.org/t/how-to-detect-oscillations-characteristic-frequencies-in-data/105169
**Category:** Signal and Image Processing
**Tags:** dsp, fft
**Created:** [October 19, 2023, 9:47am UTC](https://discourse.julialang.org/t/how-to-detect-oscillations-characteristic-frequencies-in-data/105169 "2023-10-19T09:47:32Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)
#### Post date: [October 19, 2023, 9:47am UTC](https://discourse.julialang.org/t/how-to-detect-oscillations-characteristic-frequencies-in-data/105169/1 "2023-10-19T09:47:32Z")

</div>

I have a (many) signal I have gotten from experiments. The extent can be argued, but I’d definitely say there is _something_ pulsing/oscillatory going on:

```julia
using Plots
plot(signal)

```

![image](https://global.discourse-cdn.com/julialang/original/3X/f/c/fc84134085154c7e2bd1cdc99aa2ddc482f0cfd9.png)

How do I actually show this though? I have tried to use the welch periodogram. However, it mainly seems to show a peak at 0 (which is what you’d expect from white noise, right?):

```julia
using DSP
wpd = welch_pgram(signal, 300)
plot(wpd.freq, wpd.power)

```

![image](https://global.discourse-cdn.com/julialang/original/3X/7/4/7483bce5bd533239f857eb4344708fce4d8c3d0f.png)

Removing the mean have little effect:

```julia
signal2 = signal ./ mean(signal)
wpd2 = welch_pgram(signal2, 300)
plot(wpd2.freq, wpd2.power)

```

![image](https://global.discourse-cdn.com/julialang/original/3X/e/8/e88d68b673af27e73ad876b415bbd170f52c3d9d.png)

Ideally, I was hoping one peak only, at a non-zero frequency, corresponding to the frequency of the pulsing. Am I right that the periodogram seems to suggest my signal is mostly noise?

Is there a go-to function/approach in Julia to determine whether there is an oscillatory behaviour going on? I was thinking maybe something like [Signal-to-noise ratio - MATLAB snr](https://www.mathworks.com/help/signal/ref/snr.html)

---

<div class="post-metadata">

### Author: ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)
#### Post date: [October 19, 2023, 9:56am UTC](https://discourse.julialang.org/t/how-to-detect-oscillations-characteristic-frequencies-in-data/105169/2 "2023-10-19T09:56:32Z")

</div>

This looks to me like a chaotic spiky oscillator. I wouldn’t put to much attention on signal 2 noise ration, because it seems that there is almost no noise. ~~I am not sure what `welch` does, but it seems incorrect… What does the standard FFT power spectrum show (after removing mean)?~~ EDIT: I didn’t see that the mean was divided, I assumed it was subtracted without looking at the code. Welsch works fine.

If neither work, you can try some of the methods in this function to get the dominant period: [Fixed points & Periodicity · ChaosTools.jl](https://juliadynamics.github.io/ChaosTools.jl/stable/periodicity/#Estimating-the-Period)

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [October 19, 2023, 10:03am UTC](https://discourse.julialang.org/t/how-to-detect-oscillations-characteristic-frequencies-in-data/105169/3 "2023-10-19T10:03:47Z")

</div>

> [@Torkel](#):
>
> Removing the mean have little effect:

You should subtract, not divide!

PS:  
Check out the [EasyFFTs package](https://discourse.julialang.org/t/ann-announcing-easyffts-jl/90174).

---

<div class="post-metadata">

### Author: ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)
#### Post date: [October 19, 2023, 12:47pm UTC](https://discourse.julialang.org/t/how-to-detect-oscillations-characteristic-frequencies-in-data/105169/4 "2023-10-19T12:47:40Z")

</div>

As said above, you want to _subtract_ the mean. You typically also want to plot the spectrum with a logarithmic y-axis, often also logarithmic x-axis.

---

<div class="post-metadata">

### Author: ![mike.ingold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mike.ingold/32/203749_2.png) [@mike.ingold](https://discourse.julialang.org/u/mike.ingold)
#### Post date: [October 19, 2023, 2:03pm UTC](https://discourse.julialang.org/t/how-to-detect-oscillations-characteristic-frequencies-in-data/105169/5 "2023-10-19T14:03:19Z")

</div>

> [@Torkel](#):
>
> I have tried to use the welch periodogram. However, it mainly seems to show a peak at 0 (which is what you’d expect from white noise, right?)

Power at 0 Hz is caused by a non-zero mean. Since your data is all non-negative, this is basically guaranteed. Dividing the source signal by its mean really just normalizes the mean of the new signal; subtracting the mean will zero it.

```julia
signal2 = signal ./ mean(signal)
# mean(signal2) ≈ 1.0
signal2 = signal .- mean(signal)
# mean(signal2) ≈ 0.0

```

---

<div class="post-metadata">

### Author: ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)
#### Post date: [October 19, 2023, 7:37pm UTC](https://discourse.julialang.org/t/how-to-detect-oscillations-characteristic-frequencies-in-data/105169/6 "2023-10-19T19:37:33Z")

</div>

Thanks everyone!

Substracting the mean did indeed give a more meaningful result:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/b/1/b1da62d7011e05c906113b0603252d59a27dd9f6.png)

ChaosTools sounds like it might be worth trying, I will give it a look.
