matlab - find nearby points of a lot of objects - matlab

I have a number of objects that each have three matrices of distance between own points (x1-x1,x1-x2,x1-x3...;x2-x1,x2-x2,x3-x2...) also with y and z.
I want to find as many nearby points as possible, assuming rotation is not an issue.
I tried something. Since Matlab is supposed to work easy with matrices I am sure something is cumbersome but I don't know how to fix it.
For each object and it's mirror, and for each translation on each axes there is an xyz scenario:
(x1,y1,z1;x2,y2,z2;...)
So I am translating and mirroring one object a million times.
for m=1:object1
for n=1:object2
for i=1:NumRows
for j=1:NumRows2
d_x(m,n,i,j)=obj(m).xyz(i,1)-obj(n).xyz(j,1);
d_y(m,n,i,j)=obj(m).xyz(i,2)-obj(n).xyz(j,2);
d_z(m,n,i,j)=obj(m).xyz(i,3)-obj(n).xyz(j,3);
d_r(m,n,i,j)=sqrt(d_x(m,n,i,j)*d_x(m,n,i,j)+d_y(m,n,i,j)*d_y(m,n,i,j)+d_z(m,n,i,j)*d_z(m,n,i,j));
if d_r(m,n,i,j)>=0 & d_r(m,n,i,j)<1.2
d_r(m,n,i,j)=1.2-d_r(m,n,i,j);
else
d_r(m,n,i,j)=0;
end
sy(m,n)=sy(m,n)+d_r(m,n,i,j);
end
end
end
end

Whenever you start putting indices in variable names, think twice if they maybe should be a single variable. Here we have d_x d_y d_z. My recommendation would be to replace them by a single variable:
d_xyz(m,n,i,j,:)=obj(m).xyz(i,:)-obj(n).xyz(j,:);
And now to your next line, what you are calculating there is actually called a 2-norm. If you know the name, it's simple to shorten:
d_r(m,n,i,j) = norm(squeeze(d_xyz(m,n,i,j,:)),2);

Related

Avoiding for loop with cells and matrixes involved

I am trying to avoid the for loops and I have been reading through all the old posts there are about it but I am not able to solve my problem. I am new in MATLAB, so apologies for my ignorance.
The thing is that I have a 300x2 cell and in each one I have a 128x128x256 matrix. Each one is an image with 128x128 pixels and 256 channels per pixel. In the first column of the 300x2 cell I have my parallel intensity values and in the second one my perpendicular intensity values.
What I want to do is to take every pixel of every image (for each component) and sum the intensity values channel by channel.
The code I have is the following:
Image_par_channels=zeros(128,128,256);
Image_per_channels=zeros(128,128,256);
Image_tot_channels=zeros(128,128,256);
for a=1:128
for b=1:128
for j=1:256
for i=1:numfiles
Image_par_channels(a,b,j)=Image_par_channels(a,b,j)+Image_cell_par_per{i,1}(a,b,j);
Image_per_channels(a,b,j)=Image_per_channels(a,b,j)+Image_cell_par_per{i,2}(a,b,j);
end
Image_tot_channels(a,b,j)=Image_par_channels(a,b,j)+2*G*Image_per_channels(a,b,j);
end
end
end
I think I could speed it up introducing (:,:,j) instead of specifying a and b. But still a for loop. I am trying to use cellfun without any success due to my lack of expertise. Could you please give me a hand?
I would really appreciate it.
Many thanks and have a nice day!
Y
I believe you could do something like
Image_par_channels=zeros(128,128,256);
Image_per_channels=zeros(128,128,256);
Image_tot_channels=zeros(128,128,256);
for i=1:numfiles
Image_par_channels = Image_par_channels + Image_cell_par_per{i,1};
Image_per_channels = Image_per_channels + Image_cell_par_per{i,2};
end
Image_tot_channels = Image_par_channels + 2*G*Image_per_channels;
I haven't work with matlab in a long time, but I seem to recall you can do something like this. g is a constant.
EDIT:
Removed the +=. Incremental assignment is not an operator available in matlab. You should also note that Image_tot_channels can be build directly in the loop, if you don't need the other two variables later.

