Search code examples
matlab3ddata-visualizationmatlab-figurescatter-plot

Visualizing large 3D dataset with scatter plot


I'm running a simulation in MATLAB in which I have a large 3D dataset that changes each time step. I'm trying to visualize the data using a 3D scatter plot with points that take on different locations, sizes, colors, and transparency levels as the simulation proceeds. The size and color information are redundant.

Rendering and rotating the figure in MATLAB is slow and choppy. My computer has a 4 GHz i7-4790 CPU and a NVIDIA GeForce GTX 750 Ti graphics card. I am using Matlab R2016a on Windows 7. I checked my MATLAB OpenGL settings and the hardware support level is full. (Hardware OpenGL is necessary for transparency.) Moreover, I'm monitoring my GPU usage using GPU-Z, and during plotting and rotation, the GPU load peaks at only 25-30%.

Here is my code sample:

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

and here is a link to the data. Is there any way to speed up the rendering and make rotation smoother? I noticed that fixing the size of all data points to a single scalar greatly speeds up rendering and rotation. Is it possible to keep the size as it is in the code and still have the figure render and rotate quickly?

Edit: A related question I posted.


Solution

  • It sounds like the timer function is a good place to try next in order to get a sense of your simulation's progression and then making an AVI once you are satisfied with how things look.

    MATLAB's got some great documentation for it with a variety of options for consecutive calls are made and the spacing between them. Check out the ExecutionMode and Period properties.