How can I optimize this 4D contour plot?

9 vues (au cours des 30 derniers jours)
iontrap
iontrap le 12 Avr 2023
Commenté : iontrap le 15 Avr 2023
I am trying to make a 4d contour plot using an array with ua, us, g, delta data plotted in {ua, us, g} 3D space with each point having a value of delta. The 4th value of delta will correspond to a color. The data file is attached as output.txt
There seem to be numerous similar questions to this one, most with answers that suggest using a meshgrid + isosurface + patch approach. I don't think this is applicable for me as I do not have a continuous surface over the 3D space. Rather, I have discrete data that may or may not be linearly spaced in each dimension. In this example, ua locations are exponentially spaced while us and g are linearly spaced.
Here is what I have so far:
name = sprintf('output.txt');
data = readtable(name);
data_arr = table2array(data);
ua = data_arr(:,1);
us = data_arr(:,2);
g = data_arr(:,3);
delta = data_arr(:,4);
figure
h = scatter3(ua, us, g, 12, delta,'MarkerFaceColor', 'Flat','MarkerFaceAlpha',.1,'MarkerEdgeAlpha',0.05);
xlabel('{\mu}_a (mm^{-1})');
ylabel('{\mu}_s (mm^{-1})');
zlabel('g');
grid on
colormap(flipud(turbo))
c=colorbar();
c.Label.String = 'delta';
caxis([0 0.6])
which results in the attached figure. I also pair this with the CaptureFigVid function (https://www.mathworks.com/matlabcentral/fileexchange/41093-create-video-of-rotating-3d-plot) to have a nice rotating video. The idea is that with enough sheets in the ua dimension, I can replicate a continuous 3D contour map. I'd like to optimize this method to create a figure with easily visible color contour in the 3D space. Perhaps someone has some experience with this or tips I can try? Perhaps even there is a better, more sophisticated method.
So far, I've tried to play with the values of
'MarkerFaceAlpha',.1,'MarkerEdgeAlpha',0.05
to make the volume transparent.
Perhaps also I could animate alternating through slices of constant ua, like the last example here: http://web.mit.edu/8.13/matlab/MatlabTraining_IAP_2012/AGV/DemoFiles/ScriptFiles/html/Part7_SlicesIsosurfaces.html. However, it looks like the slice() function is not compatible with data in this style.
Rather than slice, I can use
xslice = 0.230849; %% for instance.
scatter3(xslice,us(ua==xslice),g(ua==xslice),ones(size(us(ua==xslice)))*50,delta(ua==xslice))
and write a for loop to step through each value of ua.
Alternatively, I've added a loop to show the slices for each unique value of ua.
unique_ua=unique(ua);
for i = 1:length(unique_ua)
ua_scatter = repmat(unique_ua(i),M,1);
scatter3(ua_scatter,us(ua==unique_ua(i)),g(ua==unique_ua(i)),ones(size(us(ua==unique_ua(i))))*50,delta(ua==unique_ua(i)))
xlim([0 0.675]);
ylim([0.75 14]);
zlim([0 0.875]);
xlabel('{\mu}_a (mm^{-1})');
ylabel('{\mu}_s (mm^{-1})');
zlabel('g');
grid on
colormap(flipud(turbo))
c=colorbar();
c.Label.String = 'delta';
caxis([0 0.6])
pause(0.01);
end
Any other ideas or tips? Thanks.

Réponse acceptée

Ran Yang
Ran Yang le 13 Avr 2023
It looks like you're trying to visualize volumetric data. One way to do that is with slice, but you need to first restructure your data_arr from an Nx4 array of coordinates and values to a 3D volumetric array. V is also more space efficient since you're not repeating the same coordinate information n = 55 times.
data = readtable('output.txt');
% some overhead
x = data{:, 1}; y = data{:, 2}; z = data{:, 3}; c = data{:, 4};
ux = unique(x); uy = unique(y); uz = unique(z);
% assuming you sampled each data point (x,y,z) exactly once,
% brute force convert data_arr to volumetric array, v
v = zeros(length(ux), length(uy), length(uz));
for i = 1:size(v, 1)
for j = 1:size(v, 2)
for k = 1:size(v, 3)
v(i, j, k) = c(x == ux(i) & y == uy(j) & z == uz(k));
end
end
end
% visualize
figure, slice(ux, uy, uz, v, median(ux), median(uy), median(uz));
From this point you can do whatever you need to prettify your data (such as adjusting colormap, rescaling v, etc.), and it should be compatible with other functions (such as isosurface and contourslice). If you want to visualize an evenly spaced grid, see interp3.
  10 commentaires
Ran Yang
Ran Yang le 14 Avr 2023
This whole x/z axis swapping thing is getting annoying, isn't it?
v = reshape(data_sorted{:, 4}, length(uz), length(uy), length(ux)); % swap x/z
v(v > 15) = 15; % for better visualization of output_blood_2.txt only
figure, slice(uz, uy, ux, v, median(uz), median(uy), median(ux)); % swap x/z
For future reference, that GridVectors error just means that your ux,uy,uz "rescaling" vectors (the first 3 input arguments into slice) don't agree with the dimensions of v. You should always able to see your entire volume just by omitting those 3 scaling arguments and directly calling:
figure, slice(v, ...)
If even that doesn't work, or produces resulting patterns that are different than what you expect, then you'd have a much bigger problem (such as reshape not behaving as expected or your data are not 1:1).
Side note: If you have the time, I would recommend you try to figure out what's up with the whole x/z axis swap. I don't really get why I can't just assign it the proper way (why reshape has to be done using z,y,x instead of x,y,z, nested for loop has to be done z,y,x instead of x,y,z, etc.) Maybe that could even be posted as a separate Question on its own, haha.
iontrap
iontrap le 15 Avr 2023
I will look into the x/z axis issue. My knowledge of Matlab is obviously a little lacking, but I'll try to figure it out. Anyways, I can now use isosurface and similar functions to produce very nice looking figures - thanks so much for all of your help.
I think this question and answer may also be useful for others as I saw many unanswered similar versions of this question.
Thanks,
Zachary

Connectez-vous pour commenter.

Plus de réponses (0)

Produits


Version

R2021a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by