plot magnitude data at location (x,y,z)
이 질문을 팔로우합니다.
- 팔로우하는 게시물 피드에서 업데이트를 확인할 수 있습니다.
- 정보 수신 기본 설정에 따라 이메일을 받을 수 있습니다.
오류 발생
페이지가 변경되었기 때문에 동작을 완료할 수 없습니다. 업데이트된 상태를 보려면 페이지를 다시 불러오십시오.
이전 댓글 표시
0 개 추천
I can't figure out how to plot magnitudes of a variable at different (x,y,z) locations. In effect, I need to plot a 4D plot, (x,y,z,value). I thought I'd be able to do a 3D plot and set the 4D as color scale or something like that, but I can't figure how to do that.
Perhaps I'm over thinking this....but, I'd appreciate any help.
Thanks!
Jorge
채택된 답변
Star Strider
2024년 8월 22일
@Jorge —
Try this —
LD = load('data')
LD = struct with fields:
data: [201x4 double]
x = LD.data(:,1);
y = LD.data(:,2);
z = LD.data(:,3);
c = LD.data(:,4);
figure
stem3(x, y, z)
hold on
scatter3(x, y, z, 100, c, 'filled')
hold off
CL = clim;
colormap(turbo)
xlabel('X')
ylabel('Y')
zlabel('Z')
view(130,30)

Zfcn = scatteredInterpolant(x, y, z, 'natural','none'); % Create Surface Matrix
Warning: Duplicate data points have been detected and removed - corresponding values have been averaged.
Cfcn = scatteredInterpolant(x, y, c, 'natural','none'); % Create Colour MAtrix
Warning: Duplicate data points have been detected and removed - corresponding values have been averaged.
N = numel(x);
xv = linspace(min(x), max(x), N);
yv = linspace(min(y), max(y), N);
[Xm,Ym] = ndgrid(xv, yv);
Zm = Zfcn(Xm, Ym);
Cm = Cfcn(Xm, Ym);
figure
surfc(Xm, Ym, Zm, Cm, 'EdgeColor','interp')
clim(CL)
colormap(turbo)
xlabel('X')
ylabel('Y')
zlabel('Z')
view(130,30)

The only change from my previous answer was using your data. Some parts do not interpolate well and leave gaps, however that appears to be inhereint in your data, at least as far as scatteredInterpolant interprets them.
.
댓글 수: 13
Jorge
2024년 8월 22일
excellent, thank you!
Star Strider
2024년 8월 22일
As always, my pleasure!
Jorge
2024년 8월 22일
btw, I was in the process of responding to your first proposed solution when you responded again using the my sample data. Thank you!
Star Strider
2024년 8월 22일
As always, my pleasure!
When I checked and saw that you had posted a comment, I wanted to see what you wrote. At that point I saw the file and then adapted it to my existing code.
Can you try it with the whole data? I think the duplicate values are affecting the result. I think the
Zfcn = scatteredInterpolant(x, y, z,'natural','none'); % Create Surface Matrix
should be
Zfcn = scatteredInterpolant(x, y, z,val,'natural','none'); % Create Surface Matrix
?
attached is the full data...
Thanks again.
Jorge
2024년 8월 22일
I only unaccepted the previous answer in case accepting it "close" this question and you'd never see my new (continuation) issue. thanks
Star Strider
2024년 8월 23일
편집: Star Strider
2024년 8월 23일
The scatteredInterpolant function replaces the mean of the duplicated values with the duplicate values and deletes the others. Note that ‘data’ appears as a structure loading it into a avariable, and simply a matrix otherwsie. I don’t know what ‘val’ is, since ‘data’ is a matrix and not a table, so I assume the fourth column is the fourth dimension that is to be used to assign the colours.
In this instance, with the duplicated values, it takes the mean of each duplicate and plots it as the mean of the values. Here, there are four distinct ‘layers’, and each layer must be rencered separately.
This is what I get with the new ‘data.mat’ file —
load('data')
whos( '-file','data')
Name Size Bytes Class Attributes
data 560x4 17920 double
LD = load('data')
LD = struct with fields:
data: [560x4 double]
x = LD.data(:,1);
y = LD.data(:,2);
z = LD.data(:,3);
c = LD.data(:,4);
figure
stem3(x, y, z)
hold on
scatter3(x, y, z, 100, c, 'filled')
hold off
CL = clim;
colormap(turbo)
xlabel('X')
ylabel('Y')
zlabel('Z')
view(-45,30)

