Matlab 带有gnuplot或倍频程的3D直方图
我想画一个3D柱状图(带有gnuplot或octave)来表示我的数据。 假设我有一个以下格式的数据文件:Matlab 带有gnuplot或倍频程的3D直方图,matlab,gnuplot,histogram,octave,Matlab,Gnuplot,Histogram,Octave,我想画一个3D柱状图(带有gnuplot或octave)来表示我的数据。 假设我有一个以下格式的数据文件: 2 3 4 8 4 10 5 6 7 我想在集合[1,3]x[1,3]中绘制九个彩色条(矩阵的大小),这样条的颜色与条的高度成比例。我该怎么做呢?你看过吗 稍微调整一下: Z=[2 3 4 8 4 10 5 6 7]; % input data figure; h = bar3(Z); % get handle to graphics for k=1:num
2 3 4
8 4 10
5 6 7
我想在集合[1,3]x[1,3]中绘制九个彩色条(矩阵的大小),这样条的颜色与条的高度成比例。我该怎么做呢?你看过吗
稍微调整一下:
Z=[2 3 4
8 4 10
5 6 7]; % input data
figure;
h = bar3(Z); % get handle to graphics
for k=1:numel(h),
z=get(h(k),'ZData'); % old data - need for its NaN pattern
nn = isnan(z);
nz = kron( Z(:,k),ones(6,4) ); % map color to height 6 faces per data point
nz(nn) = NaN; % used saved NaN pattern for transparent faces
set(h(k),'CData', nz); % set the new colors
end
colorbar;
下面是你在最后得到的:
我没有八度音阶,但我相信这应该可以做到:
Z = [2 3 4
8 4 10
5 6 7];
[H W] = size(Z);
h = zeros( 1, numel(Z) );
ih = 1;
for ix = 1:W
fx = ix-.45;
tx = ix+.45;
for iy = 1:W
fy = iy-.45;
ty = iy+.45;
vert = [ fx fy 0;...
fx ty 0;...
tx fy 0;...
tx ty 0;...
fx fy Z(iy,ix);...
fx ty Z(iy,ix);...
tx fy Z(iy,ix);...
tx ty Z(iy,ix)];
faces = [ 1 3 5;...
5 3 7;...
7 3 4;...
7 8 4;...
5 6 7;...
6 7 8;...
1 2 5;...
5 6 2;...
2 4 8;...
2 6 8];
h(ih) = patch( 'faces', faces, 'vertices', vert, 'FaceVertexCData', Z(iy,ix),...
'FaceColor', 'flat', 'EdgeColor','none' );
ih = ih+1;
end
end
view( 60, 45 );
colorbar;
我认为下面的方法应该可以奏效。我没有使用比
colormap
、surf
和patch
更复杂的东西,据我所知,它们都应该在八度音阶中工作
守则:
%# Your data
Z = [2 3 4
8 4 10
5 6 7];
%# the "nominal" bar (adjusted from cylinder())
n = 4;
r = [0.5; 0.5];
m = length(r);
theta = (0:n)/n*2*pi + pi/4;
sintheta = sin(theta); sintheta(end) = sqrt(2)/2;
x0 = r * cos(theta);
y0 = r * sintheta;
z0 = (0:m-1)'/(m-1) * ones(1,n+1);
%# get data for current colormap
map = colormap;
Mz = max(Z(:));
mz = min(Z(:));
% Each "bar" is 1 surf and 1 patch
for ii = 1:size(Z,1)
for jj = 1:size(Z,2)
% Get color (linear interpolation through current colormap)
cI = (Z(ii,jj)-mz)*(size(map,1)-1)/(Mz-mz) + 1;
fC = floor(cI);
cC = ceil(cI);
color = map(fC,:) + (map(cC,:) - map(fC,:)) * (cI-fC);
% Translate and rescale the nominal bar
x = x0+ii;
y = y0+jj;
z = z0*Z(ii,jj);
% Draw the bar
surf(x,y,z, 'Facecolor', color)
patch(x(end,:), y(end,:), z(end,:), color)
end
end
结果:
如何生成“标称条”是基于MATLAB的cylinder()
中的代码。一件很酷的事情是,你可以很容易地制作出更时髦的酒吧:
这是通过改变
n = 4;
r = [0.5; 0.5];
进入
仅使用倍频程中可用的函数的解决方案,通过测试 此解决方案以与Matlabs
hist3d
函数内部类似的方式生成曲面
简而言之:
- 创建具有4个点的曲面,每个点的“高度”为 值,该值打印在每个存储箱边缘
- 每个箱子都由零包围,这些零也绘制在每个箱子边缘李>
- 颜色设置为基于箱子值,并应用于 4个点和周围的零。(以便“条”的边缘和顶部的颜色与“高度”匹配。)
bin_values=rand(5,4); %some random data
bin_edges_x=[0:size(bin_values,2)];
x=kron(bin_edges_x,ones(1,5));
x=x(4:end-2);
bin_edges_y=[0:size(bin_values,1)];
y=kron(bin_edges_y,ones(1,5));
y=y(4:end-2);
mask_z=[0,0,0,0,0;0,1,1,0,0;0,1,1,0,0;0,0,0,0,0;0,0,0,0,0];
mask_c=ones(5);
z=kron(bin_values,mask_z);
c=kron(bin_values,mask_c);
surf(x,y,z,c)
输出
下面是我实现的一个函数,用作替换(部分) 在我的版本中,这些条是通过创建:我们构建一个矩阵来呈现的 我们的想法是首先构建一个“3d立方体”作为模板,然后将其复制到尽可能多的条上。每个条都会根据其位置和高度进行移动和缩放 顶点/面矩阵以矢量化的方式构造(look ma,无循环!),结果是为所有条绘制一个面片,而不是为每个条绘制一个面片(这更有效) 通过使用
XData
、YData
、ZData
和CData
属性,而不是顶点
和面
属性,可以通过指定形成多边形的连接顶点的坐标来实现该功能。事实上,这就是bar3内部所做的。这种方法通常需要更大的数据来定义面片(因为我们不能在面片面上共享点,尽管在我的实现中我不太关心这一点)。在这里,我试图解释由bar3
构建的数据结构
我的妈妈3.m
请注意,我选择用单一纯色对所有条进行着色(类似于函数的输出),而MATLAB则用匹配的颜色强调矩阵的列
但这很容易理解;下面是一个使用以下方法匹配bar3
的示例:
或者说您想使用以下方法为条形图上色:
请注意,在上一个示例中,将影响渐变的外观。在MATLAB中,“OpenGL”渲染器将沿RGB颜色空间插值颜色,而其他两个渲染器(“Painters”和“ZBuffer”)将跨当前使用的颜色贴图的颜色进行插值(因此,直方图条看起来像是穿过jet
调色板的迷你colorbar
s,而不是从底部的蓝色渐变到定义高度处的任何颜色,如上图所示)。有关更多详细信息,请参阅
我已经在Octave中测试了该功能,并且都在Windows上运行,效果很好。如果运行上面的示例,您会发现一些高级3D功能在Octave中还没有正确实现(包括透明度、照明等)。此外,我还使用了倍频程中不可用的函数,如
membrane
和spiral
来构建示例矩阵,但这些不是代码所必需的,只需用您自己的数据替换即可:)
使用
interp2
和最近邻插值对数据进行重采样,从3×3到300×300,然后使用surf
?@Dan为什么要添加matlab标签?@TomFenech matlab和Octave共享相同的语法和函数,matlab有一个更大的SO社区,因此它应该会增加打个好主意solution@Dan我没意识到他们如此相似。我想,如果确定有效的MATLAB答案也适用于倍频程,那就足够了。@TomFenech不确定,但这极有可能是MATLAB的最佳解决方案-但看起来对于倍频程,bar3
不存在:(@Dan-你能在Octave上检查一下吗?我也没有安装Octave。我通常在这里检查:但它并不总是绘制图形。虽然如此,它不会出错。你能解释一下你的面矩阵吗?@Dan面是一个顶点列表,我怀疑Octave不支持非平面,因此这里的所有面都是三角形(3个顶点)。每个三角形面(一行面
)在顶点
中索引三行。因此面[1 3 5]
是一个连接第一、第三和第五个顶点的三角形。我不需要检查倍频程。好的,我知道了,所以它是每小节10个三角形-谢谢。@Dan:你能验证这在倍频程上是否正确吗(或其在线版本)?在线版本上没有错误,但不幸的是,我无法检查它是否绘制了正确的绘图。我怀疑如果它没有错误,那么它确实可以工作,但我恐怕我无法真正检查。看起来
bin_values=rand(5,4); %some random data
bin_edges_x=[0:size(bin_values,2)];
x=kron(bin_edges_x,ones(1,5));
x=x(4:end-2);
bin_edges_y=[0:size(bin_values,1)];
y=kron(bin_edges_y,ones(1,5));
y=y(4:end-2);
mask_z=[0,0,0,0,0;0,1,1,0,0;0,1,1,0,0;0,0,0,0,0;0,0,0,0,0];
mask_c=ones(5);
z=kron(bin_values,mask_z);
c=kron(bin_values,mask_c);
surf(x,y,z,c)
function pp = my_bar3(M, width)
% MY_BAR3 3D bar graph.
%
% M - 2D matrix
% width - bar width (1 means no separation between bars)
%
% See also: bar3, hist3
%% construct patch
if nargin < 2, width = 0.8; end
assert(ismatrix(M), 'Matrix expected.')
% size of matrix
[ny,nx] = size(M);
% first we build a "template" column-bar (8 vertices and 6 faces)
% (bar is initially centered at position (1,1) with width=? and height=1)
hw = width / 2; % half width
[X,Y,Z] = ndgrid([1-hw 1+hw], [1-hw 1+hw], [0 1]);
v = [X(:) Y(:) Z(:)];
f = [
1 2 4 3 ; % bottom
5 6 8 7 ; % top
1 2 6 5 ; % front
3 4 8 7 ; % back
1 5 7 3 ; % left
2 6 8 4 % right
];
% replicate vertices of "template" to form nx*ny bars
[offsetX,offsetY] = meshgrid(0:nx-1,0:ny-1);
offset = [offsetX(:) offsetY(:)]; offset(:,3) = 0;
v = bsxfun(@plus, v, permute(offset,[3 2 1]));
v = reshape(permute(v,[2 1 3]), 3,[]).';
% adjust bar heights to be equal to matrix values
v(:,3) = v(:,3) .* kron(M(:), ones(8,1));
% replicate faces of "template" to form nx*ny bars
increments = 0:8:8*(nx*ny-1);
f = bsxfun(@plus, f, permute(increments,[1 3 2]));
f = reshape(permute(f,[2 1 3]), 4,[]).';
%% plot
% prepare plot
if exist('OCTAVE_VERSION','builtin') > 0
% If running Octave, select OpenGL backend, gnuplot wont work
graphics_toolkit('fltk');
hax = gca;
else
hax = newplot();
set(ancestor(hax,'figure'), 'Renderer','opengl')
end
% draw patch specified by faces/vertices
% (we use a solid color for all faces)
p = patch('Faces',f, 'Vertices',v, ...
'FaceColor',[0.75 0.85 0.95], 'EdgeColor','k', 'Parent',hax);
view(hax,3); grid(hax,'on');
set(hax, 'XTick',1:nx, 'YTick',1:ny, 'Box','off', 'YDir','reverse', ...
'PlotBoxAspectRatio',[1 1 (sqrt(5)-1)/2]) % 1/GR (GR: golden ratio)
% return handle to patch object if requested
if nargout > 0
pp = p;
end
end
subplot(121), bar3(magic(7)), axis tight
subplot(122), my_bar3(magic(7)), axis tight
M = membrane(1); M = M(1:3:end,1:3:end);
h = my_bar3(M, 1.0);
% 6 faces per bar
fvcd = kron((1:numel(M))', ones(6,1));
set(h, 'FaceVertexCData',fvcd, 'FaceColor','flat', 'CDataMapping','scaled')
colormap hsv; axis tight; view(50,25)
set(h, 'FaceAlpha',0.85) % semi-transparent bars
M = 9^2 - spiral(9);
h = my_bar3(M, 0.8);
% use Z-coordinates as vertex colors (indexed color mapping)
v = get(h, 'Vertices');
fvcd = v(:,3);
set(h, 'FaceVertexCData',fvcd, 'FaceColor','interp')
axis tight vis3d; daspect([1 1 10]); view(-40,20)
set(h, 'EdgeColor','k', 'EdgeAlpha',0.1)