Plot 3d surface plot in matlab/freemat - matlab

I would like to ask about 3d surface plotting. As I am new to it, I was just trying out. Basically, I have 3 parameters, x, y ,z which I have the values from experimental datas and I would like to plot them out. As such, i tried,
x= [6 7 8 9 10 11 12 1]
x =
6 7 8 9 10 11 12 1
--> y=[2 3 4 5 6 1 6 8]
y =
2 3 4 5 6 1 6 8
--> z= [3 4 5 6 7 8 9 10]
z =
3 4 5 6 7 8 9 10
meshgrid(x,y,z)
surf(x,y,z)
The plot window did come out but there was no graph. Is my method wrong?
Thanks!

It sounds like you need to start with plot3, as you're just describing a set of points in 3D, rather than points on a mesh or surface. See if that does what you want.
x = [6 7 8 9 10 11 12 1];
y = [2 3 4 5 6 1 6 8];
z = [3 4 5 6 7 8 9 10];
plot3(x, y, z, '.');

This is how I would plot a surface :
%define the data
x=[6 7 8 9 10 11 12 1 6 7 8 9 10 11 12 1];
y=[2 3 4 5 6 1 6 8 2 3 4 5 6 1 6 8];
z=[3 4 5 6 7 8 9 10 3 4 5 6 7 8 9 10];
%Create 3D surface
[X,Y]=meshgrid(x,y);
Z=griddata(x,y,z,X,Y);
%Plot the surface
surface(X,Y,Z);
shading interp %makes it look sexy
%xlim([])
%ylim([])
Sometimes I use axis limets to make the plot look nicer (eliminates the unneeded white area's); for this set of data I could use xlim([6 11]) and ylim([2 6]).

Related

How can I store a matrix in a row of another matrix? MATLAB

I have a 3D matrix and I want to store each 2D component of this in the row of another 2D matrix which has many rows as the 3rd dimension of the 3D matrix.
How can I do this?
With permute & reshape -
reshape(permute(A,[3 2 1]),size(A,3),[])
Sample run -
>> A
A(:,:,1) =
7 1 7 5
3 4 8 5
9 4 2 6
A(:,:,2) =
7 7 2 4
7 6 5 6
3 2 9 3
A(:,:,3) =
7 7 5 3
3 9 2 8
5 9 2 3
>> reshape(permute(A,[3 2 1]),size(A,3),[])
ans =
7 1 7 5 3 4 8 5 9 4 2 6
7 7 2 4 7 6 5 6 3 2 9 3
7 7 5 3 3 9 2 8 5 9 2 3
If you don't mind a little indexing madness...
You can build a linear index with the appropriate shape, which applied on the original array will give the desired result:
B = A(bsxfun(#plus, (1:L*M:L*M*N).', reshape(bsxfun(#plus, (0:L:L*M-1).', 0:L-1),1,[])));
Example:
>> A = randi(10,2,3,4)-1; %// example array; size 2x3x4
>> A
A(:,:,1) =
5 3 2
9 8 9
A(:,:,2) =
8 7 4
9 8 6
A(:,:,3) =
3 4 8
0 4 4
A(:,:,4) =
2 8 8
4 6 7
Result:
>> B
B =
5 3 2 9 8 9
8 7 4 9 8 6
3 4 8 0 4 4
2 8 8 4 6 7
That is easily done with MATLABs matrix unrolling syntax:
A=ones(N,M,O);
B=zeros(O,N*M);
for ii=1:size(A,3)
aux=A(:,:,ii); % aux is NxM
B(ii,:)=aux(:); % unroll!
end
(note I called O the thing you call N in your pictures)

Reshape matrix from 3d to 2d keeping specific order

I would like to resize a matrix under the form let's say 4x3x5, to a 2d matrix of 20x3 but while preserving the order as illustrated below :
The function reshape() does not keep this particular order, how could I achieve this the simplest way possible ?
Let's solve these problems of concatenating and cutting across the third dimension once and for all!
Part I (3D to 2D) : Concatenate along the columns and across the 3rd dim of a 3D array, A to form a 2D array -
reshape(permute(A,[1 3 2]),[],size(A,2))
Part II (2D to 3D) : Cut a 2D array B after every N rows to form 3D slices of a 3D array -
permute(reshape(B,N,size(B,1)/N,[]),[1 3 2])
Sample run -
Part I (3D to 2D)
>> A
A(:,:,1) =
4 1 4 3
8 4 6 4
8 5 6 1
A(:,:,2) =
9 4 4 1
2 2 9 7
1 5 9 3
A(:,:,3) =
4 4 7 7
5 9 6 6
9 3 5 2
>> B = reshape(permute(A,[1 3 2]),[],size(A,2));
>> B
B =
4 1 4 3
8 4 6 4
8 5 6 1
9 4 4 1
2 2 9 7
1 5 9 3
4 4 7 7
5 9 6 6
9 3 5 2
Part II (2D to 3D)
>> N = 3;
>> permute(reshape(B,N,size(B,1)/N,[]),[1 3 2])
ans(:,:,1) =
4 1 4 3
8 4 6 4
8 5 6 1
ans(:,:,2) =
9 4 4 1
2 2 9 7
1 5 9 3
ans(:,:,3) =
4 4 7 7
5 9 6 6
9 3 5 2

Extend the borders of a matrix and replicate the border elements in MATLAB

I am given the following matrix B:
B =
1 4 7
2 5 8
3 6 9
I would like to pad this matrix so that there is a 1 element border that surrounds it with the border elements replicated. Essentially, I would like this result:
B =
1 1 4 7 7
1 1 4 7 7
2 2 5 8 8
3 3 6 9 9
3 3 6 9 9
How can I do this in MATLAB?
If you have the Image Processing Toolbox, use padarray, specifically the replicate flag. If you don't have it, there's an implementation that someone made here on Github: https://github.com/gpeyre/matlab-toolboxes/blob/master/toolbox_nlmeans/toolbox/ordfilt2/padarray.m . You can download it and use the function for your own use.
padarray creates a larger matrix with the source matrix centred within this larger matrix. You have several options on what you can do with the extra border elements. The default behaviour is to set these equal to 0. However, we can specify the replicate flag, which copies values along the original border of the matrix and places them along the extra border elements with this new matrix. Because you want to go from 3 x 3 to 5 x 5, you just need a 1 element border along both dimensions. You specify this with the second parameter to padarray. The replicate flag is the third parameter:
>> B = reshape(1:9, 3, 3);
>> B2 = padarray(B, [1 1], 'replicate')
B2 =
1 1 4 7 7
1 1 4 7 7
2 2 5 8 8
3 3 6 9 9
3 3 6 9 9
Edit
If you don't want to use padarray, you can use the scatteredInterpolant class instead, with nearest as the interpolation flag. You would build a 3 x 3 2D spatial grid of coordinates that map to each value in B, then we'd specify a 5 x 5 spatial grid of coordinates where the border elements are outside of the range of the original 3 x 3 grid. Something like this:
>> [X,Y] = meshgrid(1:3,1:3);
>> [X2,Y2] = meshgrid(0:4,0:4);
>> F = scatteredInterpolant(X(:),Y(:),B(:),'nearest');
>> B2 = F(X2, Y2)
B2 =
1 1 4 7 7
1 1 4 7 7
2 2 5 8 8
3 3 6 9 9
3 3 6 9 9
The question was explicitly to add a single element as border, so try this (no toolbox needed):
B = [1 4 7; 2 5 8; 3 6 9] % or use B=rand(3,4), etc. to try something else.
B2 = B([1 1:end end],[1 1:end end])
This is the result (as desired):
B =
1 4 7
2 5 8
3 6 9
B2 =
1 1 4 7 7
1 1 4 7 7
2 2 5 8 8
3 3 6 9 9
3 3 6 9 9

Quiver from a single matrix

I have a matrix (In Matlab) which I need to plot with a quiver plot but I don't know how to turn it into a "quiver plot-able form". Are there any commands to change it? I saw some example on MathWorks Homepage using the peaks function but I couldn't get it to work.
The matrix I have is pretty huge with lots of NaN's so I created an smaller version of it.
Temperature = [ 1 2 2 2 3 4 6 7 ;
1 2 3 4 4 5 6 7 ;
2 3 4 NaN NaN 6 8 9 ;
3 4 5 NaN NaN 7 8 9 ;
4 4 6 6 7 8 10 11;
4 5 7 7 8 9 11 12];
contour(Temperature)
%quiver(Temperature)
In the comments you find the example code from the documentation which I used. Besides knowing that the dimensions are ordered [Y,X,Z] to get a matching meshgrid it's mostly copy&paste
% figure
figure
% [X,Y] = meshgrid(-2:.2:2);
Temperature = [ 1 2 2 2 3 4 6 7 ;
1 2 3 4 4 5 6 7 ;
2 3 4 NaN NaN 6 8 9 ;
3 4 5 NaN NaN 7 8 9 ;
4 4 6 6 7 8 10 11;
4 5 7 7 8 9 11 12];
[X,Y] = meshgrid(1:size(Temperature,2),1:size(Temperature,1));
% Z = X.*exp(-X.^2 - Y.^2);
Z=Temperature;
% [DX,DY] = gradient(Z,.2,.2);
[DX,DY] = gradient(Z,1,1);
% contour(X,Y,Z)
contour(X,Y,Z)
% hold on
hold on
% quiver(X,Y,DX,DY)
quiverscaling=3;
quiver(X,Y,DX,DY,quiverscaling)
% colormap hsv
colormap hsv
% hold off
hold off

plot two histograms (using the same y-axis) and a line plot (using a different y-axis) on the same figure

How can I plot two histograms (using the same y-axis) and a line plot (using a different y-axis) on the same figure? I am using Matlab 2014b. I am aware of this but it seems to only work for bar plots?
This is my histogram code:
A = [1 2 2 2 3 4 5 5 5 5 5 5 5 5 5 6 6 6 7 7];
B = [6 6 6 7 7 7 7 7 7 7 8 8 8 9 9 10 10];
hist(A,7);
hold on
hist(B,7);
h = findobj(gca,'Type','patch');
set(h(1),'FaceColor','b','EdgeColor','b','facealpha',0.2)
set(h(2),'FaceColor','r','EdgeColor','r','facealpha',0.2)
xlabel('Day','fontsize',14)
ylabel('Frequency','fontsize',14)
xlim([1 10])
Now say I have these data:
Day = [1 2 3 4 5 6 7 8 9 10];
Prevalence = [3 2 4 8 5 6 7 8 9 5];
I want to plot these data (plot(Day,Prevalence)) using the right y-axis.
Thanks.
I think this workaround will do what you want.
Basically create a new axes at the same position than the one in which the histograms are plot, however set its color property to 'none' and the YAxisLocation to the right. You can then assign the new axes the properties you want.
Code:
clear
clc
%// ====================
%// Your code
A = [1 2 2 2 3 4 5 5 5 5 5 5 5 5 5 6 6 6 7 7];
B = [6 6 6 7 7 7 7 7 7 7 8 8 8 9 9 10 10];
hist(A,7);
hold on
hist(B,7);
h = findobj(gca,'Type','patch');
set(h(1),'FaceColor','b','EdgeColor','b','facealpha',0.2)
set(h(2),'FaceColor','r','EdgeColor','r','facealpha',0.2)
xlabel('Day','fontsize',14)
ylabel('Frequency','fontsize',14)
xlim([1 10])
%// ====================
Day = [1 2 3 4 5 6 7 8 9 10];
Prevalence = [3 2 4 8 5 6 7 8 9 5];
%// Get the current axes position to place the new one.
AxesPos = get(gca,'Position');
hold on
hax2 = axes('Position',AxesPos);
%// Plot the data
plot(Day,Prevalence,'--k','LineWidth',4,'Parent',hax2)
%// Set properties of the axes.
set(hax2,'Color','none','YAxisLocation','right','XTick',[],'XTickLabel','','YLim',[0 15])
ylabel('Prevalence','FontSize',16)
%// Rotate the label to correct orientation
LabelPos = get(get(hax2,'YLabel'),'Position');
set(get(hax2,'YLabel'),'Position',[LabelPos(1)+.2 LabelPos(2) LabelPos(3)],'Rotation',-90)
Output:
Note that it's far from perfect ...for example the left border of the first axes is not visible...that could be fixed by playing around with the position of the new axes. Hopefully it does the job for you!