# How do frequencies shift after a FFT?

**URL:** <https://discourse.julialang.org/t/how-do-frequencies-shift-after-a-fft/88089>\
**Category:** Signal and Image Processing\
**Tags:** fftw, dsp, fft\
**Created:** [October 1, 2022, 4:11pm UTC](https://discourse.julialang.org/t/how-do-frequencies-shift-after-a-fft/88089 "2022-10-01T16:11:31Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![bertulli](https://avatars.discourse-cdn.com/v4/letter/b/ecc23a/32.png) [@bertulli](https://discourse.julialang.org/u/bertulli)\
**Post date:** [October 1, 2022, 4:11pm UTC](https://discourse.julialang.org/t/how-do-frequencies-shift-after-a-fft/88089/1 "2022-10-01T16:11:31Z")

</div>

Hi all!

I hope this is the right subcategory to ask in. I’m playing around with the FFTW package to perform some Fourier transforms. I got how to define a signal and transform it, but I can’t get how (and why) can I shift the frequency domain to reflect the actual frequencies of my signal. My Google-fu made me understand I need to call `fftshift()` and `fftfreq()`, but apparently I can’t understand **how and why**.

As an example, I have this script:

```julia
using FFTW
using Plots

x = 0:100
y = sin.(x)
# y = [abs(x) <= 10 ? 1 : 0 for x in x]
transform = fftshift(fft(y))
f = fftshift(fftfreq(length(x)) * length(x))
plot(f, abs.(transform))

```

However, I got this:  
 ![fourier_module](https://global.discourse-cdn.com/julialang/original/3X/a/3/a36c18949efa3928f14e963d793146209b507620.png)  
Inspecting it with `plotlyjs()` I can see the spike on the right is at x ~= 16. Why, since the original signal had frequency = 1?

Is this the right way to go? If not, what it is? And why? Thanks ❤

---

<div class="post-metadata">

**Author:** ![dlakelan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlakelan/32/8491_2.png) [@dlakelan](https://discourse.julialang.org/u/dlakelan)\
**Post date:** [October 1, 2022, 4:43pm UTC](https://discourse.julialang.org/t/how-do-frequencies-shift-after-a-fft/88089/2 "2022-10-01T16:43:24Z")

</div>

> [@bertulli](#):
>
> since the original signal had frequency = 1?

The original signal repeats how many times per 100 samples? It’s 100/(2pi) ~16

Time is measured by the duration of the sample… Frequency is measured by cycles per duration of sample

If you want to calculate with physical frequencies you will need to explicitly tell fftfreq the sample rate. Like if you are sampling every millisecond then sample rate is 1/0.001

---

<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 2, 2022, 9:46pm UTC](https://discourse.julialang.org/t/how-do-frequencies-shift-after-a-fft/88089/3 "2022-10-02T21:46:38Z")

</div>

> [@bertulli](#):
>
> the original signal had frequency = 1

If the original **angular** frequency is 1, to get it we have to multiply `fftfreq()` by `2π`. See annotated code below:

```julia
using FFTW, Measures, Plots; gr()

x = 0:100
N = length(x)
y = sin.(x) # ω0*x = x; with angular frequency ω0 = 1
Y = fft(y) # Fundamental DFT period T = N*ΔT = N; with ΔT = 1
ω = 2π*fftfreq(N, 1) # 2π-scaler to get angular frequency. Sampling rate fs = 1/ΔT = 1
p1 = plot(x, y, st=:line, m=:o, ms=2, xlabel="Sample number");
p2 = plot(ω, abs.(Y), st=:stem, m=:o, ms=2, xlabel="Radians per sample");
plot(p1, p2, margins=5mm, size=(800,350))

```

 ![FFT_Plot_radians_per_sample](https://global.discourse-cdn.com/julialang/original/3X/e/6/e644da819c870b6a6bf40dfc5a4f372d7646128f.png)

---

<div class="post-metadata">

**Author:** ![bertulli](https://avatars.discourse-cdn.com/v4/letter/b/ecc23a/32.png) [@bertulli](https://discourse.julialang.org/u/bertulli)\
**Post date:** [October 5, 2022, 10:44am UTC](https://discourse.julialang.org/t/how-do-frequencies-shift-after-a-fft/88089/4 "2022-10-05T10:44:22Z")

</div>

Uhm, I think I see the problem but I can’t understand the solution: what frequencies does the DFT outputs? Radians? If this is so, shouldn’t I get the “right” frequencies in the output (and graph) without calling `fftfreq` (since `sin.(x)` also expects radians)?

---

<div class="post-metadata">

**Author:** ![stephancb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephancb/32/14243_2.png) [@stephancb](https://discourse.julialang.org/u/stephancb)\
**Post date:** [October 5, 2022, 11:56am UTC](https://discourse.julialang.org/t/how-do-frequencies-shift-after-a-fft/88089/5 "2022-10-05T11:56:58Z")

</div>

[Here](https://discourse.julialang.org/t/why-are-the-return-values-of-fft-and-fftfreq-so-terrible/87510) is a recent thread with similar discussion.

---

<div class="post-metadata">

**Author:** ![dlakelan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlakelan/32/8491_2.png) [@dlakelan](https://discourse.julialang.org/u/dlakelan)\
**Post date:** [October 5, 2022, 2:06pm UTC](https://discourse.julialang.org/t/how-do-frequencies-shift-after-a-fft/88089/6 "2022-10-05T14:06:56Z")

</div>

> [@bertulli](#):
>
> what frequencies does the DFT outputs?

Cycles per window length.

---

<div class="post-metadata">

**Author:** ![TheLateKronos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thelatekronos/32/12824_2.png) [@TheLateKronos](https://discourse.julialang.org/u/TheLateKronos)\
**Post date:** [October 5, 2022, 2:22pm UTC](https://discourse.julialang.org/t/how-do-frequencies-shift-after-a-fft/88089/7 "2022-10-05T14:22:13Z")

</div>

> [@bertulli](#):
>
> `fftshift(fftfreq(length(x)) * length(x))`

Give the sample freqiency as the second argument to fftfreq, and do not multiply by `length(x)`. I usually do something like this to get it right:

```julia
using FFTW
using UnicodePlots
let
    fs = 1000 # sample freq
    duration = 1
    timestamps = range(0, duration, step=1 / fs) # step = sample period = 1 / fs

    f = 250
    A = 2
    s = @. A * sin(f * 2π * timestamps)

    plt1 = scatterplot(timestamps, s)

    transform = fft(s)|>fftshift
    freqs = fftfreq(length(s), fs)|>fftshift
    plt2 = scatterplot(freqs, transform .|> abs)
    display(plt1)
    display(plt2)
end

```

```julia
┌────────────────────────────────────────┐ 
    2 │⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉│ 
      │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
      │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
      │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
      │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
      │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
      │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
      │⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶⠶│ 
      │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
      │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
      │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
      │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
      │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
      │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
   -2 │⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀│ 
      └────────────────────────────────────────┘ 
      ⠀0⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀1⠀ 
        ┌────────────────────────────────────────┐ 
   1000 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
        │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
        │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
        │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
        │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
        │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
        │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
        │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
        │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
        │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
        │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
        │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
        │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
        │⠀⠀⠀⠀⠀⠀⠀⠀⠀⢈⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⢠⡁⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 
      0 │⣀⣀⣀⣀⣀⣀⣀⣀⣀⡼⢇⣀⣀⣀⣀⣀⣀⣀⣀⣀⣇⣀⣀⣀⣀⣀⣀⣀⣀⡸⢧⣀⣀⣀⣀⣀⣀⣀⣀⣀│ 
        └────────────────────────────────────────┘ 
        ⠀-500⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀500⠀ 

```

EDIT :  
f=250 makes the time domain look funny, lower frequencies make the dot harder to spot in the frequency domain, and may reault in leakage. I would reccomend copying the code and varying e.g. the signal frequency yourself. You can also try adding another signal, to get two distrinct frequency peaks.

---

<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 5, 2022, 3:46pm UTC](https://discourse.julialang.org/t/how-do-frequencies-shift-after-a-fft/88089/8 "2022-10-05T15:46:28Z")

</div>

> [@bertulli](#):
>
> what frequencies does the DFT outputs

The DFT assumes the input data is periodic and it outputs amplitudes of the sinusoids whose frequencies are defined as a multiple of a fundamental frequency that is equal to the inverse of the input data duration (called also fundamental period T = N\*dT; assume dT=1 in your example). The first sample is at 0, the second sample corresponds to 1 cycle per fundamental period (i.e., think of one sine wave with a period equal to the input window length), the third sample corresponds to 2 cycles per fundamental period, etc. (after N/2 the negative frequencies wrap around). If we want to convert cycles per fundamental period to radians per fundamental period (i.e. angular frequencies instead of regular frequencies), we need to multiply by 2pi.

---

<div class="post-metadata">

**Author:** ![bertulli](https://avatars.discourse-cdn.com/v4/letter/b/ecc23a/32.png) [@bertulli](https://discourse.julialang.org/u/bertulli)\
**Post date:** [October 9, 2022, 2:04pm UTC](https://discourse.julialang.org/t/how-do-frequencies-shift-after-a-fft/88089/9 "2022-10-09T14:04:05Z")

</div>

I think I’m slowly getting now. I think I misunderstood some quirks of the DFT, and the problems that arise in the sampling process. For instance, I now get that the DFT has no way of teling what the frequencies were, if you don’t take into account the sampling frequency. That iiuc it’s the reason why `fftfreq()` asks for it!

I am trying to fill my gaps using [this tutorial book](http://complextoreal.com/tutorials/tutorial-6-discrete-time-fourier-series-part-3/).

Anyway, a comment on the line

```julia
fftshift(fftfreq(length(x)) * length(x))

```

I took it from another tutorial, but iiuc it’s not idiomatic: there’s no point in multiplying for `lenght(x)` (the number of samples), the usual way to go is to pass the sampling time to `fftfreq()`, right? With this, frequencies are already good, I think?

---

<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 9, 2022, 3:36pm UTC](https://discourse.julialang.org/t/how-do-frequencies-shift-after-a-fft/88089/10 "2022-10-09T15:36:19Z")

</div>

> [@bertulli](#):
>
> I now get that the DFT has no way of teling what the frequencies were

There is no need to define physical units in the mathematical definition of FFT, as hinted in my previous post. However, the main applications of FFT are in engineering where physical units of time or space are commonly used.

Examples have been posted multiple times in Discourse, including by TheLateKronos above. FWIW find here below another time domain example, annotated.

```julia
using FFTW, Measures, Plots; gr()

Δt = 2e-3 # sampling period [s]
fs = 1/Δt # sampling frequency [Hz]
t = 0:Δt:0.24 # times sampled in [s]
N = length(t)
f0 = 25.0 # sinusoid frequency [Hz]
yt = sin.(2π*f0*t) # sample values at times t
Yf = fft(yt)
f = fftfreq(N, fs) # frequencies of the Yf amplitudes

p1 = plot(t, yt, m=:o, ms=2, xlabel="Time [s]")
p2 = plot(f, abs.(Yf), st=:stem, lw=0.4, m=:o, ms=2, xlabel="Frequency [Hz]")
plot(p1, p2, size=(800,350), margins=5mm)

```

 ![FFT_physical_units](https://global.discourse-cdn.com/julialang/original/3X/a/0/a0285f892313dfeeb1f4fbad28f610766e44dc2a.png)

---

<div class="post-metadata">

**Author:** ![bertulli](https://avatars.discourse-cdn.com/v4/letter/b/ecc23a/32.png) [@bertulli](https://discourse.julialang.org/u/bertulli)\
**Post date:** [October 9, 2022, 5:56pm UTC](https://discourse.julialang.org/t/how-do-frequencies-shift-after-a-fft/88089/11 "2022-10-09T17:56:00Z")

</div>

Many thanks! I think I’m getting it now. 👍

One more thing: in Julia, which is is the coefficient of the DFT? The unitary one (1/\sqrt(N))? And why? (I can open a new topic if this is too OT)

---

<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 9, 2022, 6:22pm UTC](https://discourse.julialang.org/t/how-do-frequencies-shift-after-a-fft/88089/12 "2022-10-09T18:22:26Z")

</div>

> [@bertulli](#):
>
> which is is the coefficient of the DFT?

For the FFTW package see [this section of the manual.](https://www.fftw.org/fftw3_doc/The-1d-Discrete-Fourier-Transform-_0028DFT_0029.html)
