How to plot z (data) on x-y (grid) from a structure?

Hi! I state that I'm a beginner on Matlab and this is just my second interaction on the community, so I apologize if my code seems stupid. It WORKS, but I have a problem regarding a plot. I have a structure (file.mat, attached) where 5 simulations of wave energy transport happen on a grid (195x336 cells). Every result is stored on a field, for a total of 5x195x336 data. Since each simulation occur for a certain time (array "CumHours"), I was able to multiply each of the 5 simulations for the proper time (for cycle). Then I summed all the result ("TOT") and divided by the sum of the hours, in order to get a weighted average of the energy transport on the grid.
clear all
close all
TotalData = load('Etransp_5steps.mat');
Dati=TotalData.data;
Values=Dati.Val %to see how the results are organized
plot(extractfield(Dati,'X'),extractfield(Dati,'Y')); %image of the grid
Extract=extractfield(Dati,'Val');
%%
CumHours=[0.3; 3.03; 14.56; 3.34; 0.3;]; %5 amount of hours for every simulation
sumCH=sum(CumHours(:));
s=1;
f=5;
for cont=1:f
NewVal(s,:,:)=Values(s,:,:)*CumHours(s,1);
s=1+s;
end
%%
j=1;
Cum=NewVal(j,:,:);
while j<f
j=j+1;
Cum=Cum+NewVal(j,:,:);
end
TOT=Cum;
ResultVal=TOT(1,:,:)/sumCH;
figure(1);
s=plot3(Dati.X(2:end,2:end),Dati.Y(2:end,2:end),squeeze(ResultVal(1,:,:)));
figure(2);
t=scatter3(Dati.X(2:end,2:end),Dati.Y(2:end,2:end),squeeze(ResultVal(1,:,:)));
The problem is on the plot; by previous suggestions I used plot3 to get the results, but what I would like to get is the grid, on which I plot "ResultVal" with a jet colormap. In order to get an idea, this is the goal
Targetimage.png
But of course, by using plot3, I get this, which is correct but not my idea.
Plot3_2.png
Can someone help me to understand what should I use? Maybe playing with the properties?
Thanks a lot.

 Réponse acceptée

I took a few liberties with your code since I do not have the Mapping Toolbox.
Try this:
TotalData = load('Etransp_5steps.mat');
X = TotalData.data.X;
Y = TotalData.data.Y;
Values = TotalData.data.Val;
%%
CumHours=[0.3; 3.03; 14.56; 3.34; 0.3;]; %5 amount of hours for every simulation
sumCH=sum(CumHours(:));
s=1;
f=5;
for cont=1:f
NewVal(s,:,:)=Values(s,:,:)*CumHours(s,1);
s=1+s;
end
%%
j=1;
Cum=NewVal(j,:,:);
while j<f
j=j+1;
Cum=Cum+NewVal(j,:,:);
end
TOT=Cum;
ResultVal=TOT(1,:,:)/sumCH;
figure(1);
s=plot3(X(2:end,2:end),Y(2:end,2:end),squeeze(ResultVal(1,:,:)));
figure(2);
hs = surf(X(2:end,2:end),Y(2:end,2:end),squeeze(ResultVal(1,:,:)))
grid on
hs.EdgeColor = 'none';
view(-20,40)
producing this figure(2):
Although this might be what you want:
figure(3)
[~,hc] = contourf(X(2:end,2:end),Y(2:end,2:end),squeeze(ResultVal(1,:,:)),50);
hc.LineStyle = 'none';
colormap(jet)
producing:
Experiment to get the result you want.

10 commentaires

