How to pad cell-arrays in Matlab - matlab

Does someone know how to pad cell-arrays? For regular (multi-dimensional) arrays, I can use the function
A = padarray(A,dim,value)
However it won't accept cells...
Been searching but I can't find anything in the docs or google, thought I'd ask before trying to reprogram padarray() to accept cells... if someone knows how to do this, it would be much appreciated.

You can always use cellfun to apply a function to each cell in a cell array:
padize = 2;
A = cellfun( #(x) padarray(x,padsize), A ,'uni', 0);

I'm pretty sure regular Matlab has nothing for cell arrays just like it has nothing for numeric ones (padarray belongs to the Image Processing Toolbox). How difficult it is depends on how generic you need it - the basic symmetric empty-padded fixed-number-of-dimensions case is trivial:
function y = padcell2d(x, r)
y = cell(size(x) + r.*2);
y(r+1:end-r, r+1:end-r) = x;
end
Add complexity as required.
Since it was fun thinking of the simplest way to handle arbitrary dimensions, here's a really hacky way of n-dimensional symmetric empty padding without loops (tested on Octave):
function x = padcell(x, r)
if any(r>0) && ~any(r<0)
if isscalar(r) % otherwise, assume it's a value-per-dimension vector
r = repmat(r, 1, ndims(x));
end
sz = num2cell(size(x) + 2*r);
x{sz{:}} = []; % hooray for comma-separated lists!
x = circshift(x, r);
end
end

Related

Differentiation consistency in matlab

I'm trying to write a program in matlab that checks how consistent the definition of the derivative becomes:
(f(x+h)-f(x))/h ~= f'(x)
when h is small enough. Thus far i have this:
function [errList] = diffConsistency(f,df,x,iMax,h0)
h=h0;
for i=1:iMax
leftSide = (f(x+h) - f(x)) / h;
rightSide = df(x);
errList = abs(leftSide - rightSide);
h = h*10^(-1);
end
I then use f=#(x)sin(x) and df=#(x)cosx, I'm new to using function handles so this might be wrong completely. iMax is set to 10 and h0 = 1, x=rand(10)
Could anyone check if this is even remotely correct. Especially the use of the function handles inside the diffConsistency function and use of the rand.
Should i define x differently, leftside rightside are correct? etc
Any feedback would help.
Thanks in advance
You use some specific data that obscures the result. You input 10x10 random numbers, and output a 10x10 matrix of errors, but this is only for the last i, as you overwrite errList every iteration!
change the function to:
function [errList] = diffConsistency(f,df,x,iMax,h0)
h=h0;
for i=1:iMax
leftSide = (f(x+h) - f(x)) / h;
rightSide = df(x);
errList(i) = abs(leftSide - rightSide);
h = h*10^(-1);
end
and if you call it as :
err=diffConsistency(#sin,#cos,rand,10,1)
and plot(err), you can clearly see how the error gets reduced each smaller h.

Is there a builtin way to flip the i-th dimension of an nd-array?

Basically, I'm looking for a generalization of flipud and fliplr to flip the i-th dimension of an nd-array.
When the dimension to be flipped is the first one, I guess I can use
function flipped = flipfirst(ndarr)
sz = size(ndarr);
flipped = reshape(flipud(reshape(ndarr, sz(1), [])), sz);
end
Likewise, if the dimension to be flipped is the last one, I could use
function flipped = fliplast(ndarr)
sz = size(ndarr);
flipped = reshape(fliplr(reshape(ndarr, [], sz(end))), sz);
end
I'm sure that I can code something more general, with calls to permute and whatnot, but is there anything built-in for this?
I'm not sure how expensive it is to do all the reshape-ing above, but if it is, I'd also be interested in more efficient non-built-in approaches.
If you have R2013b+ you should use the new flip function:
A = rand(2,2,2);
B = flip(A,3);
For older versions you can use flipdim:
A = rand(2,2,2);
B = flipdim(A,3);
Type edit flipdim in your command window to see the clever code for flipdim.
You can also flip an array by using the time reversal property of the Discrete Fourier Transform. The code below works for any number of dimensions, but we demonstrate it with a 2D array because it's easier to examine the results.
A = magic(8);
d = 1; % dimension along which to flip
% Create frequency array w, we need it to go along dimension d
sz = size(A, d);
w = 2*pi * (0:sz-1) / sz;
w = shiftdim(w(:), 1-d);
% The actual time reversal property:
B = ifft( conj(fft(A, [], d)) .* exp(1j*w), [], d, 'symmetric');
(yes, this is overly complicated and ridiculously expensive compared to flip, but it's fun!)
From flipdim:
Flip array along specified dimension
Mostly for fun too...
This uses a comma-separated list generated from a cell array, together with the not very well known fact that you can use ':' as an index:
A = rand(3,4,5); % input array
dim = 2; % dimension to flip along
c = repmat({':'}, 1, ndims(A));
c{dim} = size(A, dim):-1:1;
B = A(c{:});

how to do this in a for loop in Matlab

I have a 3-dimensial matrix W of size 160x170x18 and I want to compute the difference
between each sucessive matrices inside W.
For example diff1 = W(:,:,1) - W(:,:,2) and diff2 = W(:,:,2) - W(:,:,3), etc ...
Next I want to select some special parts of the resulting matrices, For example:
NewDiff1 = [diff1(20:50,110:140); diff1(60:90,110:140)];
and the same thing for the other matrices.
finally I want to compute the mean of each matrix and the error as follow:
mean1 = mean(mean(NewDiff1));
er1 = 0.1-abs(mean1);
I succeeded to do this for each matrix alone, but prefer to do all at once in a for loop.
The expression
diff1 = diff(W,1,3)
will return, in your example, a 160*170*17 matrix where diffW(:,:,1) = W(:,:,2) - W(:,:,1), which isn't quite what you want. But
diff1 = (-1)*diff(W,1,3)
does, if my arithmetic is good, give you the differences you want. From there on you need something like:
newdiff1 = [diff1(20:50,110:140,:);diff1(60:90,110:140,:)];
and
means = mean(mean(newdiff1));
er1 = 0.1 - abs(mean1);
I haven't tested this thoroughly on matrices of the size you are working with, but it seems to work OK on smaller tests.
Store your matrices into a cell array and then just loop through the contents of the cell array and apply the same differencing logic to each thing. Be careful to use the {} syntax with a cell array to get its contents, rather than () which gives you the cell at a particular location.

Replace values in matrix with other values

I have a matrix with integers and I need to replace all appearances of 2 with -5. What is the most efficient way to do it? I made it the way below, but I am sure there is more elegant way.
a=[1,2,3;1,3,5;2,2,2]
ind_plain = find(a == 2)
[row_indx col_indx] = ind2sub(size(a), ind_plain)
for el_id=1:length(row_indx)
a(row_indx(el_id),col_indx(el_id)) = -5;
end
Instead of loop I I seek for something like: a(row_indx,col_indx) = -5, which does not work.
find is not needed in this case.
Use logical indexing instead:
a(a == 2) = -5
In case of searching whether a matrix is equal to inf you should use
a(isinf(a)) = -5
The general case is:
Mat(boolMask) = val
where Mat is your matrix, boolMask is another matrix of logical values, and val is the assignment value
Try this:
a(a==2) = -5;
The somewhat longer version would be
ind_plain = find(a == 2);
a(ind_plain) = -5;
In other words, you can index a matrix directly using linear indexes, no need to convert them using ind2sub -- very useful! But as demonstrated above, you can get even shorter if you index the matrix using a boolean matrix.
By the way, you should put semicolons after your statements if (as is usually the case) you're not interested in getting the result of the statement dumped out to the console.
The Martin B's method is good if you are changing values in vector. However, to use it in matrix you need to get linear indices.
The easiest solution I found is to use changem function. Very easy to use:
mapout = changem(Z,newcode,oldcode)
In your case: newA = changem(a, 5, -2)
More info: http://www.mathworks.com/help/map/ref/changem.html
Here's a trivial, unoptimised, probably slow implementation of changem from the Mapping Toolbox.
function mapout = changem(Z, newcode, oldcode)
% Idential to the Mapping Toolbox's changem
% Note the weird order: newcode, oldcode. I left it unchanged from Matlab.
if numel(newcode) ~= numel(oldcode)
error('newcode and oldcode must be equal length');
end
mapout = Z;
for ii = 1:numel(oldcode)
mapout(Z == oldcode(ii)) = newcode(ii);
end
end

Storing Results of a Operation in a Matrix

Let's say I want to take the sin of 1 through 100 (in degrees).
I come from a C background so my instinct is to loop 1 through 100 in a for loop (something I can do in Matlab). In a matrix/vector/array I would store sin(x) where x is the counter of the for loop.
I cannot figure out how to do this in Matlab. Do I create a array like
x = [1 .. 100];
And then do
x[offset] = numberHere;
I know the "correct" way. For operations like addition you use .+ instead of + and with a function like sin I'm pretty sure you just do
resultArray = sin(x);
I just want to know that I could do it the C way in case that ever came up, thus my question here on SO. :)
% vectorized
x = sin((1:100)*pi/180);
or
% nonvectorized
x=[];
for i = 1:100
x(i) = sin(i*pi/180);
end
I beleive this can actually be done as a one liner in MatLab:
x = sind(1:100);
Note that you use sind() instead of sin(). Sin() takes radians as arguments.
As others have already pointed out there are for-loops in MATLAB as well.
help for
should give you everything you need about how it works. The difference from C is that the loop can go over objects and not only an integer:
objects = struct('Name', {'obj1', 'obj2'}, 'Field1', {'Value1','Value2'});
for x = objects
disp(sprintf('Object %s Field1 = %d', x.Name, x.Field1))
end
That example will output:
Object obj1 Field1 = Value1
Object obj2 field1 = Value2
This could have been done as
for i=1:length(objects)
x = objects(i);
disp(sprintf('Object %s Field1 = %d', x.Name, x.Field1))
end
And now to what I really wanted to say: If you ever write a for loop in MATLAB, stop and think!. For most tasks you can vectorize the code so that it uses matrix operations and builtin functions instead of looping over the data. This usually gives a huge speed gain. It is not uncommon that vectorized code executes 100x faster than looping code. Recent versions of MATLAB has JIT compilation which makes it less dramatic than before, but still: Always vectorize if you can.
#Daniel Fath
I think you'll need the final line to read
resultArray(i) = sin(x(i)) (rather than x(1))
I think you can also do:
for i = x
...
though that will behave differently if x is not a simple 1-100 vector
Hmm, if understand correctly you want a loop like structure
resultArray = zeros(1,length(x)) %% initialization aint necessary I just forgot how you dynamically add members :x
for i = 1:length(x) %% starts with 1 instead of zero
resultArray(i) = sin(x(i))
end
Warning I didn't test this but it should be about right.