how can I find the place of some numbers in a Matlab matrix?

I have a matrix with values from -180 to 180 and I want to find all the places where each value is and then save them in a new matrix, how can I do it?
I want to create a for loop that goes for values -180:1:180 and finds all the locations(i,j) for each value. e.g I want to find all the locations for value -180 and then save them in a new matrix. is it possible to be done? I wrote here the code for the loop function and it works but I don't know how to save the values so as to know which location is for each value.
for a= 180:-1:-180
[i,j]=find(ORIENT==a)
end
So many ways to do this.Assuming that ORIENT is the matrix, you could use cells to store the i's and j's, like:
ORIENT=round(180.*(2.*rand(100,100)-1)); %or whatever
find_results=cell(361,2);
a=-180:1:180;
for index=1:length(a)
[i,j]=find(ORIENT==a(index));
find_results{index,1}=i;
find_results{index,2}=j;
end
Not very elegant or efficient, but it works fine for me. I know you wantted to use matrix, but as you cant freely choose the length of each column in the matrix, I think this will do. Otherwhise you could go like
find_results(index,1:length(i))=i;
But you need to first create the matrix which will end up filled with zeros,because the only way for this to work is to make sure size(find_result,1)=number of elements in the matrix(cells dont care). You could use a sparse matrix but man, it is getting out of hand.
--------------------------edit---------------------------------------
I guess you could do something like this for a matrix, but size will be huge:
ORIENT=round(180.*(2.*rand(100,100)-1)); %or whatever
a=-180:1:180;
find_results_i=nan(size(ORIENT,1).*size(ORIENT,2),size(a,2));
find_results_j=nan(size(ORIENT,1).*size(ORIENT,2),size(a,2));
for index=1:length(a)
[i,j]=find(ORIENT==a(index));
find_results_i(1:length(j),index)=i;
find_results_j(1:length(j),index)=j;
end
If you are familiar with sparse, use
find_results_i=sparse(size(ORIENT,1).*size(ORIENT,2),size(a,2));
find_results_j=sparse(size(ORIENT,1).*size(ORIENT,2),size(a,2));
To save a ton of memory, altougth it will be slower

Vector operations on object-array with 'colon' indexing [MATLAB]

In my Matlab code I have an object-array of 'masses' which are an object of a class which describes the mass, speed, accerleration etc.
To speed up the simulation I want to reduce the usage of for-loops with using more vector operations. One of the operations is to get the distance of the current mass to all others.
I would like to solve it like that:
%position is a vector with x and y values e.g. [1 2]
%repeat the current mass as many times as there are other masses to compare with
currentMassPosition = repmat(obj(currentMass).position, length(obj), 2);
distanceCurrentMassToOthersArray = obj(:).position - currentMassPosition;
I cannot use the colon-indexing operation on the object array. Currently i use a for-loop where I iterate through every single object. Do you have any tips to optimise that without using a for loop?
I hope my question was clear enough, otherwise I will optimise it ;).
I used this code to reproduce your problem. For future questions please try to include such examples into your question:
classdef A
properties
position
end
methods
function obj=A()
obj.position=1;
end
end
end
.
%example code to reproduce
x(1)=A
x(2)=A
x(3)=A
%line which causes the problem
x(:).position-3
To understand why this is not working, take a look at the output of x(:).position, just type it into the console. You get multiple ans values, indicating a comma separated list of multiple values. If you use [x(:).position] instead, you get an array of doubles. The correct code is:
[x(:).position]-3

Suppress kinks in a plot matlab

