Matlab pdist2 : Out of memory - matlab

I have a vector X which contain x and y value in column 1 and 2 respectively.
I make a calcul between each point :
Distance = pdist2(X,X);
But sometimes I have a problem of memory.
However, I use this matrix in a loop like this :
for i:1:n
find(Distance(i,:) <= epsilon);
.....
end
So, do you know how to make the calcul inside the loop of just the line i of the matrix Distance ?
Thanks

This is what I looked for :
pdist2(X(i,:),X)

Related

How can I easily create a dynamic 2D matrix of vectors in Matlab

Given my code:
G=zeros(height,width); %zeros or whatever
for y = 1 : height
for x = 1 : width
magnitude = sqrt(Gx(y,x)^2 + Gy(y,x)^2);
gradient_direction = atan(Gy(y,x)/Gx(y,x));
G(y,x) = [magnitude gradient_direction];
end
end
I keep getting this (if I don't use zeros()):
Subscripted assignment dimension mismatch.
or this:
Assignment has more non-singleton rhs dimensions than non-singleton
subscripts
While #atru answer works, I would want to suggest a vectorize way that faster and neater, if that will help. The operations here can easily converted to vectorized operations:
G=cat(3,hypot(Gy,Gx),atan(Gy./Gx));
By using G(y,x,:) = [magnitude, gradient_direction]; you are attempting to assign two values to a spot reserved for a single value with indices (y,x). One way to fix this is to use a 3 dimensional array G instead,
G=zeros(height,width,2);
for y = 1 : height
for x = 1 : width
magnitude = sqrt(Gx(y,x)^2 + Gy(y,x)^2);
gradient_direction = atan(Gy(y,x)/Gx(y,x));
G(y,x,:) = [magnitude, gradient_direction];
end
end
Now at each point G(y,x) you can store both of the values and access them as for instance G(1,2,1) for magnitude at (1,2) position and G(1,2,2) for gradient_direction. This assumes Gx and Gy are both arrays with size height x width.
Important thing to note is that slices of G along the third dimension will also be 3D arrays, i.e. mag_dir = G(3,2,:) will have a size [1 1 2] and not [1 2]. This may cause errors in some applications, examples include trying to concatenate mag_dir with another vector (that does not have the extra dimension) and linear algebra operations.
To resolve this, use reshape to explicitly change the dimensions to to target ones. For the vector here it would be reshape(mag_dir, 1, 2). Same holds for 2D slices like more_md = G(1,:,:) - this will need for instance more_md = reshape(more_md,2,5).

calculate conservative interpolation of two vectors in matlab

G'day
Firstly, apologies for poor wording - I'm at a bit of a loss of how to describe this problem. I'm trying to calculate the conservative interpolation between two different vertical coordinate systems.
I have a vector of ocean transport values Ts, that describe the amount of transport at different depth values S. These depths are unevenly spaced (and size(S) is equal to size(Ts)+1 as the values in S are the depths at the top and bottom over which the transport value applies). I want to interpolate(/project?) this onto a vector of regularly spaced depths Z, where each new transport value Tz is formed from the values of Ts but weighted by the amount of overlap.
I've drawn a picture of what I mean (sorry for the bad quality webcam picture) I want to go from Ts1,Ts2.Ts3...TsN (bottom lines) to Tz1,Tz2,...TzN (top lines). The locations in the x direction for these are s0,s1,s2,...sN and z0,z1,z2,...zN. An example of the 'weighted overlap' would be:
Tz1 = a/(s1-s0) Ts1 + b/(s2-s1) Ts2 + c/(s3-s2) Ts3
where a, b and c are shown in the image as the length of overlap.
Some more details:
Example of z and s follow:
z = 0:5:720;
s = [222.69;...
223.74
225.67
228.53
232.39
237.35
243.56
251.17
260.41
271.5
284.73
300.42
318.9
340.54
365.69
394.69
427.78
465.11
506.62
551.98
600.54
651.2];
Note that I'm free to define z, but not s. Typically, z will be bigger than s (i.e. the smallest value in z will be smaller than in s, while the largest value in z will be larger than in s).
Help or tips greatly appreciated. Cheers,
Dave
I don't think there is an easy solution, as stated in the comments. I'll give it a go though :
One hypothesis first : We assume z0>s0 in order for your problem to be defined.
The idea (for your example) would be to get to the array below :
1 (s1-z0) s1-s0 Ts1
1 (s2-s1) s2-s1 Ts2
1 (z1-s2) s3-s2 Ts3
2 (s3-z1) s3-s2 Ts3
2 (z2-s3) s4-s3 Ts4
3 (z3-z2) s4-s3 Ts4
......
Then we would be able to compute, for each row : column1*column3/column2 and then use accumarray to sum the results with respect to the indexes in the first column.
Now the hardest part is to get this array :
Suppose you have :
A Nx1 vectors Ts
2 (N+1)x1 vectors s and z, with z(1)>s(1).
Vectsz=sort([s(2:end);z]); % Sorted vector of s and z values
In your case this vector should look like :
z0
s1
s2
z1
s3
z2
z3
...
The first column will serve as a subscript to apply accumarray, so we'll want it to increase each time there is a z value in our vector Vectsz
First=interp1(z,1:length(z),Vectsz,'previous');
Second=[diff(Vectsz);0]; % Padded with a 0 to keep the right size
Temp=diff(s);
Third=interp1(s(1:end-1),Temp,Vectsz,'previous');
This will just repeat the diff value everytime you have a z value in your vector Vectsz.
The last column is built exactly like the third one
Fourth=interp1(s(1:end-1),Ts,Vectsz,'previous');
Now that the array is built, a call to accumarray is enough to get the final result :
Res=accumarray(First,Second.*Fourth./Third);
EDIT : There is actually no need for the use of interp1 with the previous option :
Vectsz=sort([s(2:end);z]);
First=cumsum(ismember(Vectsz,z));
Second=[diff(Vectsz);0];
idx=cumsum(ismember(Vectsz,s(2:end)))+1;
Diffs=[diff(s);0];
Third=Diffs(idx);
Fourth=Ts(idx);
Res=accumarray(First,Second.*Fourth./Third);

How to find a value of one vector, in a range of value in another vector in matlab

I have a vector A with size of 54000 x 1 and vector B with size of 54000 x 1 which is standard deviation of elements of A. From the other side, I have vector C with size of 300000 x 1. Now I want to find that each element of vector C correspondences to which row of vector A with accepted range 3*standard deviation? I have written the below code and it works fine for small vector but for large vector such that I have it is too too slow!!
for i=1:length(A)
L=A(i,1)- 3*B(i,1);
U=A(i,1)+ 3*B(i,1);
inds{i,1} = not(abs(sign(sign(L - C) + sign(U - C))));
end
Does anybody know how can I make this code faster or does anybody know another solution? THX.
MATLAB is an acronym for Matrix Laboratory and was developed to simply and speed up matrix(vector) calculations. Compared to C or any other programming language you can often skip the for loops when working with matrices. For your code you should be able to skip the for loop and do it as this:
L = A - 3*STD;
U = A + 3*STD;
inds = not(abs(sign(sign(L - C) + sign(U - C))));
And remember that i means the complex number in Matlab. Don't know if it affects speed though.
Edit:
Getting the result as a cell:
inds = num2cell(inds)

Generate matrix with for-loop in matlab

Say I have two functions f(x), g(x), and a vector:
xval=1:0.01:2
For each of these individual x values, I want to define a vector of y-values, covering the y-interval bounded by the two functions (or possibly a matrix where columns are x-values, and rows are y-values).
How would I go about creating a loop that would handle this for me? I have absolutely no idea myself, but I'm sure some of you have something right up your sleeve. I've been sweating over this problem for a few hours by now.
Thanks in advance.
Since you wish to generate a matrix, I assume the number of values between f(x) and g(x) should be the same for every xval. Let's call that number of values n_pt. Then, we also know what the dimensions of your result matrix rng will be.
n_pt = 10;
xval = 1 : 0.01 : 2;
rng = zeros(n_pt, length(xval));
Now, into the loop. Once we know what the y-values returned by f(x) and g(x) are, we can use linspace to give us n_pt equally spaced points between them.
for n = 1 : length(xval)
y_f = f(xval(n))
y_g = g(xval(n))
rng(:, n) = linspace(y_f, y_g, n_pt)';
end
This is nice because with linspace you don't need to worry about whether y_f > y_g, y_f == y_g or y_f < y_g. That's all taken care of already.
For demsonstration, I run this example for xval = 1 : 0.1 : 2 and the two sinusoids f = #(x) sin(2 * x) and g = #(x) sin(x) * 2. The points are plotted using plot(xval, rng, '*k');.

Matlab Vectorization : How to remove for loop in this?

I have following matrices :
X=1 2 3
A=1 2 3
4 5 6
7 8 9
I Want to do
for each (i,j) in A
B(i,j) = sum(A(i,j)*x)
i.e. each element of A is multiplied by vector X, and we sum all 3 elements of that vector.
Can it be done without for loop ?
Something like this perhaps ?
B = A.*sum(X)
EDIT As #HighPerformanceMark points out, you can simply multiply by the sum of X, which is clearly preferrable. Below is a solution that does exactly the steps you wanted to do, which may make my solution useful for non-linear variants of the problem.
You can turn X into a 1-by-1-by-3 array, and multiply it with A to get a 3-by-3-by-3 array, which you can then sum along the third dimension:
X = permute(X,[1,3,2]); %# make X 1*1*3
B = sum( bsxfun(#times, A, X), 3); %# multiply and sum