Read 3 1xN arrays into a 3xN matrix in matlab - arrays

I have 3 arrays in matlab that are 1xN, X Y Z respectively. I need to read these arrays into a 3xN matrix respectively so I get
x1 y1 z1
x2 y2 z2
.. .. ..
xn yn zn
I have currently got the data in a Nx 3 matrix, the wrong way round. The code I have is
X = [];
Y = [];
Z = [];
for ctr = 1:length(A)
X = [X A(ctr,1)];
Y = [Y A(ctr,2)];
Z = [Z A(ctr,3)];
end
M = [X;Y;Z];
Where A is the input data from a 624*600 double cell and M is my desired matrix.
Thanks

I guess you want that:
X = [];
Y = [];
Z = [];
for ctr = 1:length(A)
X(end+1, 1) = A(ctr,1);
Y(end+1, 1) = A(ctr,2);
Z(end+1, 1) = A(ctr,3);
end
M = [X Y Z];
Faster with 1 line code:
M = [A(:, 1) A(:, 2) A(:, 3)];

I just found that you can transpose with Mt = transpose(M); which has the overall intended result but feels like 3 rights to make a left.

Related

how to solve y = |Sin(x^x)/2^(((x^x)-pi/2)/pi)| in MATLAB

how to solve this question in MATLAB?
Create an array for x from 0 to 2π with 1000 elements and graph the following equation:
y = |Sin(x^x)/2^(((x^x)-pi/2)/pi)|
I have tried but it didn't work:
x = linspace(0, 2*pi, 1000);
y = abs(sin(x.^x)/(2.^(((x.^x) - pi / 2)/ pi)));
plot(x,y)

Find the first and last index of each coordinate in a list of coordinates using MATLAB

I have a list of coordinates (x,y) and I need to find the index of the first and last occurrence of each coordinate in the list.
Example (in my use-cast I have ~30M coordinates):
x = [1 3 7 1 3];
y = [5 1 6 5 1];
first = [1 2 3 1 2];
last = [4 5 3 4 5];
I implemented it using a Matrix and a loop, it looks like this, but it is slow:
x1 = min(x);
y1 = min(y);
x2 = max(x);
y2 = max(y);
tic
Mlast = zeros(y2-y1+1, x2-x1+1);
Mfirst = Mlast;
ind = sub2ind(size(Mlast),y-y1+1, x-x1+1);
for i1=1:length(ind)
first = Mfirst(ind(i1));
if first == 0
first = i1;
end
Mlast(ind(i1)) = i1;
Mfirst(ind(i1)) = first;
end
I tried to vectorize the whole process, but I only succeed with Mlast:
ind = sub2ind(size(Mlast),y-y1+1, x-x1+1);
t = (1:length(x))';
Mlast(ind) = t;
Mfirst = ???
Is there a way to get this for the first occurrence as well?
The unique function can do that:
[~, b, c] = unique([x(:) y(:)], 'rows', 'first');
first = b(c).';
[~, b, c] = unique([x(:) y(:)], 'rows', 'last');
last = b(c).';
Assuming that coordinates are positive integers and specially when the range of coordinates is small you can use accumarray:
x1 = min(x);
y1 = min(y);
x2 = max(x);
y2 = max(y);
sz = [y2-y1+1, x2-x1+1];
ind = sub2ind(sz,y-y1+1, x-x1+1);
ifirst = accumarray(ind(:), 1:numel(ind), [], #min);
ilast = accumarray(ind(:), 1:numel(ind), [], #max);
Mfirst = ifirst(ind);
Mlast = ilast(ind);
For higher ranges you can use the sparse option:
ifirst = accumarray(ind(:), 1:numel(ind), [], #min,[],1);
ilast = accumarray(ind(:), 1:numel(ind), [], #max,[],1);
If you've got 30M points then you likely don't have enough memory for this method... but it's pretty quick for smaller arrays
x = [1 3 7 1 3];
y = [5 1 6 5 1];
xy = cat( 3, x, y );
chk = all( xy == permute( xy, [2 1 3] ), 3 );
[~,first] = max( chk );
[~,last] = max( flipud( chk ) );
last = size(chk,1) - last + 1;
Edit You can also do this with findgroups, and looping over the unique coordinates instead of each coordinate to have a potentially much shorter loop...
x = [1 3 7 1 3];
y = [5 1 6 5 1];
g = findgroups( x, y );
first = zeros( size( x ) );
last = first;
for ii = 1:max(g)
idx = (ii==g);
first( idx ) = find( idx, 1, 'first' );
last( idx ) = find( idx, 1, 'last' );
end
Edit2 I think these are both pretty slow relative to other answers here...

MATLAB two different arrays for the same variable

So, I got a strange problem.
Below is my code, it is a simple Euler method for integrating a Linear system of ODE's.
function [V, h, n, b, z] = hodgkin_huxley_CA1(t, Iapp, t_app)
%function based on the CA1 pyramidal neuron model:
h = zeros(length(t));
n = zeros(length(t));
b = zeros(length(t));
z = zeros(length(t));
V = zeros(length(t));
% Initial conditions
h(1) = 0.9771;
n(1) = 0.0259;
b(1) = 0.1787;
z(1) = 8.0222e-04;
V(1) = -71.2856;
% Euler method
delta_t = t(2) - t(1);
for i=1:(length(t)-1)
h(i+1) = h(i) + delta_t*feval(#h_prime,V(i),h(i));
n(i+1) = n(i) + delta_t*feval(#n_prime,V(i),n(i));
b(i+1) = b(i) + delta_t*feval(#b_prime,V(i),b(i));
z(i+1) = z(i) + delta_t*feval(#z_prime,V(i),z(i));
minf = m_inf(V(i));
pinf = p_inf(V(i));
ainf = a_inf(V(i));
if (t(i) >= t_app(1) && t(i) <= t_app(2))
I = Iapp;
else I = 0;
end;
V(i+1) = V(i) + delta_t*feval(#V_prime,V(i),h(i),n(i),b(i),z(i),minf,pinf,ainf,I);
end;
So, this function returns me 5 arrays, V,h,n,b and z. The problem is that if I use V(1), V(2), V(3), ..., I get the expected result. But when I tell matlab to print the whole array, I receive all values as 0.
So, if I plot this array, I will get 2 curves: one that is the right one, and one that is zero.
Note that this also happens to all the other variables h,n,b and z.
Anyone knows what may be happening?
Your outputs are meant to be vectors, however you are initializing them as square matrices.
You can simply replace:
h = zeros(length(t));
n = zeros(length(t));
b = zeros(length(t));
z = zeros(length(t));
V = zeros(length(t));
With
h = zeros(length(t),1);
n = zeros(length(t),1);
b = zeros(length(t),1);
z = zeros(length(t),1);
V = zeros(length(t),1);
The zeros function, with 1 input, creates a 2D square matrix of that dimension. With two or more inputs, it interprets the inputs as specification for all dimensions. For example:
>> x = zeros(3)
x =
0 0 0
0 0 0
0 0 0
>> x = zeros(3,1)
x =
0
0
0

Finding the best way to define a function of dot product for a 3D grid

I am trying to build the following function in a three dimensional domain.
where is a constant vector, is the position vector, is a constant, and is time.
is a vector of size [1 3], is the array of size [NX*NY*NZ 3] that represents the points in the three-dimensional domain, is constant, and is array of size [1 NT].
The following is the setup of the problem.
dx = 0.1;
dy = 0.5;
dz = 0.1;
[x, y, z] = meshgrid( (1:100)*dx, (1:100)*dy, (1:100)*dz );
X = [x(:) y(:) z(:)];
k = [1 2 3];
c = 0.5;
t = 0:0.1:1;
In fact, the following loop works but it is very slow (~200 seconds).
f = zeros(numel(X)/3, numel(t));
for n = 1:numel(t)
for i = 1:numel(X)/3
f(i, n) = tan(dot(k, X(i,:)+c*t(n)));
end
end
I thought about using arrayfun and repeating the vector k using repmat and dot it with X in the second dimension but I don't know what I should do for the multiplication of c and t.
What would be an efficient way of defining the function for all the points and all the times? The output of this function, for example, looks like an array of size [NX*NY*NZ NT].
bsxfun approach to speedup f calculation -
t1 = bsxfun(#plus,X,permute(c*t,[1 3 2]));
t2 = permute(k(ones(numel(t),1),:),[3 2 1]);
t3 = bsxfun(#times,t1,t2);
f = tan(squeeze(sum(t3,2)));
Or a slight variant -
t1 = bsxfun(#plus,X,permute(c*t,[1 3 2]));
t3 = bsxfun(#times,t1,k);
f = tan(squeeze(sum(t3,2)));
f = tan(sum(bsxfun(#times, permute(k, [1 3 2]), bsxfun(#plus, permute(X, [1 3 2]), c*t)), 3));
Or replace the outer bsxfun by matrix multiplication. This seems to be slightly faster:
f = tan(reshape(reshape(bsxfun(#plus, permute(X, [1 3 2]), c*t), [], 3) * k(:), [size(X,1) numel(t)]));

How to plot specific points in matlab?

I've X axis with values [2,6,10] and for Y axis [0.5,0.4,0.2,0.2,....0.5], all values between 0 and 1.
There are certain points which correspond to 2, let's say 1/3rd and the remaining 1/3rd for 6 and remaining 1/3rd for 10. The points corresponding to 2 can have any values between 0 and 1, same applies for point 6 and point 10.
How can I plot this?
I guess you have some way to match up each Y-value to its corresponding X-value. By generating a vector of the same length as Y with these X-values they can then be plotted against each other.
The two vectors will then have the following form:
X = [2,6,2,10,6,6,10,2,....6]
Y = [0.5,0.4,0.2,0.2,0.9,0.3....0.5]
Here is a sample code
% X-data
X = [2,6,10];
% Generate random Y-data
n1 = 10;
n2 = 20;
n3 = 30;
n = n1 + n2 + n3;
Y = rand(1,n);
% Match X indices corresponding to Y
% Xall = [2,2,2,...,2,6,6,6,...,6,10,10,10,...,10]
X1 = zeros(1,n1);
X1(:) = X(1);
X2 = zeros(1,n2);
X2(:) = X(2);
X3 = zeros(1,n3);
X3(:) = X(3);
Xall = [X1 X2 X3];
plot(Xall,Y,'o')
xlim([min(X)-2,max(X)+2])
which will generate a figure of the following form
plot(a(1:3:end))
This will plot every third point.
a=[0.5,0.4,0.2,0.2,....0.5]
b=[1:3:length(a)]
plot(a(b))

Resources