繁体   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