From: Pete on
Hello all
I calculate a number of random walks, generating x and y coordinates. I wish to map these to a spatial grid (X,Y) of a different resolution. What I want to do is count the number of 'stops' (x,y pairs) that 'land' in each cell of the spatial grid (X,Y). The code below might make it a bit easier to see what I mean. There is a severe bottleneck in the last part of the code where i calculate euclidean distances. If I increase the size and number of the walks (which I really need to do, by a great deal), then this part of the code slows everything down to a crawl. Can anyone think of a way to speed that part up, or replace it?

--------------------------------------------------------------------------

n = 100; % number of steps in each walk
N = 100; % number of separate walks
minstep = 10; % minimum length of each step
mu = 2; % exponent of a power law distribution
x = zeros(N,n); % x coordinates of the walks
y = zeros(N,n); % y coordinates of the walks

angle = 2*pi*rand(N,n); % random trajectory angles
length = minstep*rand(N,n).^(1/(1-mu)); % random trajectory lengths
x = length.*cos(angle); % steps
y = length.*sin(angle); % steps
X = cumsum(x,2); % x coordinates of walk
Y = cumsum(y,2); % y coordinates of walk

% Plot walk coordinates
shg
figure(1),h = plot(X,Y,'b.');
axis square
box on
hold off;
zzz=1;

% Cartesian grid
ls = -5000; % [m]. extent to left of origin
rs = 5000; % [m]. extent to right of origin
ts = 5000; % [m]. extent above origin
bs = -5000; % [m]. extent below origin
xnp = 100; % number of x coordinates
ynp = 100; % number of y coordinates
xk = linspace(ls,rs,xnp); % vector of x coordinates
yk = linspace(ts,bs,ynp); % vector of y coordinates
[Xk,Yk] = meshgrid(xk,yk); % X and Y coordinates

% Storage array for counts
grid = zeros(size(Xk)); % [#]. Will contain a count of the
% number of walk coordinates that 'land'
% in each cell defined by the cartesian grid

% Remove random points that lie outside cartesian grid boundaries
[i] = find(X>rs);X(i) = [];Y(i) = [];
[j] = find(X<ls);X(j) = [];Y(j) = [];
[k] = find(Y>ts);X(k) = [];Y(k) = [];
[l] = find(Y<bs);X(l) = [];Y(l) = [];
nrp = numel(X);

% Assign each random point to its nearest cartesian coordinate
for i = 1:nrp
euc = sqrt((X(i)-Xk).^2+(Y(i)-Yk).^2);
grid(euc==min(min(euc))) = grid(euc==min(min(euc)))+1;
end
---------------------------------------------------------------
From: Pete on
I have tried the following also, but the arrays get too large when I increase n and N to the values I want (e.g., n = 1000, N = 1000):

% Assign each random point to its nearest cartesian coordinate
Xrep = repmat(reshape(X,[1 1 nrp]),[ynp xnp 1]);
Yrep = repmat(reshape(Y,[1 1 nrp]),[ynp xnp 1]);
Xkrep = repmat(Xk,[1 1 nrp]);
Ykrep = repmat(Yk,[1 1 nrp]);
euc = sqrt((Xrep-Xkrep).^2+(Yrep-Ykrep).^2);

for i = 1:nrp
euk = euc(:,:,i);
grid(euk==min(min(euk))) = ...
grid(euk==min(min(euk)))+1;
end
From: ImageAnalyst on
I really don't understand that last for loop. You have X and Y which
is a list of the X and Y coordinates. These are floating point
numbers so you just have to figure out what index they correspond to
and increment it. Something like this
for k =1:nrp
indexX = X(k);
indexY = Y(k);
grid(indexY, indexX) = grid(indexY, indexX) + 1
end

You'd need to modify that if your x and y were in the range (-5000 to
+5000) instead of (1 to nrp) but that's a simple mapping, for example
just add 5000 and divide by 100 or something like that to get the
index in the range of 1-100. This would be many, many fewer
computations than what you are doing.

From: Pete on
ImageAnalyst <imageanalyst(a)mailinator.com> wrote in message <13e0efdd-f5d1-4dbb-9a14-0bffd471b4a3(a)m25g2000yqc.googlegroups.com>...
> I really don't understand that last for loop. You have X and Y which
> is a list of the X and Y coordinates. These are floating point
> numbers so you just have to figure out what index they correspond to
> and increment it. Something like this
> for k =1:nrp
> indexX = X(k);
> indexY = Y(k);
> grid(indexY, indexX) = grid(indexY, indexX) + 1
> end
>
> You'd need to modify that if your x and y were in the range (-5000 to
> +5000) instead of (1 to nrp) but that's a simple mapping, for example
> just add 5000 and divide by 100 or something like that to get the
> index in the range of 1-100. This would be many, many fewer
> computations than what you are doing.

Hey ImageAnalyst
The reality is that X and Y are not created using meshgrid - I just put that in to try and make my example a bit clearer. X and Y are non-uniformly spaced coordinates - covering a wide range of resolutions and a very large extent.........so it does not seem possible to create a finer grid that encompasses all X,Y pairs (to assist in indexing). I was hoping someone would know a nice trick or command that could help...........
From: ImageAnalyst on
Pete:
Yes I realized that. And I thought my last paragraph was the nice
"trick" that would speed it up for you.

Why calculate the min of a huge bunch of numbers, and then compare it
to that same bunch of numbers just to find an index that you already
have? And then you do this unnecessary stuff not once, but twice.
And it's not only twice, it's twice for every one of your ten thousand
numbers - what a huge waste of time and effort for something that can
be done so simply and efficiently.
-ImageAnalyst