带有gnuplot或八度音阶的3D直方图

时间:2014-06-12 09:27:08

标签: matlab gnuplot histogram octave

我想绘制一个3D直方图(带有gnuplot或octave)以表示我的数据。 假设我有一个以下形式的数据文件:

2 3 4    
8 4 10    
5 6 7

我想在集合[1,3] x [1,3]中绘制九个彩色条(矩阵的大小),这样条的颜色与酒吧的高度。我怎么能这样做?

5 个答案:

答案 0 :(得分:12)

以下是我实施的一项功能,可以作为bar3替换(部分)。

在我的版本中,通过创建patch graphics object来渲染条形图:我们构建了一个vertex coordinates and a list of faces connecting those vertices的矩阵。

这个想法是首先构建一个单一的“立方体”#34;作为模板,然后复制它为我们有多少个酒吧。每个栏都根据其位置和高度进行移动和缩放。

顶点/面矩阵以矢量化方式构造(看起来没有循环!),结果是为所有条形绘制的单个patch object,而不是每个条形一个多个补丁(这是在graphics performance)方面效率更高。

可以通过使用XDataYDataZDataCData属性而不是{VerticesFacesbar3bar3属性指定形成多边形的连接顶点的坐标来实现此功能。 {1}}和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 属性。实际上这就是bar3内部所做的事情。这种方法通常需要更大的数据来定义补丁(因为我们不能在补丁面上有共享点,尽管我在实现中并不关心它)。这是一个related post,我试图解释由subplot(121), bar3(magic(7)), axis tight subplot(122), my_bar3(magic(7)), axis tight 构建的数据的结构。

my_bar3.m

bar3

以下是将其与MATLAB中的内置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)

comparison_bar3

请注意,我选择使用单一纯色(与hist3函数的输出相似)为所有条形图着色,而MATLAB强调矩阵的列具有匹配的颜色。

虽然很容易customize the patch;以下是使用coloring mode匹配colorbar indexed color mapping (scaled)的示例:

jet

bar3_coloring

或者说您想使用gradient according to their heights

为条形设置颜色
membrane

gradient_bars_animation

请注意,在上一个示例中,"Renderer" property of the figure会影响渐变的外观。在MATLAB中,&#39; OpenGL&#39;渲染器将​​沿RGB颜色空间插入颜色,而其他两个渲染器(&#39; Painters&#39;和ZBuffer&#39;)将在所使用的当前颜色映射的颜色之间进行插值(因此直方图条看起来如此比如迷你spiral穿过{{1}}调色板,而不是从底部的蓝色到任何颜色在定义高度的渐变,如上所示)。有关详细信息,请参阅this post


我已经在Windows上运行的Octave 3.6.43.8.1中测试了该功能,并且运行正常。如果您运行我上面显示的示例,您会发现某些高级3D功能尚未在Octave中正确实现(这包括透明度,照明等等)。此外,我还使用了{{1}}和{{1}}等Octave中不可用的函数来构建样本矩阵,但这些函数对代码并不重要,只需将它们替换为您自己的数据:)

octave_my_bar3

答案 1 :(得分:3)

我无法访问Octave,但我相信这应该可以解决问题:

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;

答案 2 :(得分:3)

我认为以下应该可以解决问题。我没有使用比colormapsurfpatch更复杂的东西,据我所知,这些都应该在Octave中按原样运行。

代码:

%# 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

结果:

enter image description here

我如何生成&#34;标称栏&#34;基于MATLAB&#39; cylinder()的代码。一个很酷的事情就是你可以很容易地制作出更加时髦的酒吧:

enter image description here

这是通过更改

生成的
n = 4;
r = [0.5; 0.5];

进入

n = 8;
r = [0.5; 0.45; 0.2; 0.1; 0.2; 0.45; 0.5];

答案 3 :(得分:3)

解决方案仅使用OCTAVE中提供的功能,使用octave-online

进行测试

此解决方案以类似于Matlabs hist3d函数内部的方式生成表面。

简而言之:

  • 使用&#34; height&#34;创建一个带有4个点的曲面。每个 值,在每个箱边绘制。
  • 每个都被零包围,也在每个bin边缘绘制。
  • 颜色设置为基于bin值并应用于 4点和周围的零点。 (以便&#39;条的边缘和顶部被着色以匹配&#34;高度&#34;。)

对于以包含bin高度的矩阵形式给出的数据(代码中的bin_values):

<强>代码

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)

<强>输出

3dhist

答案 4 :(得分:2)

你看过this tutorial on bar3吗?

稍微调整一下:

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;

这就是你最后得到的: enter image description here