绘制线条周围的阴影区域
Plot shaded region around lines
我正在寻找一种方法来围绕我根据点分布计算出的每条线绘制阴影区域(见附图)。该区域应具有固定宽度(绘制线上方和下方 10 个像素)。事情比平常稍微复杂一些,因为编写代码是为了考虑一系列数据集,并且我需要为每个集合绘制多条曲线(不同集合的数字不同)。我尝试了各种方法,包括 errorbar(f(xx,:), threshold_distance_fit)
,但都没有成功。
你建议如何解决这个问题?
这是我用来绘制数据集和曲线的代码:
g = figure; xlabel('Omega'); ylabel('Y_detector');
plot(Angle, Y_measured, '*'); hold on;
f = zeros(number_centers, 180);
for xx = 1:number_centers
for deg = 1:180
% f is the fitting function
f(xx, deg) = double((R_fit(xx)*sind(alpha_fit(xx)+deg)/0.05)+113);
end
plot(1:180, f(xx,:), '.'); hold on;
end
一个很好的可能性是创建具有更大线宽的相同绘图并使其透明。不幸的是,这在 MATLAB 中不容易实现,但有某种解决方法。您可以使用 z=0
创建一个 surface 图,它看起来与图完全一样。
请注意,如果 x
和 y
分别是大小为 1 x n
和 1 x m
的向量,则 surface
假设 z
是大小为 m x n
的矩阵。因此,您需要制作 x
、y
和 z
矩阵。您可以通过 [x;x]
轻松地做到这一点(假设 x
是一个行向量)。
然后您可以为曲面图指定线宽、颜色和不透明度 (alpha-value)。
例如
x = 0:0.01:2*pi;
y = sin(2*x);
z = zeros(size(x));
hold on;
surface([x;x],[y;y],[z;z], 'linew',20, 'edgecolor','r', 'edgealpha',0.2);
plot(x,y,'-r');
hold off;
创造:
我在使用 patch
或 surface
之间犹豫不决,而 hbaderts 在提出 surface
选项时速度更快,所以我将向您展示如何使用 patch
.
我将在我的示例中提供更多构造细节,但最终您可以根据需要用表面对象替换我的补丁。
首先,我开始构建一系列看起来像您的曲线:
colorCollection = get(0,'defaultAxesColorOrder') ;
nPlot = 4 ;
h.fig = figure ;
h.ax = axes('NextPlot','add') ;
x = linspace(0,180) ;
f = zeros( nPlot , numel(x) ) ;
for k=1:nPlot
f(k,:) = sin(k*x/180*pi) * 180 ;
h.plotf(k) = plot( x , f(k,:) , '.' , 'Color',colorCollection(k,:) ) ;
end
这将创建并绘制 4 条曲线。下一步是解决您的“上方 10 个像素和下方 10 个像素”的请求。绘制的曲线或任何 patch/surface 将没有 "pixel" 的概念,而只有数据 space 中的值。所以你必须知道如何将像素转换为数据或相反。
%// retrieve a few propery values
xlim = get(h.ax,'XLim') ; %// axes X limits
ylim = get(h.ax,'YLim') ; %// axes Y limits
set( [h.ax h.fig] , 'Unit','Pixels') %// set the axes units in pixel
axpos = get( h.ax,'Position') ; %// get the coordinates of the axes object on the figure (in pixels)
nPix.W = round(axpos(3)) ; %// axes WIDTH , in [pixel]
nPix.H = round(axpos(4)) ; %// axes HEIGHT , in [pixel]
%// calculate the vertical data/pixel ratio (to know how much "y" value
%// will correspond to "10" pixels)
nPixelOverlap = 10 ; %// this is defined in your question
pixelRatio = (ylim(2)-ylim(1)) ./ nPix.H ; %// =0.0052 in my example. => 1pixel=0.0052*y
dataOverlap = nPixelOverlap .* pixelRatio ; %// how much I have to add or remove to a curve to cover 10 pixels
一旦我有了这个魔法系数dataOverlap
,我就可以构建必须包含每条曲线的图形对象,它们的上下Y
边界将是曲线的值,dataOverlap
分别加减。
在你的情况下,你似乎没有大向量(没有那么多 x
值),所以下面的部分解决方案可能对你的问题有点矫枉过正。但是,如果您必须对大型数据向量(例如数千或更糟,数百万个元素)做同样的事情,那么创建具有那么多点的许多补丁(甚至曲面)很可能几乎冻结您的图形(响应时间非常慢,如果不会更糟)。一个简单的方法是绘制一个下采样版本。由于我们已经计算了轴跨越多少个像素,我们可以只创建这个大小的图形对象(所以我们基本上每个像素有一个 x
点,仅此而已)。
%// define a minimal "x" vector to populate every pixel in the axes
x4interp = linspace(xlim(1),xlim(2),nPix.W) ;
xpatch = [x4interp fliplr(x4interp)] ; %// common X vector for all the patch objects
ypatch = zeros( nPlot , numel(xpatch) ) ; %// preallocate Y arrays for each patch (one patch per initial curve)
for k=1:nPlot
ytemp = interp1( x , f(k,:) , x4interp ) ; %// reinterp the "k-th" curve value on the new "x" axis
%// prepare the patch "Y" data (=the curve reinterpolated value + and - the overlap
ypatch( k , : ) = [ytemp-dataOverlap fliplr(ytemp)+dataOverlap] ;
%// plot the actual patch
h.patch(k) = patch( xpatch , ypatch(k,:) , colorCollection(k,:) , 'FaceAlpha',0.2 , 'EdgeColor','none' ) ;
end
如果你一次执行这个例子,你应该得到非常相似的东西(颜色可能会有所不同,具体取决于你使用的 Matlab 版本):
正如我上面所说,最后一点重新插值对于这个例子来说有点过头了(补丁实际上比曲线有 更多 数据点),但好处是它非常可扩展。如果您的初始曲线有 107 个点,您可以使用完全相同的方法,补丁不会占用您的内存(您的曲线可能 ).
请注意,pixel/data比例的计算是根据您的屏幕尺寸而定的。如果调整图的大小,计算不会更新。您要么必须 re-execute 计算部分并更新图形对象,要么最简单的方法是先将图形设置为所需的大小,然后执行计算并绘制图形对象。
我正在寻找一种方法来围绕我根据点分布计算出的每条线绘制阴影区域(见附图)。该区域应具有固定宽度(绘制线上方和下方 10 个像素)。事情比平常稍微复杂一些,因为编写代码是为了考虑一系列数据集,并且我需要为每个集合绘制多条曲线(不同集合的数字不同)。我尝试了各种方法,包括 errorbar(f(xx,:), threshold_distance_fit)
,但都没有成功。
你建议如何解决这个问题?
这是我用来绘制数据集和曲线的代码:
g = figure; xlabel('Omega'); ylabel('Y_detector');
plot(Angle, Y_measured, '*'); hold on;
f = zeros(number_centers, 180);
for xx = 1:number_centers
for deg = 1:180
% f is the fitting function
f(xx, deg) = double((R_fit(xx)*sind(alpha_fit(xx)+deg)/0.05)+113);
end
plot(1:180, f(xx,:), '.'); hold on;
end
一个很好的可能性是创建具有更大线宽的相同绘图并使其透明。不幸的是,这在 MATLAB 中不容易实现,但有某种解决方法。您可以使用 z=0
创建一个 surface 图,它看起来与图完全一样。
请注意,如果 x
和 y
分别是大小为 1 x n
和 1 x m
的向量,则 surface
假设 z
是大小为 m x n
的矩阵。因此,您需要制作 x
、y
和 z
矩阵。您可以通过 [x;x]
轻松地做到这一点(假设 x
是一个行向量)。
然后您可以为曲面图指定线宽、颜色和不透明度 (alpha-value)。
例如
x = 0:0.01:2*pi;
y = sin(2*x);
z = zeros(size(x));
hold on;
surface([x;x],[y;y],[z;z], 'linew',20, 'edgecolor','r', 'edgealpha',0.2);
plot(x,y,'-r');
hold off;
创造:
我在使用 patch
或 surface
之间犹豫不决,而 hbaderts 在提出 surface
选项时速度更快,所以我将向您展示如何使用 patch
.
我将在我的示例中提供更多构造细节,但最终您可以根据需要用表面对象替换我的补丁。
首先,我开始构建一系列看起来像您的曲线:
colorCollection = get(0,'defaultAxesColorOrder') ;
nPlot = 4 ;
h.fig = figure ;
h.ax = axes('NextPlot','add') ;
x = linspace(0,180) ;
f = zeros( nPlot , numel(x) ) ;
for k=1:nPlot
f(k,:) = sin(k*x/180*pi) * 180 ;
h.plotf(k) = plot( x , f(k,:) , '.' , 'Color',colorCollection(k,:) ) ;
end
这将创建并绘制 4 条曲线。下一步是解决您的“上方 10 个像素和下方 10 个像素”的请求。绘制的曲线或任何 patch/surface 将没有 "pixel" 的概念,而只有数据 space 中的值。所以你必须知道如何将像素转换为数据或相反。
%// retrieve a few propery values
xlim = get(h.ax,'XLim') ; %// axes X limits
ylim = get(h.ax,'YLim') ; %// axes Y limits
set( [h.ax h.fig] , 'Unit','Pixels') %// set the axes units in pixel
axpos = get( h.ax,'Position') ; %// get the coordinates of the axes object on the figure (in pixels)
nPix.W = round(axpos(3)) ; %// axes WIDTH , in [pixel]
nPix.H = round(axpos(4)) ; %// axes HEIGHT , in [pixel]
%// calculate the vertical data/pixel ratio (to know how much "y" value
%// will correspond to "10" pixels)
nPixelOverlap = 10 ; %// this is defined in your question
pixelRatio = (ylim(2)-ylim(1)) ./ nPix.H ; %// =0.0052 in my example. => 1pixel=0.0052*y
dataOverlap = nPixelOverlap .* pixelRatio ; %// how much I have to add or remove to a curve to cover 10 pixels
一旦我有了这个魔法系数dataOverlap
,我就可以构建必须包含每条曲线的图形对象,它们的上下Y
边界将是曲线的值,dataOverlap
分别加减。
在你的情况下,你似乎没有大向量(没有那么多 x
值),所以下面的部分解决方案可能对你的问题有点矫枉过正。但是,如果您必须对大型数据向量(例如数千或更糟,数百万个元素)做同样的事情,那么创建具有那么多点的许多补丁(甚至曲面)很可能几乎冻结您的图形(响应时间非常慢,如果不会更糟)。一个简单的方法是绘制一个下采样版本。由于我们已经计算了轴跨越多少个像素,我们可以只创建这个大小的图形对象(所以我们基本上每个像素有一个 x
点,仅此而已)。
%// define a minimal "x" vector to populate every pixel in the axes
x4interp = linspace(xlim(1),xlim(2),nPix.W) ;
xpatch = [x4interp fliplr(x4interp)] ; %// common X vector for all the patch objects
ypatch = zeros( nPlot , numel(xpatch) ) ; %// preallocate Y arrays for each patch (one patch per initial curve)
for k=1:nPlot
ytemp = interp1( x , f(k,:) , x4interp ) ; %// reinterp the "k-th" curve value on the new "x" axis
%// prepare the patch "Y" data (=the curve reinterpolated value + and - the overlap
ypatch( k , : ) = [ytemp-dataOverlap fliplr(ytemp)+dataOverlap] ;
%// plot the actual patch
h.patch(k) = patch( xpatch , ypatch(k,:) , colorCollection(k,:) , 'FaceAlpha',0.2 , 'EdgeColor','none' ) ;
end
如果你一次执行这个例子,你应该得到非常相似的东西(颜色可能会有所不同,具体取决于你使用的 Matlab 版本):
正如我上面所说,最后一点重新插值对于这个例子来说有点过头了(补丁实际上比曲线有 更多 数据点),但好处是它非常可扩展。如果您的初始曲线有 107 个点,您可以使用完全相同的方法,补丁不会占用您的内存(您的曲线可能 ).
请注意,pixel/data比例的计算是根据您的屏幕尺寸而定的。如果调整图的大小,计算不会更新。您要么必须 re-execute 计算部分并更新图形对象,要么最简单的方法是先将图形设置为所需的大小,然后执行计算并绘制图形对象。