I have a csv file which contains data like below:[1st row is header]
Element,State,Time
Water,Solid,1
Water,Solid,2
Water,Solid,3
Water,Solid,4
Water,Solid,5
Water,Solid,2
Water,Solid,3
Water,Solid,4
Water,Solid,5
Water,Solid,6
Water,Solid,7
Water,Solid,8
Water,Solid,7
Water,Solid,6
Water,Solid,5
Water,Solid,4
Water,Solid,3
The similar pattern is repeated for State: "Solid" replaced with Liquid and Gas.
And moreover the Element "Water" can be replaced by some other element too.
Time as Integer's are in seconds (to simplify) but can be any real number.
Additionally there might by some comment line starting with # in between the file.
Problem Statement: I want to eliminate the first dip in Time values and smooth out using some quadratic or cubic or polynomial interpolation [please notice the first change from 5->2 --->8. I want to replace these numbers to intermediate values giving a gradual/smooth increase from 5--->8].
And I wish this to be done for all the combinations of Elements and States.
Is this possible through some sort of coding in Matlab etc ?
Any Pointers will be helpful !!
Thanks in advance :)
You can use the interp1 function for 1D-interpolation. The syntax is
yi = interp1(x,y,xi,method)
where x are your original coordinates, y are your original values, xi are the coordinates at which you want the values to be interpolated at and yi are the interpolated values. method can be 'spline' (cubic spline interpolation), 'pchip' (piece-wise Hermite), 'cubic' (cubic polynomial) and others (see the documentation for details).
You have alot of options here, it really depends on the nature of your data, but I would start of with a simple moving average (MA) filter (which replaces each data point with the average of the neighboring data points), and see were that takes me. It's easy to implement, and fine-tuning the MA-span a couple of times on some sample data is usually enough.
http://www.mathworks.se/help/curvefit/smoothing-data.html
I would not try to fit a polynomial to the entire data set unless I really needed to compress it, (but to do so you can use the polyfit function).

Gaps In Plot Of Piecewise Function in Matlab

I want to plot a piecewise function, but I don't want any gaps to appear
at the junctures, for example:
t=[1:8784];
b=(26.045792 + 13.075558*sin(0.0008531214*t - 2.7773943)).*((heaviside(t-2184))-(heaviside(t-7440)));
plot(b,'r','LineWidth', 1.5);grid on
there should not be any gaps appearing in
the plot between the three intervals , but they do.
I want the graph to be continueous without gaps.
Any suggestions on how to achieve that.
Thanks in advance.
EDIT
Actually, my aim is to find the carrier function colored by yellow in the figure below. I divide the whole interval into 3 intervals: 1-constant 2-sinusoidal 3- constant, then I want to find the overall function from the these three functions
Of course there are "gaps". The composite function is identically zero for all t<2184, and for all t>7440. The relationships can only be non-zero inside of that interval. And you have not chosen a function that is zero at the endpoints, so how can you expect there not to be "gaps"?
What values does your function take on at the endpoints of the interval?
>> t = [2184 7440];
>> (26.045792 + 13.075558*sin(0.0008531214*t - 2.7773943))
ans =
15.689 20.616
So look at the hat function part of this. I'll be lazy and use ezplot.
>> ezplot(#(t) ((heaviside(t-2184))-(heaviside(t-7440))),[0,8784])
Now, combine this, multiplying it by a trig piece, and of course the result is identically zero outside of that domain.
>> ezplot(#(t) (26.045792 + 13.075558*sin(0.0008531214*t - 2.7773943)).*((heaviside(t-2184))-(heaviside(t-7440))),[0,8784])
But if your goal is some sort of continuous function across the two chosen points in the hat function, you need to chose the trig part such that it is zero at those same two points. Mathematics is not spelled mathemagics. Wishing that you get a continuous function will not make it so.
So is your real question how to chose that internal piece (segment) as one such that the final result is continuous? If so, then we need to know why you have chosen the arbitrary constants in there. Surely these numbers, {26.045792, 13.075558, 0.0008531214, 2.7773943} all must have some significance to you. And if they are important, then how can we possibly make the result a continuous function?
Perhaps, and I'm just guessing here, you want some other result out of this, such that the function is not identically zero outside of those bounds. Perhaps you wish to extrapolate as a constant function outside of those points. But to help you, you must help us.