How do I create a plot like this grid in MATLAB? - matlab

I have data like this
-1 -1 -1 1 0 0 1 1 -1 0 1 -1 0 1
where each element of the vector is one of a several states. In this case (which is arbitrary and obviously only an example), are -1 0 1. I'm trying to make a plot like this grid:
The closest I was able to get was with a combination of spy and various tweaks:
%% ARBITRARY example data
states = [-1 0 1];
data = [-1 -1 -1 1 0 0 1 1 -1 0 1 -1 0 1];
%% Approximate plot using sparse matrix and spy
T = size(data, 2);
num_states = size(states, 2);
g = zeros(num_states, T);
for idx = 1:T
jdx = find(data(idx) == states, 1, 'first');
g(jdx, idx) = 1;
end
g = sparse(g);
%% Tweak plot
obj = figure();
obj.Color = 'white';
spy(g, 30)
s = obj.Children(1);
s.XLim = [1 T];
s.YLim = [1 num_states];
s.XLabel.String = '';
s.XGrid = 'on';
s.YTick = 1:num_states;
s.YTickLabel = num2cell(states);
s.GridLineStyle = '-';
s.YGrid = 'on';
However, this is far from ideal, since a) it's not actually a shaded grid, and b) the ticks on the y-axis are in descending order, starting from the bottom, because this is how spy functions, among other problems. How do I make a plot like this? I'm using MATLAB 2015b on a Windows 7 64-bit machine.

You'll want to play around with colours and grids, but this should be sufficient to get started:
data = [-1 -1 -1 1 0 0 1 1 -1 0 1 -1 0 1];
states = flipud(unique(data)');
im = bsxfun(#eq,data,states);
image(im);
colormap([1 1 1;0 0 0]);
axis equal;
axis tight;
set(gca,'XTick',1:length(data));
grid minor
set(gca,'YTickLabel',states);
The above results in

Related

MATLAB - Update Plot with Matrix

I want to plot data, which is stored in an array. A contains three columns, each column represents a different data set. The following code works fine:
A = [0 0 0;
0 1 0];
h = plot(A)
However, a new line is appended to A and the plot shall be updated. I read that you can update plots with set and 'XData':
A = [0 0 0;
0 1 0;
1 2 0];
set(h,'XData',A)
This throws me an error: Error using set.
Value must be a column or row vector. Is there any way to refresh the data instead of a new plot? The following works just fine?
A = [0 0 0;
0 1 0;
1 2 0];
h = plot(A)
The initial code
A = [0 0 0;
0 1 0];
h = plot(A)
generates three line objects, one for each column of A (check that h has size 3×1). So you need to update each of those lines in a loop. Also, you need to update both the 'XData' and 'YData' properties:
for k = 1:numel(h)
set(h(k), 'XData', 1:size(A,1), 'YData', A(:,k))
end
You could use linkdata (https://mathworks.com/help/matlab/ref/linkdata.html):
A = [
0 0 0;
0 1 0
];
plot(A);
linkdata on;
A = [
0 0 0;
0 1 0;
1 2 0
];
Another approach deleting the plot and redrawing it immediately after:
h = plot(x,y);
% modify data...
delete(h);
h = plot(x,y);

Quick Assembly of sparse matrix

I have indices
I = [nGrid x 9] matrix % mesh on fine grid (9 point rectangle)
J = [nGrid x 4] matrix % mesh on coarse grid (4 point rectangle)
Here, nGrid is large number depending on the mesh (e.g. 1.e05)
Then I want to do like
R_ref = [4 x 9] matrix % reference restriction matrix from fine to coarse
P_ref = [9 x 4] matrix % reference prolongation matrix from coarse to fine
R = sparse(size) % n_Coarse x n_Fine
P = sparse(size) % n_Fine x n_Coarse
for k = 1 : nGrid % number of elements on coarse grid
R(I(k,:),J(k,:)) = R_ref;
P(J(k,:),I(k,:)) = P_ref;
end
size is predetermined number.
Note that even if there is same index in (I,J), I do not want to accumulate. I just want to put stencils Rref and Pref at each indices respectively.
I know that this is very slow due to the data structure of sparse.
Usually, I use
sparse(row,col,entry,n_row,n_col)
I can use this by manipulate I, J, R_ref, P_ref by bsxfun and repmat.
However, this cannot be done because of the accumulation of sparse function
(if there exists (i,j) such that [row(i),col(i)]==[row(j),col(j)], then R(row(i),row(j)) = entry(i)+entry(j))
Is there any suggestion for this kind of assembly procedure?
Sample code
%% INPUTS
% N and M could be much larger
N = 2^5+1; % number of fine grid in x direction
M = 2^5+1; % number of fine grid in y direction
% [nOx * nOy] == nGrid
nOx = floor((M)/2)+1; % number of coarse grid on x direction
nOy = floor((N)/2)+1; % number of coarse grid on y direction
Rref = [4 4 -1 4 -2 0 -1 0 0
-1 -1 -2 4 4 4 -1 4 4
-1 -1 4 -2 4 -2 4 4 -1
0 4 4 0 0 4 -1 -2 -1]/8;
Pref = [2 1 0 1 0 0 0 0 0
0 0 0 1 1 1 0 1 2
0 0 1 0 1 0 2 1 0
0 2 1 0 0 1 0 0 0]'/2;
%% INDEX GENERATION
tri_ref = reshape(bsxfun(#plus,[0,1,2]',[0,N,2*N]),[],1)';
TRI_ref = reshape(bsxfun(#plus,[0,1]',[0,nOy]),[],1)';
I = reshape(bsxfun(#plus,(1:2:N-2)',0:2*N:(M-2)*N),[],1);
J = reshape(bsxfun(#plus,(1:nOy-1)',0:nOy:(nOx-2)*nOy),[],1);
I = bsxfun(#plus,I,tri_ref);
J = bsxfun(#plus,J,TRI_ref);
%% THIS PART IS WHAT I WANT TO CHANGE
R = sparse(nOx*nOy,N*M);
P = R';
for k = 1 : size(I,1)
R(J(k,:),I(k,:)) = Rref;
P(I(k,:),J(k,:)) = Pref;
end

Why does my 3 axes system coordinate orientation change x with y values?

I am using Matlab and Euler Angles in order to reorient a 3axes coordinate system. Specifically,
Rz = [cos(ψ) sin(ψ) 0;-sin(ψ) cos(ψ) 0;0 0 1];
Ry = [cos(φ) 0 -sin(φ);0 1 0;sin(φ) 0 cos(φ)];
Rx = [1 0 0;0 cos(θ) -sin(θ);0 sin(θ) cos(θ)];
Rtotal = Rz*Ry*Rz
Then I loop through my old system coordinates (x,y,z) and make a vector coord_old. Then I get the reoriented system with (xn,yn,zn)
for i=1:size(num,1)
coord_old = [x(i,1);y(i,1);z(i,1)];
coord_new = Rtotal*coord_old;
xn(i,1) = coord_new(1,1);
yn(i,1) = coord_new(2,1);
zn(i,1) = coord_new(3,1);
end
My issue is that when θ,φ,ψ≃0 then x->-y and y->x and when θ,φ≃0 and ψ=90 then x and y will not rotate! That means that when x,y should rotate they don't and when they shouldn't rotate they stay as they were!
--EDIT--
For example, when ψ=20.0871, φ=0.0580 and θ=0.0088 I get these results
See that x->-y and y->x while z doesn't change at all!
Any thoughts?
Ok, I see two main problems here:
Rtotal = Rz*Ry*Rz is probably not what you want since Rz is multiplied twice. I think you mean Rtotal = Rz*Ry*Rx.
Your rotation matrix seems to be incorrect. Check this Wikipedia artice to get the correct signs.
Here a corrected rotation matrix:
Rz = [cos(psi) -sin(psi) 0; sin(psi) cos(psi) 0; 0 0 1];
Ry = [cos(phi) 0 sin(phi); 0 1 0; -sin(phi) 0 cos(phi)];
Rx = [1 0 0; 0 cos(theta) -sin(theta); 0 sin(theta) cos(theta)];
Rtotal = Rz*Ry*Rx;
With this matrix I get the correct results:
x=1; y=2; z=3;
psi=0; phi=0; theta=0;
[xn,yn,zn] >> 1 2 3
x=1; y=2; z=3;
psi=90/180*pi; phi=0; theta=0;
[xn,yn,zn] >> -2 1 3
And here a full graphical example of a cube in 3d-space:
% Create cube (not in origin)
DVert = [0 0 0; 0 1 0; 1 1 0; 1 0 0 ; ...
0 0 1; 0 1 1; 1 1 1; 1 0 1];
DSide = [1 2 3 4; 2 6 7 3; 4 3 7 8; ...
1 5 8 4; 1 2 6 5; 5 6 7 8];
DCol = [0 0 1; 0 0.33 1; 0 0.66 1; ...
0 1 0.33; 0 1 0.66; 0 1 1];
% Rotation angles
psi = 20 /180*pi; % Z
phi = 45 /180*pi; % Y
theta = 0 /180*pi; % X
% Rotation matrix
Rz = [cos(psi) -sin(psi) 0; sin(psi) cos(psi) 0; 0 0 1];
Ry = [cos(phi) 0 sin(phi); 0 1 0; -sin(phi) 0 cos(phi)];
Rx = [1 0 0; 0 cos(theta) -sin(theta); 0 sin(theta) cos(theta)];
Rtotal = Rz*Ry*Rz;
% Apply rotation
DVertNew = Rtotal * DVert';
% Plot cubes
figure;
patch('Faces',DSide,'Vertices',DVert,'FaceColor','flat','FaceVertexCData',DCol);
patch('Faces',DSide,'Vertices',DVertNew','FaceColor','flat','FaceVertexCData',DCol);
% Customize view
grid on;
axis equal;
view(30,30);
When I use your code and insert 0 for all angles, I get Rtotal:
Rtotal =
1 0 0
0 1 0
0 0 1
This is the identity matrix and will not change your values.
You have an error in your matrix multiplication. I think you should multiply: Rtotal*coord_old. I think you are missing the _old. depending on what is in you coordvariable, this may be the bug.
When I run:
for i=1:size(1,1)
coord_old = [1;2;3];
coord_new = Rtotal*coord_old;
xn(i,1) = coord_new(1,1);
yn(i,1) = coord_new(2,1);
zn(i,1) = coord_new(3,1);
end
I get the correct result:
coord_new =
1
2
3
Thank you both #Steffen and #Matt. Unfortunately, my reputation is not high enough to vote Up your answers!
The problem was not with Rtotal as #Matt correctly stated. It should be as it was Rz*Ry*Rx. However, both your ideas helped me test my code with simple examples (5 sets of coordinates and right hand rule), and realize where my (amateur) mistake was.
I had forgotten I had erased parts of codes where I was expressing my angles to degrees... I should be using sind & cosd instead of sin and cos.

How to formulate this expression

I am new to MATLAB and I want to formulate the following lease square expression in Matlab. I have some codes that I am typing here. But the optimization problem solution seems not to be correct. Does anyone has an idea why?
First, I want to solve the heat equation
$$T_t(x,t) = - L_x . T(x,t) + F(x,t)$$
where L_x is Laplacian matrix of the graph.
then find y from the following least square.
$$ \min_y \sum_{j} \sum_{i} (\hat{T}_j(t_i) - T_j(t_i, y))^2$$
Thanks in advance!!
Here is my code:
%++++++++++++++++ main ++++++++++++++++++++
% incidence matrix for original graph
C_hat = [ 1 -1 0 0 0 0;...
0 1 -1 0 0 -1;...
0 0 0 0 -1 1;...
0 0 0 1 1 0;...
-1 0 1 -1 0 0];
% initial temperature for each vertex in original graph
T_hat_0 = [0 7 1 9 4];
[M_bar,n,m_bar,T_hat_heat,T_hat_temp] = simulate_temp(T_hat_0,C_hat);
C = [ 1 1 -1 -1 0 0 0 0 0 0;...
0 -1 0 0 1 -1 1 0 0 0;...
0 0 1 0 0 1 0 -1 -1 0;...
0 0 0 1 0 0 -1 0 1 -1;...
-1 0 0 0 -1 0 0 1 0 1];
%
% initial temperature for each vertex in original graph
T_0 = [0 7 1 9 4];
%
% initial temperature simulation
[l,n,m,T_heat,T_temp] = simulate_temp(T_0,C);
%
% bounds for variables
lb = zeros(m,1);
ub = ones(m,1);
%
% initial edge weights
w0 = ones(m,1);
% optimization problem
% w = fmincon(#fun, w0, [], [], [], [], lb, ub);
%++++++++++++++++++++ function++++++++++++++++++++++++++++
function [i,n,m,T_heat,T_temp] = simulate_temp(T,C)
%
% initial conditions
delta_t = 0.1;
M = 20; %% number of time steps
t = 1;
[n,m] = size(C);
I = eye(n);
L_w = C * C';
T_ini = T';
Temp = zeros(n,1);
% Computing Temperature
%
for i=1:M
K = 2*I + L_w * delta_t;
H = 2*I - L_w * delta_t;
%
if i == 1
T_heat = (K \ H) * T_ini;
%
t = t + delta_t;
else
T_heat = (K \ H) * Temp;
%
t = t + delta_t;
end
% replacing column of T_final with each node temperature in each
% iteration. It adds one column to the matrix in each step
T_temp(:,i) = T_heat;
%
Temp = T_heat;
end
end
%++++++++++++++++++ function+++++++++++++++++++++++++++++++++++++++++
function w_i = fun(w);
%
for r=1:n
for s=1:M_bar
w_i = (T_hat_temp(r,s) - T_temp(r,s)).^2;
end
end
To give a more clear answer, I need more information about what form you have the functions F_j and E_j in.
I've assumed that you feed each F_j a value, x_i, and get back a number. I've also assumed that you feed E_j a value x_i, and another value (or vector) y, and get back a value.
I've also assumed that by 'i' and 'j' you mean the indices of the columns and rows respectively, and that they're finite.
All I can suggest without knowing more info is to do this:
Pre-calculate the values of the functions F_j for each x_i, to give a matrix F - where element F(i,j) gives you the value F_j(x_i).
Do the same thing for E_j, giving a matrix E - where E(i,j) corresponds to E_j(x_i,y).
Perform (F-E).^2 to subtract each element of F and E, then square them element-wise.
Take sum( (F-E).^2**, 2)**. sum(M,2) will sum across index i of matrix M, returning a column vector.
Finally, take sum( sum( (F-E).^2, 2), 1) to sum across index j, the columns, this will finally give you a scalar.

Debugging 24 symmetric operators

I have written the following code to calculate the disorientation between two points in a large dataset using 24 crystal symmetry operators. The code seems to work fine though the end result is not right. I have a huge dataset containing the euler angles for each points. I find the misorientation between 1st point and 2nd point and then between 2 and 3rd and so on.
I want the end result to contain the corresponding misorientaion angles for each two data points. Following is the full code for your better understanding of my requirement.
LA=[phi1 phi phi2];
function gi=get_gi(pvec)
%pvec is a 1x3 vector of [phi1 phi phi2]
g_11=((cosd(pvec(1)).*cosd(pvec(3)))-(sind(pvec(1)).*sind(pvec(3)).*cosd(pvec(2))));
g_12=((sind(pvec(1)).*cosd(pvec(3)))+(cosd(pvec(1)).*sind(pvec(3)).*cosd(pvec(2))));
g_13= (sind(pvec(3)).*sind(pvec(2)));
g_21 =((-cosd(pvec(1)).*sind(pvec(3)))-(sind(pvec(1)).*cos(pvec(3)).*cos(pvec(2))));
g_22 = ((-sin(pvec(1)).*sind(pvec(3)))+(cosd(pvec(1)).*cosd(pvec(3)).*cosd(pvec(2))));
g_23 = (cosd(pvec(3)).*sind(pvec(2)));
g_31 = (sind(pvec(1)).* sind(pvec(2)));
g_32 = -cosd(pvec(1)).* sind(pvec(2));
g_33 = cosd(pvec(2));
gi =[g_11 g_12 g_13;g_21 g_22 g_23;g_31 g_32 g_33];
f = [1 1 1 -1 1 -1 -1 -1 1 1 -1 -1];
l= [1 1 1];
for i=1:3:10
l1= [f(i) 0 0;0 f(i+1) 0;0 0 f(i+2)];
l2= [0 f(i) 0;0 0 f(i+1);f(i+2) 0 0];
l3= [0 0 f(i);f(i+1) 0 0;0 f(i+2) 0];
l4= -[0 0 f(i);0 f(i+1) 0;f(i+2) 0 0];
l5= -[0 f(i) 0;f(i+1) 0 0;0 0 f(i+2)];
l6= -[f(i) 0 0;0 0 f(i+1);0 f(i+2) 0];
l=[l;l1;l2;l3;l4;l5;l6];
end
k=1;
t=1;
for m=1:(length(a)-1)
for i=2:3:71
for j=2:3:71
g_r= (get_gi(LA(m,:)*l(i:i+2,1:3))*(inv(get_gi(LA(m+1,:)))*inv(l(j:j+2,1:3))));
tr(k)= g_r(1,1) + g_r(2,2) +g_r(3,3);
angle(k) = real(acosd((tr(k)-1)/2));
k=k+1;
end
angle(angle==0)=360;
del_theta=min(angle)
del(t)=del_theta;
t=t+1;
end