Matlab:sign()函数的傅立叶系数振荡 [英] Matlab: fourier coefficients of sign() function are oscillating

查看:393
本文介绍了Matlab:sign()函数的傅立叶系数振荡的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个接收时变信号并返回FFT的函数.它遵循Matlab文档:

I'm writing a function that takes in a time-varying signal and returns the FFT. It follows the Matlab documentation:

  • https://www.mathworks.com/help/matlab/math/fourier-transforms.html
  • https://www.mathworks.com/help/matlab/ref/fftshift.html

它对于非常简单的正弦波总和非常有效.

It works well for really simple sums of sinusoids.

对于其他模拟信号,例如阶跃函数,我最终得到了一些fubar,它们以锯齿状的方式振荡.这是一个使用重边阶跃函数的最小示例,该函数绘制了FFT权重的虚部:

For other simulated signals, like step functions, I end up with something fubar, that oscillates in a sawtooth-like fashion. Here is a minimal example using a heaviside step function, that plots the imaginary component of the FFT weight:

%Create and plot sign function 
Fs = 1000;
dt = 1/Fs;
tvals = -1: dt: 1-dt;
yvals = sign(tvals); %don't use heaviside() it is very slow

subplot(2,1,1);
    plot(tvals, yvals, 'k', 'LineWidth', 2); hold on; 
    axis([-1 1 -1.1 1.1]);

%Calculate center-shifted FFT and plot imaginary part
fftInitial = fft(yvals);
n = length(fftInitial);
dF = Fs/n;
frequenciesShifted = -Fs/2: dF: Fs/2-dF;  %zero-centered frequency range
fftShifted = fftshift(fftInitial/length(yvals));

subplot(2,1,2);
plot(frequenciesShifted, imag(fftShifted), 'b', 'LineWidth', 2);hold on
xlim([-8 8])

这是结果图:

请注意,假想解已知为2/jwj(-2/w).

Note the imaginary solution is known to be 2/jw, or j(-2/w).

请注意,除了锯齿之外(这是我最关心的问题),这些砝码的信封似乎都没有遵循.实际上,它似乎在原点周围翻转了.不知道我在这里做错了什么事情.

Note in addition to the sawtooth, which is my primary concern, the envelope of these weights doesn't even seem to follow that. It actually seems flipped around the origin. Not sure what combination of things I've done wrong here.

基于一些有用的反馈,人们指出了这个问题:
Matlab中函数的分析傅立叶变换与FFT

Based on some helpful feedback, people pointed out this question:
Analytical Fourier transform vs FFT of functions in Matlab

尤其是,在时间数组中不包括零可能会引起问题,这是此处的主要问题.我的代码中的时间数组包含零,因此它看起来不像是重复的.我通过时移步骤将零推到了数组的最前面(尽管坦率地说,我没有做很多的fft(),而且它们看起来都很好,所以我不认为这是问题所在,但是我只想暂时将其删除).所以我们最终得到:

In particular, not including a zero in the time array could cause problems, which was a main concern there. The time array in my code includes a zero, so it doesn't seem like a duplicate. I have pushed my zero to the front of the array by time-shifting the step (though frankly I have done lots of fft() without doing this and they have all looked fine, so I don't imagine that is the problem, but I just want to remove that as an issue for now). So we end up with:

Fs = 1000;
dt = 1/Fs;
tvals = 0: dt: 2-dt;
yvals = sign(tvals-1); %don't use heaviside() it is very slow
zeroInd = find(yvals == 1, 1, 'first');
yvals(zeroInd-1) =0;
%Calculate center-shifted FFT and plot imaginary part
fftInitial = fft(yvals);
n = length(fftInitial);
dF = Fs/n;
frequenciesShifted = -Fs/2: dF: Fs/2-dF;  %zero-centered frequency range
fftShifted = fftshift(fftInitial/length(yvals));

%Plot stuff
subplot(2,1,1);
plot(tvals, yvals, 'k', 'LineWidth', 2); hold on; 
axis([0 2 -1.1 1.1]);  
subplot(2,1,2);
plot(frequenciesShifted, imag(fftShifted), 'b', 'LineWidth', 2);hold on
xlim([-8 8])
grid on;

我仍然使用相同的错误信封获得相同的Zig-Zaging功能.因此,尽管我确实看到我的问题与该问题密切相关,但我不确定它们是否重复.而且我真的很想能够绘制这些成分的值的中途观察图(我确实使用了一些基本为阶跃函数的生理信号(与我相比,它们非常移动得非常快测量仪器,所以这对我来说不仅仅是一个学术练习.

I still get the same zig-zagging function with the same incorrect envelope. So, while I do see that my question and that question are closely related, I am not sure they are duplicates. And I would really like to be able to draw a halfway-reasonable looking plot of the values of these components (I do work with some physiological signals that are basically step functions (they move very fast compared to my measuring instruments, so this is not just an academic exercise for me).

推荐答案

您的代码有两个问题:

  1. DFT(FFT算法计算DFT)将原点放在最左侧的bin处.创建yvals使得原点在中间会导致输出频谱变为信号偏移其长度一半的频谱.这导致非常高的频率振荡.解决方法是在调用fft之前在输入数据 上使用ifftshift.查看其他在此其他问题中

  1. The DFT (the FFT algorithm computes the DFT) takes the origin to be at the leftmost bin. Creating yvals such that the origin is in the middle causes the output Frequency spectrum to be that of a signal shifted by half its length. This leads to very high frequency oscillations. The fix is to use ifftshift on the input data before calling fft. See more in this other question

DFT假定(可以解释为假设)输入信号是周期性的.这导致第二次大跳.基本上,您的信号看起来像是移位框函数,因此您的变换看起来像是具有修改后相位的Sinc函数.解决方案是在调用fft之前将窗口功能应用于输入 .参见例如其他问题.

The DFT assumes (can be interpreted as assuming) that the input signal is periodic. This leads to a second large jump. Basically, your signal looks like a shifted box function, and hence your transform looks like a sinc function with modified phase. The solution is to apply a windowing function to your input before calling fft. See for example this other question.

按如下所示修改您的代码:

Modify your code as follows:

yvals = sign(tvals);
yvals = yvals .* hanning(numel(yvals), 'periodic').'; % Apply windowing function

% ...

fftInitial = fft(ifftshift(yvals)); % Shift signal before calling FFT

这是您的代码现在提供的输出:

This is the output your code now gives:

这篇关于Matlab:sign()函数的傅立叶系数振荡的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