Matlab. Storing 2D arrays within 3D arrays - arrays

I have defined the following 2D function,
Ngrid = 100;
h = 1/(Ngrid-1);
x = 0:h:1;
y = 0:h:1;
[x y] = meshgrid(x,y);
f = exp(-((1-x).^2)./0.45)
and I want to store this function within the 3D array "c",along the "T" dimension,
k = 0.001;
Tend = 1;
T = 0:k:Tend;
c = zeros(length(T),length(x),length(y));
What I have tried is,
c(1:end,:,:) = f;
but it does not work. ¿Any idea of how can I store the same function within this 3D array?
Thanks in advance.

The subscript dimension mismatch is because you are trying to squeeze 100 * 100 elements into a 1001 x 100 x 100 matrix.
You could do this assignment the following way:
c(1,:,:) = f;
c(2,:,:) = f;
...
c(1001,:,:) = f;
But you can accomplish the same thing using repmat
c = repmat(reshape(f, [1, size(f)]), [numel(T), 1 1]);
Or bsxfun
c = bsxfun(#plus, zeros(numel(T), 1), reshape(f, [1, size(f)]));

Related

Add Object to Array in Matlab

I'm new to matlab and I can't add an object to an array:
%g is a transfer function
h = bodeplot(g);
% class('h') prints 'resppack.bodeplot'
a = zeros(2,1);
a(1,1) = h;
% I get the error: Conversion to double from resppack.bodeplot is not possible.
This happens because my matrix 'a' is of type double while 'h' isn't.
How can I define an array of type 'resppack.bodeplot'?
resppack.bodeplot doesn't have an 'empty' method...
The problem here, i s that you create an array of doubles, and you want to store other things.
You can not initialize the array and start adding objects like this:
my-array(1) = something
my-array(2) = something-2
...
new-array(1) = h
new-array =
resppack.bodeplot
new-array(2) = h
new-array =
resppack.bodeplot: 1-by-2
new-array
new-array =
resppack.bodeplot: 1-by-2

Simple: How can I concatenate more elements of struct arrays in Matlab?

I have the following array k defined as a struct array of coordinates, i.e. k={{x1,y1},{x2,y2}}.
If I'd like to add one more coordinate to this struct array, what notation would I use? the pseudocode would be k=k+{x3,y3} and the result would be {{x1,y1},{x2,y2},{x3,y3}}. As a Python coder, I have trouble with the syntax of Matlab.
Thanks
Suppose that you have a structure that already contains a x and y coordinate and you have a master structure that contains your other coordinates, which is k in your case. Here's an example structure that contains two points where each structure has two fields: x and y:
k(1).x = 10;
k(1).y = 20;
k(2).x = 20;
k(2).y = 30;
If you have another point:
pt.x = 40;
pt.y = 50;
... to concatenate this point onto your structure k, it's simply:
k = [k pt];
This is the most common way to concatenate a structure to a larger list of structures.
As proof, let's look at the x and y coordinates before and after the concatenation:
>> xvals = [k.x]
xvals =
10 20
>> yvals = [k.y]
yvals =
20 30
>> pt.x = 40;
>> pt.y = 50;
>> k = [k pt];
>> xvals = [k.x]
xvals =
10 20 40
>> yvals = [k.y]
yvals =
20 30 50
With your notation you created an cell array containing cells. This is different to a struct in matlab. If you want to stick to cell arrays you can add a third by
k(end+1) = {x3,y3}
For structs in matlab #rayryeng just answered.

Combine 2D matrices to form 3D one in Matlab

I have 3 20x2 double arrays A, B and C. I want to combine them in one 3d array D so that D(:,:,1) will return A, D(:,:,2) will return B and D(:,:,3) will return C.
Using cat to concatenate along the third dimension might be the elegant way -
D = cat(3,A,B,C)
Here, the first input argument 3 specifies the dimension along which the concatenation is to be performed.
Like this?
A = 1*ones(20,2);
B = 2*ones(20,2);
C = 3*ones(20,2);
D = zeros(20,2,3); % Preallocate the D Matrix
D(:,:,1) = A;
D(:,:,2) = B;
D(:,:,3) = C;
D(1,1,1) % prints 1
D(1,1,2) % prints 2
D(1,1,3) % prints 3

Elegant way of creating an array full of one number in MATLAB?

I know that to get 10 0's, one can do
A = zeros(10, 1);
To get 10 1's, one can do
A = ones(10, 1);
What about any arbitrary number? Say, I want 10 3's. I have come up with a way of doing it.
A = linspace(3, 3, 10);
Is this satisfactory? Is there a more elegant way of doing this?
Some alternatives:
Using repmat:
A = repmat(3, [5 7]); %// 5x7 matrix filled with the value 3
Using indexing:
A(1:m, 1:n) = x;
Following is a timing comparison between all proposed approaches. As you can see, #Dennis' solutions are the fastest (at least on my system).
Functions:
function y = f1(x,m,n) %// Dennis' "ones"
y = x*ones(m,n);
function y = f2(x,m,n) %// Dennis' "zeros"
y = x+zeros(m,n);
function y = f3(x,m,n) %// Luis' "repmat"
y = repmat(x,[m n]);
function y = f4(x,m,n) %// Luis' "dirty"
y(m,n) = 0;
y(:) = x;
function y = f5(x,m,n) %// Luis' "indexing"
y(1:m,1:n) = x;
function y = f6(x,m,n) %// Divakar's "matrix porod"
y = x*ones(m,1)*ones(1,n);
Benchmarking script for square arrays:
x = 3;
sizes = round(logspace(1,3.7,10)); %// max limited by computer memory
for s = 1:numel(sizes)
n = sizes(s);
m = sizes(s);
time_f1(s) = timeit(#() f1(x,m,n));
time_f2(s) = timeit(#() f2(x,m,n));
time_f3(s) = timeit(#() f3(x,m,n));
time_f4(s) = timeit(#() f4(x,m,n));
time_f5(s) = timeit(#() f5(x,m,n));
time_f6(s) = timeit(#() f6(x,m,n));
end
loglog(sizes, time_f1, 'r.-');
hold on
loglog(sizes, time_f2, 'g.:');
loglog(sizes, time_f3, 'b.-');
loglog(sizes, time_f4, 'm.-');
loglog(sizes, time_f5, 'c.:');
loglog(sizes, time_f6, 'k.:');
xlabel('Array size')
ylabel('Time')
legend('ones', 'zeros', 'repmat', 'dirty', 'indexing', 'matrix prod')
For column arrays: just change the following lines:
sizes = round(logspace(1,3.7,10)).^2; %// max limited by computer memory
n = 1;
m = sizes(s);
For row arrays:
sizes = round(logspace(1,3.7,10)).^2; %// max limited by computer memory
n = sizes(s);
m = 1;
Results for a dual-core CPU, 2-GB RAM, Windows Vista, Matlab R2010b:
Square arrays;
Column arrays;
Row arrays.
There are two basic ways to do this:
A = ones(10,1)*3
B = zeros(10,1)+3
The first one is most commonly used in examples, yet if I am not mistaken, the second one performs slightly better. All in all it is just a matter of taste.
Of course, if you have an existing matrix, there is another simple way:
C = zeros(10,1)
C(:) = 3;
And for completeness, the repmat solution as suggested by #Luis is also fine.
As an alternative, a matrix multiplication (which is supposed to be pretty fast on MATLAB) based method could be also be suggested for 2D or multidimensional array assignment work.
Thus, assuming m as rows, n as columns and x as the value to be assigned for all elements, the code would be -
y = x*ones(m,1)*ones(1,n);

Interpolating trajectory from unsorted array of 2D points where order matters

I need a way of obtaining a Lx2 trajectory from a Nx2 array of points, i.e. a way of connecting those points into a single trajectory (for example, create a 10000x2 array of points from a 5x2 array of points). I have tried using interp1 and interp2 but either I don't fully understand them or they don't do what I need.
It sounds like you need to be using interp1 in a loop (i.e. to preserve original order) interpolating between each consecutive pair of points:
X = [10; 10.0001; 9; 48]; %// You can consider something like X = [10;10;9;48]; X=X+rand(size(X))*0.0001 instead of dealing with equal X values manually
Y = [10; 20; 50; 6];
m = 3333; %//num points between nodes
n = m*(length(X)-1);
Yi = zeros(n,1);
Xi = [];
for k = 1:length(X)-1
xi = linspace(X(k), X(k+1), m);
Xi = [Xi, xi];
Yi(((k-1)*m+1):k*m) = interp1(X(k:k+1), Y(k:k+1),xi);
end
plot(X,Y,'or');
hold on
plot(Xi,Yi);
To get a pentagon (not a W) try this looping code with these inputs:
X = [0.25; 0.75; 1; 0.5; 0; 0.25];
Y = [0; 0; 1; 1.8; 1; 0];
Result:

Resources