[Uz,ixs,ixv] = unique(z);
L = accumarray(ixv, (1:numel(ixv)).', [], @(v) {[x(v) y(v) z(v) c(v)]})
L = 5x1 cell array
{112x4 double}
{112x4 double}
{112x4 double}
{112x4 double}
{112x4 double}
figure
hold on
for k = 1:numel(L)
x = L{k}(:,1);
y = L{k}(:,2);
z = L{k}(:,3);
c = L{k}(:,4);
Zfcn = scatteredInterpolant(x, y, z, 'natural','none'); % Create Surface Matrix
Cfcn = scatteredInterpolant(x, y, c, 'natural','none'); % Create Colour MAtrix
N = numel(x);
xv = linspace(min(x), max(x), N);
yv = linspace(min(y), max(y), N);
[Xm,Ym] = ndgrid(xv, yv);
Zm = Zfcn(Xm, Ym);
Cm = Cfcn(Xm, Ym);
surf(Xm, Ym, Zm, Cm, 'EdgeColor','interp')
clim(CL)
colormap(turbo)
end
hold off
xlabel('X')
ylabel('Y')
zlabel('Z')
view(-45,30)
grid on

figure
hold on
for k = 1:numel(L)
x = L{k}(:,1);
y = L{k}(:,2);
z = L{k}(:,3);
c = L{k}(:,4);
Zfcn = scatteredInterpolant(x, y, z, 'natural','none'); % Create Surface Matrix
Cfcn = scatteredInterpolant(x, y, c, 'natural','none'); % Create Colour MAtrix
N = numel(x);
xv = linspace(min(x), max(x), N);
yv = linspace(min(y), max(y), N);
[Xm,Ym] = ndgrid(xv, yv);
Zm = Zfcn(Xm, Ym);
Cm = Cfcn(Xm, Ym);
surf(Xm, Ym, Zm, Cm, 'EdgeColor','interp')
clim(CL)
colormap(turbo)
end
hold off
xlabel('X')
ylabel('Y')
zlabel('Z')
view(-45,30)
grid on
daspect(gca, [2.5 1 5])

I doubt that a volumetric version of this is possible, since that is not how the data are arranged. Plotting four distinct layers is likely the best possible outcome. It is possible to ‘squash’ it a bit in the z-direction, however that does not appear to accomplish much. Experiment with the daspect call to change the aspect ratios of the axes. (Assigning them as [1 1 1] is the same as axis('equal').)
EDIT — (23 Aug 2024 at 12:01)
Changed explicit loop to accumarray call to produce ‘L’.
.
Jorge
2024년 8월 23일
this is great, and i agree that the unsquished version is probably the most informative version. Thank you.
however, i still don't really understand how you are getting these plots. the collected data is arranged into matrix and is all unique. the first three columns are x, y ,z coordinates, and the last column has the measurement value at each fof those coordinates. there are no duplicate rows; each row is a new coordinate and measurement.
for example, row 1 has the 3D position in space as located by the first three columns of the matrix, (x,y,z), respectively, and the magnetic field strength measured at that location is stored in the fourth column. the scatter plot is showing this correctly, but I'm not sure if the surf plot is converying the same info- because i dont really understand how it is set up. I'm gonna try to follow how/why you did what you did. Thank you!
Star Strider
2024년 8월 23일
편집: Star Strider
2024년 8월 23일
I don’t understand what the problem is. After looking at the scatter3 plot, it was obvious that there are five discrete layers in the data, so I used accumarray to separate the data into each ‘L’ layer:
[Uz,ixs,ixv] = unique(z);
L = accumarray(ixv, (1:numel(ixv)).', [], @(v) {[x(v) y(v) z(v) c(v)]})
with ‘Lv’ being a logical vector, and then did the same interpolation and surf plot with each ‘L’ matrix and then plotted them together using hold. That’s all there is to it.
EDIT — (23 Aug 2024 at 12:03)
Updated text to include the accumarray call.
if you have the time to explain it to me, let me try to break it down so you can understand what I don't understand. If you want to move on, that's fine too, no worries.
1) why do you need to do unique z, when every row in the matrix is 'unique"?
2) wht is this exactly doing:
Zfcn = scatteredInterpolant(x, y, z, 'natural','none');
why do we need to interpolate the z values when I have them --they are fixed coordinates?
3) In my mind, I figured all we had to do was somehow create a 3d grid or mesh, and then map the value on column for to the respective location in the grid.
For example, if I had only a 2D data (x,y, value).
I could use meshgrid to create the cartesian grid, and then I would have to figure out how to map each value v to its respectdive (x,y) coordinate. Perhaps that is the crux of the thing....I don't understand how what you did does that (in this case in 3D, but I don't understand it for the 2D case either).
I'm going to continue playing with what you did above until I figure it out.
thank you.
Star Strider
2024년 8월 23일
The values may be ‘unique’ in some sense, however the matrix itself is scattered. You can see that by displaying it. That is the first thing I did, because if it was truly gridded, I would have only needed to use the reshape function to create matrices from the various vectors, once I got them separated by rows according to the ‘z’ values. (That would also have required the unique funciton in order to determine the rows at which ‘z’ changed value.)
The unique call is used to provide a vector ‘ixv’ that returns the positions of every row corresponding to specific values of ‘z’ (since it defines the layers), and sorts them (although the sorting is not specifically necessary and can be suppressed by using the 'stable' argument to unique). My code then uses that vector to separate out the corresponding values of the original matrix into five equal-size cell arrays corresponding to each specific ‘z’ value, using accumarray to do this. (The accumarray function is more efficient than the loop I used originally, so I replaced it.) The cell arrays do not have to be the same size, however they are in these data.
It is necessary to interpolate the ‘z’ values in order to create the surfaces. The scattteredInterpolant function creates the interpolation function ‘Zfcn’ that then uses the ‘Xm’ and ‘Ym’ matrices created from the ‘xv’ and ‘yv’ vectors to interpolate the surface that then exists as ‘Zm’ (the surface values) and ‘Cm’ (the surface colours). Interpolating to a finer grid (the result of the ndgrid call) produces more detail.
If you only have a 2D data, you cannot create a surface from it, since it lacks the third dimension. The data already have to exist in 3D in order to create a surface plot. With 2D data, you can createa line plot and then interpolate it as a line in 2D in order to add more data points and perhaps smooth it a bit (using 'pchip', 'spline' or 'makima' interpolation methods), however that is all you can do.
See the documentation for the various functions for details.
Jorge
2024년 8월 23일
thanks for taking the time to explain!
Star Strider
2024년 8월 23일
As always, my pleasure!
The purpose of MATLAB answers is to provide solutions, as well as education in various contexts.
추가 답변 (1개)
Here is one way where you use colors to indicate the magnitude;
% random data
x = [0:pi/50:10*pi nan]; % nan is added to remove connection between first and last data point
y = sin(x);
z = cos(x);
m = x; % magnitude you want as colors, i set it to x cause it looks nice :D
colormap(winter)
patch(x,y,z,m,'Facecolor','none','EdgeColor','interp')
colorbar
view(3)

