【问题标题】:Filling in the area between two curves, between specific points in MATLAB在MATLAB中的特定点之间填充两条曲线之间的区域
【发布时间】:2016-05-16 19:52:41
【问题描述】:

我有一个 PSD 图,我正在尝试计算并填充 MATLAB 中两条曲线之间的区域,用于两个不同的频率范围(8-30 Hz 和 70-100 Hz)。

这是我用来生成绘图的代码,其中f=frequency 和Zm,Z 代表两个条件的 Z 分数:

plot(f,Zm,f,Z,'LineWidth',2)
xlim([0 100]);
xlabel('Frequency (Hz)');
ylabel('Normalized Power');

我相信我需要使用trapz函数来计算面积和填充函数来填充空间,但我不确定如何使用这些函数来执行特定频率之间的计算。

为了进一步复杂化,我只想对频率为 8-30Hz 的 Zm Z 的区域进行着色。

这是有问题的情节:

【问题讨论】:

  • 相关:blogs.mathworks.com/graphics/2015/10/13/fill-between。另外,我对您的问题进行了一些修改,如果您有任何不同意,请随时更改。
  • @AndrasDeak:那是我需要的完美参考。效果很好!
  • 很高兴听到这个消息:) 如果您的最终解决方案与 Arzeik 的答案明显不同,您应该考虑添加自己的答案作为另一个答案(特别是如果有任何不重要的地方)。
  • @AndrasDeak:我结束了使用建议的组合(包括您发布的博客文章),并将其发布在下面的答案中。我仍然不确定如何计算面积。我只想要低频的 Zm Zm 的区域。我应该在一个单独的问题中问这个吗?
  • @SaraA 是的。当您设法解决当前问题中概述的问题时,请将其作为一个单独的问题提出。在这种情况下也请接受你自己的答案(自我接受有 24 小时的延迟,所以你明天必须这样做)

标签: matlab


【解决方案1】:

为了计算面积,这样的事情可能会起作用:

r1=(f>=8).*(f<=30);
r2=(f>=70).*(f<=100);
area=trapz(f(r1),Zm(r1)-Z(r1))+trapz(f(r2),Zm(r2)-Z(r2));

为了填充第一个区域,你可以尝试:

f1=f(r1);
Zm1=Zm(r1);
Z1=Z(r1);
for i=1:length(f1)-1
    fill([f1(i) f1(i+1) f1(i+1) f1(i)],[Z1(i) Z1(i+1) Zm1(i+1) Zm1(i)],'blue');
end

第二个类似。

如果您只想填充 Zm 小于 Z 的区域,您可以使用相同的代码,但在 for 循环中添加一个 if。比如:

for i=1:length(f1)-1
    if Zm1(i)<Z1(i) && Zm1(i+1)<Z1(i+1)
        fill([f1(i) f1(i+1) f1(i+1) f1(i)],[Z1(i) Z1(i+1) Zm1(i+1) Zm1(i)],'blue');
    end
end

【讨论】:

  • 这很棒!我唯一不同的是使用“&”符号代替 r1=(f>=8 & f=70 & f
  • 为了使事情更复杂,我忘了提到我只想对频率为 8-30Hz 的 Zm Z 的区域进行着色。知道如何添加此条件吗?
【解决方案2】:

这是我最终使用的代码(建议的组合):

%// Fill in area between low frequency bands
f1=f(r1)'; %'// <-- this prevents string markdown
Zm1=Zm(r1);
Z1=Z(r1);

mask = Zm1 <= Z1;
fx = [f1(mask), fliplr(f1(mask))];
fy = [Zm1(mask),fliplr(Z1(mask))];
hold on
fill_color = [.040 .040 1];
fh = fill(fx,fy,fill_color);
hold off
%fh.EdgeColor = 'none';

delete(fh)

hold on
output = [];
%// Calculate t in range [0 1]
calct = @(n) (n(3,1)-n(2,1))/(n(3,1)-n(2,1)-n(3,2)+n(2,2));
%// Generate interpolated X and Y values
interp = @(t,n) n(:,1) + t*(n(:,2) - n(:,1));

for i=1:length(f1)
%// If y2 is below y1, then we don't need to add this point.
if Z1(i) <= Zm1(i)
    %// But first, if that wasn't true for the previous point, then add the
    %// crossing.
    if i>1 && Z1(i-1) > Zm1(i-1)
        neighborhood = [f1(i-1), f1(i); Zm1(i-1), Zm1(i); Z1(i-1), Z1(i)];
        t = calct(neighborhood);
        output(:,end+1) = interp(t,neighborhood);
    end
else
%// Otherwise y2 is above y1, and we do need to add this point. But first
%// ...
    %// ... if that wasn't true for the previous point, then add the
    %// crossing.
    if i>1 && Z1(i-1) <= Zm1(i-1)
        neighborhood = [f1(i-1), f1(i); Zm1(i-1), Zm1(i); Z1(i-1), Z1(i)];
        t = calct(neighborhood);
        output(:,end+1) = interp(t,neighborhood);
    end

    %// add this point.
    output(:,end+1) = [f1(i); Z1(i); Zm1(i)];
end
end

xout = output(1,:);
topout = output(2,:);
botout = output(3,:);
fh = fill([xout fliplr(xout)],[botout fliplr(topout)],fill_color);
fh.EdgeColor = 'none';
uistack(fh,'bottom')
hold off

我对高频重复了这个。

结果图:

【讨论】: