I have written a python script to compute DFT of a simple sin wave having frequency 3. I have taken the following consideration for taking sample of the sin wave
sin function for test = sin( 2 * pi * 3 * t )
sample_rate = 15
time interval = 1/sample_rate = 1/15 = ~ 0.07 second
sample_duration = 1 second (for test1) and 2 seconds (for test 2)
sample_size = sample_rate * sample_duration = 15*2 = 30 samples
I run the same code for sample_duration both 1 and 2 seconds. When sample duration is 1 second, the graph produce shows the presence of frequency=3 present in the sin wave,which is correct.
But if I change the sample duration to 2 second, the graph peaks at frequency= 6, which does not present in the sin wave.But it is a factor of 2 increase of the original frequency (3*2) = 6.
And if 3 second is taken as sample duration, graph peaks at 9 second.
I was thinking that taking more sample for longer duration will produce finer result, but that is clearly not the case here.
code :
from sage.all import *
import matplotlib.pyplot as plt
import numpy as np
t = var('t')
sample_rate = 15 # will take 100 sample each second
interval = 1 / sample_rate # time interval between each reading
sample_duration = 1 # take sample over a duration of 1 second
sample_size_N = sample_rate*sample_duration #count number of touples in r array, len(r) will give sample size/ total number of sample taken over a specific duration
func = sin(3*2*pi*t)
time_segment_arr = []
signal_sample_arr= []
# take reading each time interval over sample_duration period
for time_segment in np.arange(0,sample_duration,interval):
# give discrete value of the signal over specific time interval
discrete_signal_value = func(t = time_segment)
# push time value into array
time_segment_arr.append(time_segment)
# push signal amplitude into array
signal_sample_arr.append(N(discrete_signal_value))
def construct_discrete_transform_func():
s = ''
k = var('k')
for n in range(0,sample_size_N,1):
s = s+ '+'+str((signal_sample_arr[n])* e^(-(i*2*pi*k*n)/sample_size_N))
return s[1:] #omit the forward + sign
dft_func = construct_discrete_transform_func()
def calculate_frequency_value(dft_func,freq_val):
k = var('k')
# SR converts string to sage_symbolic_ring expression & fast_callable() allows to pass variable value to that expression
ff = fast_callable(SR(dft_func), vars=[k])
return ff(freq_val)
freq_arr = []
amplitude_arr = []
#compute frequency strength per per frequency
for l in np.arange(0,sample_size_N,1):
freq_value = calculate_frequency_value(dft_func,l)
freq_arr.append(l)
amplitude_arr.append(N(abs(freq_value)))
your Frequency
axis is wrong, the lowest frequency on the DFT axis should be 1/N
which can be translated to time domain to be 1/T
, that is when the total time is 2 seconds, the first point after zero will be at 0.5 Hz not 1 Hz
the longest sine wave a DFT can represent (the lowest frquency) is a sine wave that does 1 cycle over the entire duration. (k = 1
), you can get 1/T
from
substituting t = n * Ts
. (where Ts
is the sample interval) then Ts = T/N
where T
is the total time
which results in f = k / T
and the lowest frequency k = 1
translates to f = 1 / T
this is just a plotting error, in the not-shown plotting code.