댓글 수: 2
Jorge
2024년 8월 22일
Thank you for you input. That does give me something I can use, but I'm left wondering if there is yet a better way to display the data. Here's a sample of data I collected in the lab. The data has the coordinates of the x,y,z fixture, and the values measured. The format is [x,y,z,value]. if you think of a better, please let me know. I appreciate the help. Thank you.
Here is similar scatter3 way with your code:
load('data.mat')
x = data(:,1);
y = data(:,2);
z = data(:,3);
m = data(:,4);
scatter3(x,y,z,100,m,'filled')
colorbar
view(-15,10)

카테고리
도움말 센터 및 File Exchange에서 Labels and Annotations에 대해 자세히 알아보기
참고 항목
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!웹사이트 선택
번역된 콘텐츠를 보고 지역별 이벤트와 혜택을 살펴보려면 웹사이트를 선택하십시오. 현재 계신 지역에 따라 다음 웹사이트를 권장합니다:
또한 다음 목록에서 웹사이트를 선택하실 수도 있습니다.
사이트 성능 최적화 방법
최고의 사이트 성능을 위해 중국 사이트(중국어 또는 영어)를 선택하십시오. 현재 계신 지역에서는 다른 국가의 MathWorks 사이트 방문이 최적화되지 않았습니다.
미주
- América Latina (Español)
- Canada (English)
- United States (English)
유럽
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
