Monday, September 21, 2009

Windows: Atbroker.exe failure workaround.

OP:
Atbroker.exe - Application Error in Vista


Quote:

"a workaround for now is to do CTRL-ALT-END and choose Logoff."

Monday, July 27, 2009

Matlab: grouping values according to ID

See also this post.

Q:

If we have n x 2 matrix x:

x = [11 19; 11 29; 10 34; 7 189; 6 123; 11 18; 21 182; 3 171; 6 145; 7 111]


Where the first column specifies the group ID and we want to break up the 2nd column into a cell array according to the grouping ID.

The desired output is:

c = {[171]; [145; 123]; [189; 111]; [34]; [18; 29; 19]; [182]}



A:

[u,dump,g] = unique(x(:,1))
c = accumarray(g,x(:,2),[length(u),1],@(x){x})

Matlab: handling nan for findstr

In many situations handling NaNs can be tricky if we want to write vectorized code.

For example, if I have vector

x = [1 2 3 nan 5 6 nan nan 9 10 11 12 nan 14]


If I want to locate 2 consequtive NaNs, I may use a combination of find, isnan, and diff.

However, what if I want to locate a subvector that also contains NaN? For instance, how to find

y = [3 nan 5]


in x?

If y does not contain NaNs, we know we can use findstr.

The straitforward solution is to convert NaNs to some value that doesn't appear in y.

For example,

sudoNan = max(x)+1;
x(isnan(x)) = sudoNan;
y(isnan(y)) = sudoNan;
findstr(x,y)


An even easier method is:

xc = typecast(x,'uint64');
yc = typecast(y,'uint64');
findstr(xc,yc)

Matlab: grouping and add up values according to ID

OP here.

Q:
Suppose I have n x 3 matrix x, I want a piece of code that checks the first and second columns and if they are equal then it adds up the correponding values in the third column.

x = [
1 2 3; 1 2 5; 1 2 3;...
1 3 1; 1 3 1; 2 1 1;...
2 1 1; 2 1 2; 2 1 2]


The desired answer should be

y = [
1 2 11; 1 3 2; 2 1 6]


A:

[val, dump, idx] = unique(x(:,1:2),'rows')
y = [val, accumarray(idx,x(:,3))]

Matlab: fast way to insert zeros into a vector

OP here.

Q:

Suppose I have vector

x = [1 2 3 4 5 6 7]

How do I insert zeros at every 3rd position to obtain

y = [1 2 0 3 4 0 5 6 0 7]

A1:
y = zeros(1,floor(length(x)*1.5));
z = 1:length(x);
y(z+ceil(z/2)-1) = x;

Matlab: indexing matrix of unknown number of dimensions

OP here.

Q:

If I know a multidimensional matrix x has 4 dims, I can index the first "row" of x using

x(1,:,:,:)


but how do I do this if I don't know ndims beforehand?

A:
c(1:ndims(x)-1)={':'};
x(1,c{:})

Matlab: counting zeros neighbouring each element

Q:

I have matrix x, I want to count for each element the number of zeros in the neighbouring 8 element.

For example, if

x = [
1 0 0
0 1 1
0 1 0];

I want to obtain count

c = [
2 2 1
2 5 3
1 3 0];

A:
c = conv2([1 1 1; 1 0 1; 1 1 1],double(~x),'same');


OR


c = conv2([1 1 1],[1 1 1],double(~x),'same')-~x;

Saturday, July 25, 2009

Matlab: optimization

OP here.

Q:
Is there a way to optimize this for loop?


f = 0;
for i = 1:n
for j = i+1:n
z = y(i) - y(j) ;
f = f + z*z ;
end
end
f = 2*f;



