使用散点图可视化大型 3D 数据集
Visualizing large 3D dataset with scatter plot
我 运行 在 MATLAB 中进行模拟,其中我有一个大型 3D 数据集,每个时间步长都会发生变化。我正在尝试使用 3D 散点图可视化数据,其中的点在模拟过程中呈现不同的位置、大小、颜色和透明度级别。尺寸和颜色信息是多余的。
在 MATLAB 中渲染和旋转图形缓慢且不稳定。我的电脑有一个 4 GHz i7-4790 CPU 和一个 NVIDIA GeForce GTX 750 Ti 显卡。我在 Windows 7 上使用 Matlab R2016a。我检查了我的 MATLAB OpenGL 设置,硬件支持级别已满。 (硬件 OpenGL 是透明度所必需的。)此外,我正在使用 GPU-Z 监视我的 GPU 使用情况,并且在绘图和旋转期间,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
这里是 link 到 data。有什么方法可以加快渲染速度并使旋转更平滑?我注意到将所有数据点的大小固定为单个标量会大大加快渲染和旋转速度。是否可以保持代码中的大小,并且仍然可以快速渲染和旋转图形?
编辑: A related question 我发布了。
听起来 timer
函数是下一步尝试的好地方,以便了解模拟的进展情况,然后在您对外观感到满意后制作 AVI。
MATLAB 有一些很棒的功能 documentation,它有多种连续调用的选项以及它们之间的间隔。查看 ExecutionMode
和 Period
属性。
我不确定这会解决所有问题,但作为第一步,我建议将所有计算从用于绘图的循环中取出。以下是如何操作的建议:
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
我 运行 在 MATLAB 中进行模拟,其中我有一个大型 3D 数据集,每个时间步长都会发生变化。我正在尝试使用 3D 散点图可视化数据,其中的点在模拟过程中呈现不同的位置、大小、颜色和透明度级别。尺寸和颜色信息是多余的。
在 MATLAB 中渲染和旋转图形缓慢且不稳定。我的电脑有一个 4 GHz i7-4790 CPU 和一个 NVIDIA GeForce GTX 750 Ti 显卡。我在 Windows 7 上使用 Matlab R2016a。我检查了我的 MATLAB OpenGL 设置,硬件支持级别已满。 (硬件 OpenGL 是透明度所必需的。)此外,我正在使用 GPU-Z 监视我的 GPU 使用情况,并且在绘图和旋转期间,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
这里是 link 到 data。有什么方法可以加快渲染速度并使旋转更平滑?我注意到将所有数据点的大小固定为单个标量会大大加快渲染和旋转速度。是否可以保持代码中的大小,并且仍然可以快速渲染和旋转图形?
编辑: A related question 我发布了。
听起来 timer
函数是下一步尝试的好地方,以便了解模拟的进展情况,然后在您对外观感到满意后制作 AVI。
MATLAB 有一些很棒的功能 documentation,它有多种连续调用的选项以及它们之间的间隔。查看 ExecutionMode
和 Period
属性。
我不确定这会解决所有问题,但作为第一步,我建议将所有计算从用于绘图的循环中取出。以下是如何操作的建议:
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