簡體   English   中英

如何在Python中得到正弦波的相位直流偏移和幅度

[英]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)

plot 顯示拐點就在峰值頻率倉處。 在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM