代码之家  ›  专栏  ›  技术社区  ›  Vivek Subramanian

用散点图可视化大型三维数据集

  •  3
  • Vivek Subramanian  · 技术社区  · 7 年前

    我在MATLAB中运行一个模拟,其中有一个大的3D数据集,每个时间步长都会发生变化。我试图使用三维散点图来可视化数据,其中的点在模拟过程中具有不同的位置、大小、颜色和透明度。尺寸和颜色信息是冗余的。

    在MATLAB中绘制和旋转图形既慢又不稳定。我的电脑有一个4 GHz i7-4790 CPU和一个NVIDIA GeForce GTX 750 Ti图形卡。我正在Windows 7上使用Matlab R2016a。我检查了Matlab OpenGL设置,硬件支持级别已满。(硬件OpenGL对于透明度是必要的。)此外,我正在使用 GPU-Z 在绘图和旋转期间,GPU负载峰值仅为25-30%。

    以下是我的代码示例:

    load sample_data2
    channels_matrix = cat(1, channels{:});
    num_channels = length(channels);
    channel_lengths = cellfun(@(x) size(x, 1), channels);
    
    figure(1);
    for i = 1:num_channels
        g = plot3(channels{i}(:, 1), channels{i}(:, 2), channels{i}(:, 3), 'k');
        set(g, 'LineWidth', 1.5)
        hold on;
        text(channels{i}(1, 1), channels{i}(1, 2), channels{i}(1, 3), num2str(i))
    end
    caxis([0 1])
    colorbar
    drawnow
    
    numDivisions = 8;
    ptsPerDivision = numel(grid_x)/numDivisions;
    T = 1000;
    numplotpts = 2E4;
    for t = 1:T
        plot_signal = nan(size(grid_x));
        plot_signal(sort(randsample(numel(grid_x), numplotpts))) =...
            sort(rand(numplotpts, 1));
        tic
        for i = 1:numDivisions
            temp = plot_signal(dists_idx((i-1)*ptsPerDivision+1:i*ptsPerDivision));
            yplot = grid_y(dists_idx((i-1)*ptsPerDivision+1:i*ptsPerDivision));
            xplot = grid_x(dists_idx((i-1)*ptsPerDivision+1:i*ptsPerDivision));
            zplot = grid_z(dists_idx((i-1)*ptsPerDivision+1:i*ptsPerDivision));
            if t == 1
                h(i) = scatter3(yplot(~isnan(temp)), xplot(~isnan(temp)),...
                    zplot(~isnan(temp)), 50*temp(~isnan(temp)), temp(~isnan(temp)), ...
                    'filled', 'MarkerFaceAlpha', exp(-i)^0.25);
            else
                h(i).XData = yplot(~isnan(temp));
                h(i).YData = xplot(~isnan(temp));
                h(i).ZData = zplot(~isnan(temp));
                h(i).SizeData = 50*temp(~isnan(temp));
                h(i).CData = temp(~isnan(temp));
            end
        end
        drawnow
        toc
    end
    

    这里有一个链接 data

    编辑 :A related question

    2 回复  |  直到 7 年前
        1
  •  1
  •   informaton    7 年前

    听起来像是 timer 函数是一个很好的尝试下一步,以获得您的模拟的进展,然后作出一个AVI一旦你满意的事情看起来。

    documentation 对于它,有各种连续调用的选项,以及它们之间的间距。查看 ExecutionMode Period

        2
  •  0
  •   EBH    7 年前

    我不确定这会解决所有问题,但作为第一步,我建议将所有计算从用于绘制的循环中去掉。以下是一个建议:

    load sample_data2
    clf
    channels_matrix = cat(1, channels{:});
    num_channels = length(channels);
    channel_lengths = cellfun(@(x) size(x, 1), channels);
    
    figure(1);
    for k = 1:num_channels
        g = plot3(channels{k}(:, 1), channels{k}(:, 2), channels{k}(:, 3), 'k');
        set(g, 'LineWidth', 1.5)
        hold on;
        text(channels{k}(1, 1), channels{k}(1, 2), channels{k}(1, 3), num2str(k))
    end
    caxis([0 1])
    colorbar
    drawnow
    
    numDivisions = 8;
    ptsPerDivision = numel(grid_x)/numDivisions;
    T = 1000;
    numplotpts = 2E4;
    
    % -> chnages starts here:
    
    % first loop for creating random indices
    plot_signal = nan(size(grid_x));
    rand_numplotpts =sort(rand(numplotpts,T),1);
    rand_inds = zeros(numplotpts,T);
    for t = 1:T % one loop for creating random indices
        rand_inds(:,t) = sort(randperm(numel(grid_x),numplotpts));
    end
    plot_signal(rand_inds(:,t)) = rand_numplotpts(:,t);
    
    % second loop for drawing the first instance:
    for k = 1:numDivisions
        temp = plot_signal(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
        yplot = grid_y(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
        xplot = grid_x(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
        zplot = grid_z(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
        h(k) = scatter3(yplot(~isnan(temp)), xplot(~isnan(temp)),...
            zplot(~isnan(temp)), 50*temp(~isnan(temp)), temp(~isnan(temp)), ...
            'filled', 'MarkerFaceAlpha', exp(-k)^0.25);
    end
    
    % third loop to calculate all timesteps:
    [X,Y,Z,S,C] = deal(nan(size(temp,1),numDivisions,T));
    for t = 2:T 
        plot_signal(rand_inds(:,t)) = rand_numplotpts(:,t);
        for k = 1:numDivisions
            temp = plot_signal(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
            yplot = grid_y(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
            xplot = grid_x(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
            zplot = grid_z(dists_idx((k-1)*ptsPerDivision+1:k*ptsPerDivision));
            non_nan_inds = ~isnan(temp);
            inds = 1:sum(non_nan_inds);
            X(inds,k,t) = yplot(non_nan_inds);
            Y(inds,k,t) = xplot(non_nan_inds);
            Z(inds,k,t) = zplot(non_nan_inds);
            S(inds,k,t) = 50*temp(non_nan_inds);
            C(inds,k,t) = temp(non_nan_inds);
        end
    end
    
    % forth loop to draw all data:
    for t = 2:T
        for k = 1:numDivisions
            h(k).XData = Y(:,k,t);
            h(k).YData = X(:,k,t);
            h(k).ZData = Z(:,k,t);
            h(k).SizeData = S(:,k,t);
            h(k).CData = C(:,k,t);
            drawnow
        end
    end