[英]How to get phase DC offset and amplitude of sine wave in Python
我有一個已知頻率的正弦波,在奈奎斯特頻率附近有一些樣本均勻的噪聲。 我想獲得幅度、相位和直流偏移的近似值。 我搜索了一個答案並找到了幾個接近我需要的答案,但仍然無法編寫實現我需要的適當代碼。 當我運行下面的代碼時,我得到了錯誤的相位和振幅。 很樂意得到一些幫助。
import sys
import numpy
import pylab as plt
def cosfunc(time, amplitude, omega, phase, offset):
''' Function to create sine wave. Phase in radians '''
return amplitude * numpy.cos(omega*time + phase) + offset
def get_cosine_approx(timeline,sine_data):
points_num=len(timeline)
fft_freq = numpy.fft.fftfreq(points_num-1, timeline[1]-timeline[0]) # assume uniform spacing
fft_result=numpy.fft.fft(sine_data)
#Remove negative frequencies
for i in range(len(fft_freq)):
if fft_freq[i]<0:
fft_result[i]=0
ampl=numpy.abs(fft_result)/points_num*2
max_index=numpy.argmax(ampl)
guess_amplitude=ampl[max_index]
phase_unwrapped=numpy.unwrap(numpy.angle(fft_result))
guess_phase=phase_unwrapped[max_index]
guess_phase_dig=guess_phase*180./numpy.pi
print("freq",fft_freq[max_index])
print("amplitude",guess_amplitude)
print("phase",guess_phase_dig)
plt.plot(timeline, sine_data, "ok", label="sine")
new_timeline=numpy.linspace(timeline[0], timeline[-1], len(timeline)*1000)
plt.plot(new_timeline, cosfunc(new_timeline,guess_amplitude,2.*numpy.pi*56e9,guess_phase,0), "r-", label="fit")
plt.legend(loc="best")
plt.show()
return {"amp":guess_amplitude, "ph":guess_phase,"ph_dig":guess_phase_dig}
N = 256 # Sample points
f=56e9 #56GHz
t = numpy.linspace(0.0, 100./f, N) # Time
omega = 2.*numpy.pi*f
offset=0
phase=0
A=1.
cos=cosfunc(t,A,omega,phase,offset)
result=get_cosine_approx(t,cos)
您在拐點處捕獲相位,此時相位突然從 +pi/2 過渡到 -pi/2,而您正在查看的 bin 正好在下坡滑道的中途。 這只是因為 FFT 結果不連續。 單個 bin 跨越一系列頻率。
注意當我們 plot 相位和振幅時:
import sys
import numpy as np
import matplotlib.pyplot as plt
def cosfunc(time, amplitude, omega, phase, offset):
''' Function to create sine wave. Phase in radians '''
return amplitude * np.cos(omega*time + phase) + offset
def get_cosine_approx(timeline,sine_data):
points_num=len(timeline)
fft_freq = np.fft.fftfreq(points_num, timeline[1]-timeline[0])
fft_result=np.fft.fft(sine_data)
fft_freq = np.fft.fftshift(fft_freq)
fft_result = np.fft.fftshift(fft_result)
ampl = np.abs(fft_result) * 2 / points_num
phase = np.angle(fft_result)
plt.plot(fft_freq, ampl, label='ampl' )
plt.plot(fft_freq, phase, label='phase' )
plt.legend(loc="best")
plt.show()
return 0
N = 256 # Sample points
f=56e9 #56GHz
t = np.linspace(0.0, 100./f, N) # Time
omega = 2.*np.pi*f
offset=0
phase=0
A=1.
cos=cosfunc(t,A,omega,phase,offset)
result=get_cosine_approx(t,cos)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.