How to perform a checkerboard-interpolation in matlab? - matlab

I have two matrices A and B containing values for a checkerboard/chessboard-like grid of the form
AxAxAxAx...
xBxBxBxB...
AxAxAxAx...
xBxBxBxB...
...........
...........
Where x represents values not yet known which I want to (linearly) interpolate. What's the easiest way to achieve this?
First thing is probably
C = zeros(size(A)+size(B));
C(1:2:end,1:2:end) = A;
C(2:2:end,2:2:end) = B;
to obtain aforementioned matrix. Now I could loop through all remaining points and take the average of all direct neighbours, for 1) for loops in matlab are slow and 2) there's certainly a way to use interp2, though that seems to require a meshgrid-like grid. So, can this be done easier/faster?

Thanks to woodchips' answer here I found his inpaint_nans, the solution is indeed simple:
C = nan(size(A)+size(B));
C(1:2:end, 1:2:end) = A;
C(2:2:end, 2:2:end) = B;
C = inpaint_nans(C);

Related

Using spfun with two identically ordered sparse matrices

I got two sparse matrices A and B, which have identical sparsity pattern (all nonzeros are at exactly the same locations):
i = randi(1000,[50,1]);
j = randi(1000,[50,1]);
a = rand(50,1);
b = rand(50,1);
A = sparse(i,j,a,1000,1000);
B = sparse(i,j,b,1000,1000);
I would like to calculate efficiently exp(A-B) only for the nonzeros, and save it back into A.
I tried to use spfun for that task:
f = #(x,y) exp(x-y);
A = spfun(f,A,B);
but I got an error in spfun saying: "Too many input arguments."
Can anyone suggest an efficient way to calculate it?
It should be calculated many times.
Thanks!
Edit: mikkola suggested A = spfun(#f,A-B) which solves the problem, but the question remains how to do it with a function of two variables that can't be solved using the same trick. For example:
g = #(x,y) x.*cos(y);
A = spfun(#g,A,B);
You can't use
A = spfun(#exp, A-B);
because for entries where A an B are equal you will get 0 instead of 1.
To solve that, you can compute the vector of exponentials at the nonzero components, and then build a sparse matrix from that:
A = sparse(i,j,exp(nonzeros(A)-nonzeros(B))); %// if you have i, j stored
or
A(find(A)) = exp(nonzeros(A)-nonzeros(B));
Edit
According to the documentation, spfun can take only two inputs: a function and one sparse matrix.
So you cannot do directly what you want to do. The best solution is probably what has been suggested in the comments, i.e.:
res = spfun(#exp, A-B);
Best,

Matlab: How to re-order (re-organize) a matrix

I have a random column matrix:
r = rand(1,300)';
I want to re-order it so that instead of having elements in the order of 1,2,3,...,300
I will have elements 1,11,21,31,...,291,2,12,22,32,...,292,3,13,33,...293,...,300.
In other words, I want to take every 10th value, beginning with 1 and put them in that order, then do the same for 2 with every 10th value. I know one way to do this is:
n = 10;
r = [r(1:n:numel(r)); r(2:n:numel(r)); r(3:n:numel(r));...;r(10:n:numel(r))]; % Skipped 4-9 in this example
But obviously, this is very cumbersome to do more than a couple of times. Is there something more efficient?
A loop should be easy, but I am not doing it correctly, it seems (I can see why this might not work, but I can't correct it).
(Here is what I tried:)
n = 10;
for i = 1:10
a = [r(i:n:numel(r))];
end
Any suggestions or help is greatly appreciated.
You can do it like this:
r = reshape(reshape(r, 10, 30)', 300, 1)
EDIT:
As pointed out by #LuisMendo on the comments, it's safer to use .' than ' to transpose the matrix, because if the matrix is complex, that could introduce a complex conjugation. Then, it would be safer to do it like this:
r = reshape(reshape(r, 10, 30).', 300, 1)
You could reshape it into 30x10 matrix, transpose, and take the flat index:
A = 1:300;
A = reshape(A,30,10);
A = A';
A = A(:);
Try this -
intv = 10; %%// Interval after which you intend to get the values consecutively
out = r(reshape(reshape(1:numel(r),intv,[])',1,[]))
Some of the other solutions posted are more efficient, but your idea was a good one. It requires a simple fix to work:
N = numel(r);
M = N/10;
a=[];
for ii = 1:M
a= [a r(ii:10:N)];
end
Hope this helps

Multiplying each element of a vector with a matrix

I have a vector v and a matrix M. I want to multiply each element of v with M and then sum all the resulting matrices.
for i=1:length(v)
lala(:,:,i) = v(i).*M;
end
sum(lala, 3)
Is it possible to do this without a for loop?
I think Danil Asotsky's answer is correct. He's exploiting the the linearity of the operation here. I just want to give another solution, using use the Kronecker tensor product, that does not dependent on this linearity property, hence still works with operation other than sum:
kvM = kron(v,M);
result = sum(reshape(kvM,[size(M) numel(v)]),3)
It's too late at my local time, and I dont feel like explaining the details of why this works, if you can't figure out from matlab help and wikipedia, then comment below and I'll explain for you.
Do you have single matrix M that don't depend from i?
In this case sum(v(i) * M) = sum(v(i)) *M.
E.g you will have expected result for code:
v_sum = sum(v);
lala_sum = v_sum * M;

Vectorizing the creation of a matrix of successive powers

Let x=1:100 and N=1:10. I would like to create a matrix x^N so that the ith column contains the entries [1 i i^2 ... i^N].
I can easily do this using for loops. But is there a way to do this using vectorized code?
I'd go for:
x = 1:100;
N = 1:10;
Solution = repmat(x,[length(N)+1 1]).^repmat(([0 N])',[1 length(x)]);
Another solution (probably much more efficient):
Solution = [ones(size(x)); cumprod(repmat(x,[length(N) 1]),1)];
Or even:
Solution = bsxfun(#power,x,[0 N]');
Hope this helps.
Sounds like a Vandermonde matrix. So use vander:
A = vander(1:100);
A = A(1:10, :);
Since your matrices aren't that big, the most straight-forward way to do this would be to use MESHGRID and the element-wise power operator .^:
[x,N] = meshgrid(1:100,0:10);
x = x.^N;
This creates an 11-by-100 matrix where each column i contains [i^0; i^1; i^2; ... i^10].
Not sure if it really fits your question.
bsxfun(#power, cumsum(ones(100,10),2), cumsum(ones(100,10),1))
EDIT:
As pointed out by Adrien, my first attempt was not compliant with the OP question.
xn = 100;
N=10;
solution = [ones(1,xn); bsxfun(#power, cumsum(ones(N,xn),2), cumsum(ones(N,xn),1))];
Why not use an easy to understand for loop?
c = [1:10]'; %count to 100 for full scale problem
for i = 1:4; %loop to 10 for full scale problem
M(:,i) = c.^(i-1)
end
It takes more thinking to understand the clever vectorized versions of this code that people have shown. Mine is more of a barbarian way of doing things, but anyone reading it will understand it.
I prefer easy to understand code.
(yes, I could have pre-allocated. Not worth the lowered clarity for small cases like this.)

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.