Kelto7
Kelto7 le 29 Sep 2019
Modifié(e) : Kelto7 le 29 Sep 2019
Hi Star Strider, thank you so much for your anwer, much appreciated! I guess that there should be the chance to get a jet colormap also in the first case (maybe with colormap editor?). Otherwise the second result is good, but is it possible to let some space between the figure and the axes? (right now I'm trying with Figure Properties, to manually move the figure).
P.s. Ignore the first question, a simple colormap(jet) worked:)
As always, my pleasure!
With respect to figure(2), just add a colormap call:
figure(2);
hs = surf(X(2:end,2:end),Y(2:end,2:end),squeeze(ResultVal(1,:,:)))
grid on
colormap(jet)
hs.EdgeColor = 'none';
view(-20,40)
To get space between the plot and the axes, use the axis function, specifically Set Axis Limits.
For example (with figure(3)):
figure(3)
[~,hc] = contourf(X(2:end,2:end),Y(2:end,2:end),squeeze(ResultVal(1,:,:)),50);
hc.LineStyle = 'none';
colormap(jet)
axis([4.4E+5 4.7E+5 5.83E+6 5.86E+6])
Experiment to get the result you want.
Great, I didn't think about set the axis, it's the easiest way to do it, many thanks!!
I also noticed that X and Y have both one more line (196 and 337, respectively) that should not exist, since the grid has 195x336 cells ("Values" also has 5x195x336, which is right). I don't know if it's something due to Matlab when it imports the file.mat, the structure has to have an empty line in the fields, maybe? But I can't see why it shoud do just for X and Y and not for Values too.
By using:
figure(2);
hs = surf(X(1:end-1,1:end-1),Y(1:end-1,1:end-1),squeeze(ResultVal(1,:,:)))
I don't show the last lines of both, but it shouldn't be normal to have this extra line in both fields, right?
As always, my pleasure!
I also noticed the mismatch between the ‘X’ and ‘Y’ vectors and ‘Val’. I have no idea where that comes from, since I do not know how they were calculated. There are two ways to deal with it. One is to simply ignore one index value, and the other is to use interp1 to re-scale them. For example:
Xr = interp1((1:numel(X)), X, (1:195));
Yr = interp1((1:numel(Y)), Y, (1:336));
I have not tested these, although they should work. Make appropriate changes if necessary.
Hi Star Strider, thank you su much for your kindness!
I tried the second chance and although this message of error occurs:
Error using griddedInterpolant
The grid vectors do not define a grid of points that match the given values.
Error in interp1 (line 144)
F = griddedInterpolant(X,V(:,1),method);
I will try to play with it, because I didn't know the function interp1, so maybe it's a matter of ordering the right items in the correct way.
That will teach me to always test code I post!
Try this:
Xr = interp1((1:numel(X)), X, linspace(1,numel(X),numel(X)-1));
Yr = interp1((1:numel(Y)), Y, linspace(1,numel(Y),numel(Y)-1));
It has the advantage of preserving the entire range of both vectors, creating vectors that are one element less than the argument vectors.
Kelto7
Kelto7 le 30 Sep 2019
Ok, so here "interp1" considers the number of points (from 1 to numel(X)= 66052 = 196x337), whose values are contained in X (correct, because it is 196x337 cells) and assign them to a vector of 1----->66052 values, with spacing [numel(X)-1]/ ((numel(X)-1-1).
I get the same error message, and I don't know if I'm correct, but could the error be in the linespace? numel(X)-1 gives back 66052-1=66051, while my pont is to delete one cell, so from 196-1=195 (and same in Yr). I guess this just from your previous solution, I don't know if my guess has any sense, it is beyond my comprehension so far.
I had forgotten what ‘X’ and ‘Y’ were. I somehow thought they were vectors.
The interpolation idea is not going to work with your ‘X’ and ‘Y’ matrices. When I looked at them, I discovered that they are not linear, so any extrapolation scheme distorts the extrapolated matrices, and distorts the plots. It is likely best to just trim ‘X’ and ‘Y’ to fit ‘Values’, since for the same reason, it is not possible to interpolate ‘Values’ without distorting them.
Kelto7
Kelto7 le 1 Oct 2019
Ooh ok, now it is a little bit more clear. Yes, probably it's easier just to adjust X and Y to fit Values. Ok then, thank you so much for your help and time, much appreciated, I discovered commands that I had no idea about!
As always, my pleasure!
The interpolation approach would likely work except for the ususual structure of the ‘X’ and ‘Y’ matrices. This makes it essentially impossible to interpolate them, or to interpolate (extrapolate) the ‘Values’ array to fit them.

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Interpolation dans Centre d'aide et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by