A1:
yy = meshgrid(y);
f = sum(sum((yy - yy.').^2));


A2:
Assuming y is column vector:

f = 2*((n+1)*sum(y.^2)-2*cumsum(y')*y);


A little bit explanation:

Suppose

y = [y1 y2 y3 y4]

f =
(y1-y2).^2 + (y1-y3).^2 + (y1-y4).^2 +
(y2-y3).^2 + (y2-y4).^2 +
(y3-y4).^2
=
y1y1+y2y2-2*y1y2 + y1y1+y3y3-2*y1y3 + y1y1+y4y4-2*y1y4 +
y2y2+y3y3-2*y2y3 + y2y2+y4y4-2*y2y4 +
y3y3+y4y4-2*y3y4
=
y1y1 + y1y1 + y1y1 +
y2y2 + y2y2 + y2y2 +
y3y3 + y3y3 + y3y3 +
y4y4 + y4y4 + y4y4 - 2*(
y1y2 + y1y3 + y1y4 + y2y3 + y2y4 + y3y4
)
=
3*sum(y.^2) - 2*(
(y1).*y2
(y1+y2).*y3
(y1+y2+y3).*y4
)

Friday, June 19, 2009

Misc: a 3D skull model.


Created with Blender.

Tuesday, June 16, 2009

Matlab: find row vector within matrix.

OP here.

Q:

Say I have a matrix:

x = [
11 22 33
44 55 66
11 11 11
33 99 33
11 77 23]


I want to find a specific row in it, say y = [11 11 11].


A1:
You can use ismember with parameter "rows".

A2:
To allow some tolerance:

% engine;
locrow = @(A,x,tol)find(sum(abs(bsxfun(@minus,A,x)),2) <= tol)

% usage;
tol = 0.01
locrow(A,[11.0001, 11.0001, 10.9999], tol)

Matlab: vectorize a loop that depends on past info.

OP here.

Q:

Can anybody think of a vectorized solution to the problem below? suppose x(1) ~= 0;

for k = 2:length(x)
if x(k) == 0
x(k) = x(k-1);
end
end


A:

y = find(x);
x1 = x(y(cumsum(x ~= 0)));



Note:
In most cases the for-loop is probably 3-4 times faster than the vectorized code.

Matlab: vector indexing.

OP here.

Q:
I have a random vector r of size 50000 x 1, and a strictly decreasing measuring vector d of size 300 x 1. I want for each element in r, find the indices of the first value in d that is smaller than it. I tried these codes but it is too slow. Is there a vectorized solution?

n = 50000;
r = rand(n,1);
d = linspace(1,0,300);
idx = nan(n,1);

for k = 1:n
idx(k) = find(r(k) > d, 1, 'first');
end


A:

[dump,idx] = histc(r,d(end:-1:1));
idx = length(d)-idx+1;

Wednesday, June 10, 2009

Matlab: break consecutive numbers into cells

OP here.


Q:

Suppose I have a sorted array like

[1 2 3 4 5 10 11 17 18 19]


I want to break consecutive blocks into separate arrays:

[1 2 3 4 5]
[10 11]
[17 18 19]


A:

mat2cell(x,1,diff([0,find(diff(x) ~= 1),length(x)]))

Tuesday, June 09, 2009

Matlab: find 5 consecutive numbers in an array

OP here.

Q:

I want to find blocks of values of ascending order within a vector. e.g.:

[... 10 1 2 3 4 5 56 ...]

and [1 2 3 4 5] should be recognized.

it should also recognise e.g.:

[... 100 50 51 52 53 54 20 ...]


A:

% if not care about precisely 5 number block;
strfind(diff(x), [1 1 1 1])

% if has to be 5 consecutive number;
strfind(diff(x) == 1,[0 1 1 1 1 0])+1

Thursday, May 21, 2009

Matlab: Vector indexing;

This is related to this post, and this post.

Q:
Suppose I have a vector like: v = [ 3 2 4 1 3 2...]
I want to obtain a new vector like: w = [3 3 3 2 2 4 4 4 4 1 3 3 3 2 2...]
basically every value repeates it's own number of times.

A1 (one-liner):


w = cell2mat(arrayfun(@(x) x+zeros(1,x), v, 'uni', 0))
A2:
v(v == 0) = [] % Need to get rid of zeros in the general case.
c = cumsum(v)
w = zeros(1,c(end))
w([1,c(1:end-1)+1]) = 1
w = v(cumsum(w))
Speed test:

% v = randi(800,1,90000)+1;
Method 1:
Elapsed
time is 1.997060 seconds.
Method 2:
Elapsed time is 1.630775 seconds.


Two methods are about same speed.

Wednesday, May 20, 2009

Matlab: vector indexing;

OP here.

Q:

I have a reference vector r, and a target vector v, I want to find, for every element in v, the index of first element that is greater than or equal to it in r.

With a for loop it shall look like this:

for k = 1:length(r), idx(k) = find(r >= v(k), 1, 'first'); end
A1 (the 'standard' vectorization):

[dummy,idx] = max(bsxfun(@ge,r(:),v(:).'));

A2 (interesting):

idx = ceil(interp1(r,1:length(r),v));

A3 (same logic as A2 but better):

[dummy, idx] = histc(v,r);
idx = idx+1;

Speed test:

% r = cumsum(rand(100000,1));
% r = r./r(end);
% v = rand(20000,1);


Method 1: % actually slower than the for loop ... memory.
Elapsed time is 6.582422 seconds.

Method 2:
Elapsed time is 0.015725 seconds.

Method 3:
Elapsed time is 0.006501 seconds.

The For loop:
Elapsed time is 4.209633 seconds.


Wednesday, May 13, 2009

Matlab: indexing; find first value in each row

OP here.

Q:
How can I find the first index of certain value in each row without using a for loop?

A1:
m = round(rand(9,4)*3); % the data;
[r,c] = size(m);
n = 3; % number to find.

idx = mod(sum(cumprod(double(m ~= n),2),2)+1,c+1)


A2:
idx = zeros(size(m,1),1);
tmp = m == n;
[r,c] = find(tmp & cumsum(tmp,2) == 1);
idx(r) = c;


A3 (fastest):

[v,idx] = max(m == n,[],2)
idx = idx.*(v==1);
% or idx(v==0) = 0;


Speed test:

% m = round(rand(1600000,4)*3);
A1:
Elapsed time is 0.293340 seconds.
A2:
Elapsed time is 0.407424 seconds.
A3:
Elapsed time is 0.110964 seconds.

Matlab: matrix indexing; find duplicate entries in a matrix and replace them with average

OP here.

Q:
I've got a matrix of integer values with three columns (X,Y,Z) and about 10k rows.
X and Y are in range 0..1000 and Z is in the range of 0..200.

In this matrix, there are some pairs of (X,Y) that occur more than once, but with different Z values. Now I want to remove these duplicates and replace all of them with (X,Y,mean of Z).

A:


[u,id1,id2] = unique(A(:,1:2),'rows');
B = [u,accumarray(id2,A(:,3))./accumarray(id2,1)];
% or accumarray(id2,A(:,3),[],@mean) but this is much slower.



Speed test:

% A = [round(rand(10000,2)*1000),round(rand(10000,1))*200];
Elapsed time is 0.005959 seconds.

Monday, May 11, 2009

Matlab: Block randomization

Randomized block design is a common experiment design paradigm. Suppose there are 3 conditions, it seeks to create a random sequence like this:

[3 1 2 2 1 3 1 3 2 1 3 2 1 2 3 2 3 1]

Basically random perm is performed within every size-3 block.

Here's a tip to do this in matlab in one line:

[dump,idx] = sort(rand(nCondition,nTrial));

Matlab: Vector operation

OP here.

Q:

Is there a vectorized way for this code?

for i=1:size(m,2)
m(:,i) = m(:,i).*v(i);
end

A1:

mv = bsxfun(@times,m,v');


A2:

mv = m*diag(v);


all these solutions are much better than using repmat etc.

Matlab: Matrix Indexing

OP here.


Q:

Suppose I have a 3D matrix A:

A(:,:,1) =
[0.1, 0.2, 0;
0.2, 0, 0;
0.6, 0.4, 0]

A(:,:,2) =
[0.2, 0.7, 0;
0.3, 0.8, 0;
0.1, 0, 0]


I want to find, for each row, the element before the first occurrence of zero and subtract it from 1. The outcome should look like this:

B(:,:,1) =
[0.1, 0.8, 0;
0.8, 0, 0;
0.4, 0.6, 0]

B(:,:,2) =
[0.2,0.3,0;
0.3, 0.2, 0;
0.9, 0, 0]



A1:

% location of first occurrence of zero in each row.
z = cumsum(A == 0,2) == 1;
% the element before it.
y = circshift(z,[0,-1]);
B = A;
B(y) = 1-B(y);


A2 (a beautiful solution):

% convolution along columns.
y = convn(logical(A),[-1 1],'same') > 0;
B = A;
B(y) = 1-B(y);

Friday, May 08, 2009

EEG: Topographic contour on 3d head model.


Took me a couple days to program it. But I'm happy.

Tuesday, May 05, 2009

Matlab: Vectorization.

OP here.

Q:

I have


c = cell(n,1); % Each cell is an array of integers.


How do you vectorize this loop? it takes very long.



for i=1:n-1
for j=i+1:n
lic(i,j)=length(intersect(c{i},c{j}));
end
end


A1:

Generate some data for testing:



the data:

n=200; % number of sets
m=100; % element value are from 0 to m-1
meannumel=50; % average number of elements in lists
s = 20; % standard deviation of number of elements
c=cell(1,n);

for k=1:n
nelk = meannumel+round(s*randn);
nelk = min(max(nelk,1),m);
c{k} = floor(m*rand(1,nelk));
end


The engine:


n = length(c);
c = cellfun(@(x) unique(x(:)), c, 'uni', false);

s = cumsum([1 cellfun(@length,c)]).'; % boundary of cell, in vector x;
x = cat(1,c{:}); % all elements, in one long vector;
[x,p] = sort(x); % x is sorted now;

u = cumsum([1;diff(x) ~= 0]);
% before cumsum: boundary of unique (different) elements in x; cumsum: to get a vector u, so that u = 11111223333, # of index equal to count of value;

t = cumsum(accumarray(s,1));
% accumarray: here equal to tmp = zeros(s(end),1); tmp(s) = 1; cumsum: to get a vector t, so that t = 1111222223333 # of index equal to count of that value. here s is boundary of cell, so this t is actually which cell each element belongs;

A = sparse(u,t(p),1,u(end),n);
% sparse: only store non-zero elements, save memory space; syntax: p = sparce(i,j,s,m,n) will create a m x n sparse matrix, with elements p(i(k),j(k)) = s(k); here the intention is to add 1 at, the unique element index, vs. the cell index that each elements belongs.
% A is in the format of: unique item index by which cell, here A is essentially a logical matrix (valued 0, 1 only)

A = triu(full(A'*A),1);
% A'*A is the trick to count intersected values; colums and rows in A are only 1 or 0. matrix muptiplication sums the ones.




A2:
A2 is slightly improved over A1 in that the 'unique' is only called once.


% c must be a list of *row* vectors
[dummy dummy cmap] = unique([c{:}]);
% length(dummy) is the number of unique values in c. cmap is in the form of [1 2 3 1 1 2 2 2 4 ...], which specifies unique values indeces in [c{:}]. length(cmap) = numel([c{:}];
nele = cellfun(@length,c(:));
setid = cumsum(accumarray(cumsum([1; nele]),1));
A = sparse(setid(1:end-1),cmap(:),1,length(c),length(dummy));
A = spones(A); % SPONES Replace nonzero sparse matrix elements with ones.
A = triu(full(A*A.'),1);

Speed comparison:

The for loop: 3.55 sec.
A1: 0.022 sec.
A2: 0.015 sec.

Matlab: Vector manipulation.

OP here.


Q:

Suppose I have

p = [ 0.81 0.90 0.12 0.91 0.63 0.09 0.27 0.54 0.95 0.96 0.15 0.97 0.95 0.48 0.80 0.14 0.42 0.21 0.54 0.14];

v = [ 1 0 0 1 0 1 0 1 1 1 1 1 0 0 0 0 1 1 0 1];



Where the 1 defines the boundary of blocks. So the first block is 1 0 0, second 1 0, third 1 0, fourth 1, fifth 1, ... and so on.

I want to sum values in p according to blocks defined by v. The output in this case should look like:

r = [1.83 1.54 0.36 0.54 0.95 0.96 0.15 3.34 0.42 0.75 0.14];



A:

r = accumarray(cumsum(v(:)),p(:))

Matlab: Vector indexing;

Problem:

Suppose I have a vector:

x = [1 1 1 1 2 2 2 8 8 8 8 8 8 0 0 9 9 7 5 5 2 2 2 2 2]

I want to obtain:

b = [1 2 3 4 1 2 3 1 2 3 4 5 6 1 2 1 2 1 1 2 1 2 3 4 5]

Basically each block of integer is replaced by continuous index of the count.


Solution:

Some initial processing to detect block size and locations:

y = find([true;diff(x(:)) ~= 0;true]);
c = diff(y);
v = x(y(1:end-1));

method 1:

b = cell2mat(arrayfun(@(z)(1:z)',c,'uniformout',false));


method 2:

b = ones(size(x));
b(y(2:end-1)) = 1-c(1:end-1);
b = cumsum(b);


method 3:

g = (1:max(c))'*ones(1,numel(c));
b = g(bsxfun(@ge,c,1:max(c))');


Speed comparison:


% The testing data;
x = cell2mat(arrayfun(@(y,z)(y+zeros(1,z)), ...
randi(100,10000,1),randi(2000,10000,1),'uniformout',false));

% Method 1; 0.25 sec
% Method 2; 0.17 sec
% Method 3; 1.05 sec




Method 2 is better.

Matlab: Matrix Indexing

OP here.


Q:
How do you replace the first nonzero element in each row with -1 ?


A = [
50 75 0;
50 0 100;
0 75 100;
75 100 0;
0 75 100;
0 75 100];

to
-1 75 0
-1 0 100
0 -1 100
-1 100 0
0 -1 100
0 -1 100

A1:
[I, J] = ind2sub(size(A), find(A ~= 0));
[b, c] = unique(I, 'first');
A(sub2ind(size(A), b, J(c))) = -1


A2:
B=cumsum(A~=0,2)>0
B=[false(size(B,1),1) B]
A(logical(diff(B,1,2))) = -1


A3:
A((cumsum(~~A, 2) == 1) & (A ~= 0)) = -1
% notice ~~A is equal to A ~= 0



DSP: How to understand convolution.

OP here.

Definition from wikipedia:



The convolution of ƒ and g is written ƒ∗g. It is defined as the integral of the product of the two functions after one is reversed and shifted.



Let the unit response of a filter be denoted by u, and let x denote the input, y denote the output. Think of the input as the sum of many different delayed and scaled unit inputs:


t = [1, 2, 3, 4, ... n]

x = [x(1), 0, 0, 0, 0 ... 0]
+ [0, x(2), 0, 0, 0 ... 0]
+ [0, 0, x(3), 0, 0 ... 0]
+ ...
+ [0 ... 0, 0, 0, 0, x(n)]



then the output could be seen as the sum of responses to these unit inputs:


y = [u(1)*x(1), u(2)*x(1), u(3)*x(1) ... u(n)*x(1)]
+ [0, u(1)*x(2), u(2)*x(2), u(3)*x(2) ... u(n-1)*x(2)]
+ [0, 0, u(1)*x(3), u(2)*x(3), u(3)*x(3) ... u(n-2)*x(3)]
+ ...
+ [0, 0, ... 0, 0, u(1)*x(n)]


so at particular time n, the output takes the form of:

y(n) = u(n)*x(1) + u(n-1)*x(2) + u(n-2)*x(3) + ... + u(1)*x(n)


which explains why "flipping" is needed in convolution.

Matlab: Matrix manipulation.

OP here.

Q:

I have the following matrix:
[1 5
4 9]

What's the fastest way, and without a for loop, to expand it to:

[1 1 5 5
1 1 5 5
4 4 9 9
4 4 9 9]



A1:

A = [1 4; 5 9] ;
kron(A, ones(3)) ;


A2:

idx = cumsum(ones(2),2 )
B = A(idx, idx)


A3:

[m, n] = size(A);
mdup = 4;
ndup = 3;
vx = ceil((1:m*mdup)/mdup);
vy = ceil((1:n*ndup)/ndup);

B = A(vx, vy)


A4:

[m,n] = size(A);
mdup = 4;
ndup = 3;
AX = repmat(A, [1 1 mdup ndup]);
AX = permute(AX, [3 1 4 2]);
AX = reshape(AX, m*mdup, n*ndup);

Monday, May 04, 2009

Matlab: Vector manipulation.

OP here.


Q:

Suppose

a = [0 0 0 1 1 0 0 0 1 0 0 0 0 1 0 0 1 0 1 ];


I'd like to organize this vector into a matrix with the following criteria: every time I see a 1,
I want to copy that 1 and 2 other members before it into a new line, so my resulting matrix will look like this:

b = [
0 0 1
0 1 1
0 0 1
0 0 1
0 0 1
1 0 1];


Is there a vectorized solution?

A:

apad=[0 0 a];
i1 = find(apad == 1);
b = apad(bsxfun(@plus, i1(:), (-2:0)))

Matlab: Split a vector into continuous chunks.

Original post here.


Q:

Suppose I have [1 2 3 4 8 9 16 17 18], how do I get [1 2 3 4], [8 9], [16 17 18] in a vectorized way?

A:

a = [1 2 3 4 8 9 16 17 18];

b=a-(1:length(a));
b = [true; diff(b(:)) ~= 0; true];
split = mat2cell(a(:).', 1, diff(find(b)));

split{:}

Matlab: Automatic conversion to element-by-element operation.

Original post here.

Q:

Is there a function which automatically puts points in front of / , * or ^ in a formula?

e.g.
from
f = 3*sin(2*x^2)

to
f = 3.*sin(2.*x.^2)

A:

help vectorize

Matlab: Including function definitions when Publishing

Q:

I'm using MATLAB to generate a report from a script file, and was wondering if it's possible to somehow include function definitions which will be automatically be added to my published document. Instead of having to copy/paste between seperate published documents into a final one.

A:

help dbtype

Original post here.

Matlab: Product Support 1109 - Code Vectroization Guide

Original post here.

This section might be useful:

Suppose you want to multiply each column of a very large matrix by the same vector. There is a way to do this using sparse matrices that saves space and can also be faster than matrix construction...

F = rand(1024,1024);
X = rand(1024,1);

Y = F * diag(sparse(X));
Y = diag(sparse(X)) * F;

On the other hand, most of times bsxfun would be a more efficient solution.

Matlab: search via command line

lookfor Search all M-files for keyword.

docsearch Search HTML documentation in the Help browser.



Original post here.

Q:
Is there a general command in command window to display all conversion functions used in matlab, i.e. num2str, int2str, setstr, hex2num, ... etc?

A:
lookfor convert;
docsearch convert;
docsearch conversion;