I have a matrix of zeros and ones. Each cell with a one value represents a non empty cell.
The cells with the ones is kept in a vector with the coordinates.
I'm iterating through the list and move each element randomly to one of its free neighboring cells.
Is there a way to do this with vector operations?
Thanks
Here's an attempt, not the most elegant or efficient one, but still it should work.
first I assume you have the x,y coordinates of your non empty cells, something like
c=[x y];
The relative positions of the 8 nearest neighbors (n.n.) in a 2D array are given by:
nn=[1 1;1 -1;-1 1;0 -1;-1 0;0 1;1 0;-1 -1];
Let's take all possible permutation of each x,y coordinate in c around its n.n.
permc=bsxfun(#plus,repmat(c,[1 8]),nn(:)');
Now set a vector of random n.n. out of the 8 options for each x,y coordinates:
ri=randi(8,numel(x), 1);
and use it to select random new coordinates
new_c= [ permc(sub2ind(size(permc), (1:numel(x))', 2*ri-1 )) , ...
permc(sub2ind(size(permc), (1:numel(x))', 2*ri))];
Issues:
The code doesn't check if there is a n.n. that is not free, not hard to solve having info of c and permc at hand.
The code doesn't care that a point is on the edge of the array, so it can select a coordinate that is either 0 or one larger than the size of the array. Again, permc has the info to tackle this case and it can be treated separately in several ways.
That's the jist.
Probably, but I think it would be quite tricky to write. You'd have to be careful to prevent two "dots" from moving into the same empty location at the same time.
Looping over the vector and dealing with one dot at a time seems far easier. What's your reason for wanting to do this with vector operations? If you're looking to make your code faster, post your code and ask for suggestions.
Related
I have two 3D arrays:
shape is a 240 x 121 x 10958 array
area is a 240 x 1 x 10958 array
The values of the arrays are of the type double. Both have NaN as fill values where there is no relevant data.
For each [240 x 121] page of the shape array, there are several elements filled by the same number. For example, there will be a block of 1s, a block of 2s, etc. For each corresponding page of the area array there is a single column of numeric values 240 rows long. What I need to do is progressively go through each page of the shape array (moving along the 3rd, 10958-long axis) and replace each numbered element in that page with the number that fills the row of the matching number in the area array.
For example, if I'm looking at shape(:,:,500), I want to replace all the 8s on that page with area(8,1,500). I need to do this for numbers 1 through 20, and I need to do it for all 10958 pages of the array.
If I extract a single page and only replace one number I can get it to work:
shapetest = shape(:,:,500);
shapetest(shapetest==8)=area(8,1,500);
This does exactly what I need for one page and for one number. Going through numbers 1-20 with a for loop doesn't seem like an issue, but I can't find a vectorized way to do this for all the pages of the original 3D array. In fact, I couldn't even get it work for a single page without extracting that page as its own matrix like I did above. I tried things like this to no avail:
shape(shape(:,:,500)==8)=area(8,1,500);
If I can't do it for one page, I'm even more lost as to how to do it for all at once. But I'm inexperienced in MATLAB, and I think I am just ignorant of the proper syntax.
Instead, I ended up using a cell array and the following very inefficient nested for loops:
MyCell=num2cell(shape,[2 1]);
shapetest3=reshape(MyCell,1,10958);
for w=1:numel(shapetest3)
test_result{1,w}=zeros(121,240)*NaN;
end
for k=1:10958
for i=1:29040 % 121 x 240
for n=1:20
if shapetest3{1,k}(i)==n
test_result{1,k}(i)=area(n,1,k);
end
end
end
end
This gets the job done, and I can easily turn it back to an array, but it is very slow, and I am confident there is a much better vectorized way. I'd appreciate any help or tips. Thanks in advance.
To vectorize the mapping operation, we can use shape as an index into area. But because the mapping is different for each plane, we need to loop over the planes to accomplish this. In short, it'll look like this:
test_result = zeros(size(shape)); % pre-allocate output
for k=1:size(area,3) % loop over planes
lut = area(:,1,k);
test_result(:,:,k) = lut(shape(:,:,k));
end
The above only works if shape only contains integer values in the range [1,N], where N = size(area,1). That is, for other values in shape we'll be doing wrong indexing. We will need to fix shape to avoid this. The question here is, what do we want to do with those out-of-range values?
As an example, preparing shape to deal with NaN values:
code = size(area,1) + 1; % this is an unused code word
shape(isnan(shape)) = code;
area(code,1,:) = NaN;
This replaces all NaN values in shape with the value code, which is one larger than any code value we were mapping. Then, we extend area to have one more value, a value for the input code. The value we fill in here is the value that the output test_result will have where shape is NaN. In this case, we write NaN, such that NaN in the input maps to NaN in the output.
Something similar can be done with values below 0 and above 240 (shape(shape<1 | shape>240) = code), or with non-integer values (shape(mod(shape,1)~=0) = code).
I have a struct like this mesh.m_1_0.Deformation_Entformung;
the second field is a struct from m_1_0 till m_3_5 in 6 steps;
the Deformation_Entformung is a matrix with 6 columns and 325562 rows, whereby the first 3 columns contain coordinates (x,y,z).
Now I'm interested in the coordinates that are the closest to (33.5 -88.7801,-0.4480).
This is my code:
SNames = fieldnames(mesh); % SName = m_1_0,m_1_5...m_3_5
for loopIndex = 1:numel(SNames)
stuff = mesh.(SNames{loopIndex}).Deformation_Entformung;
mesh.(SNames{loopIndex}).('Deformation_Entformung_Koordi')=...
stuff(min(stuff(:,1)-33.5) & min(stuff(:,2)--88.7801) & ...
min(stuff(:,3)-0.4480), :);
end
The code runs, but the problem is that the answer is always the first row of the matrix Deformation_Entformung.
I would be glad, if someone could give me a hint.
Well, first of all you mix up indices with values.
min(stuff) returns the minimal value of stuff. So when you write stuff(min(stuff)) that's certainly not doing what you want it to do.
Secondly, if min(stuff(:,1)-33.5) would actually return an index (which it doesn't), then the index would be the same whether you searched for min(stuff(:,1)+100) or min(stuff(:,1)-500000). So the program would still not be doing what you want it to do.
Additionally, the way you are trying to search for the closest point does not even work from a mathematical point of view (even if your programming had no errors). The closest point is not necessarily the closest in each single coordinate. For example, [1 1 1] is certainly closer to [0 0 0] than [20 0 0], [0 20 0] and [0 0 20]. But it is not the closest one in each single coordinate. In fact it is not the closest one in any coordinate.
There might be even more issues with your code, but for starters you should work on how to determine distances. After you master that you should try to pick points with minimal distance. And only after you master both of these should you try to integrate everything into the rest of your stuff. No point in trying to do everything at once.
I am currently working in matlab to design a way to reconstruct 3D data. For this I have two pictures with black points. The difference in the amount of points per frame is key for the reconstruction, but MATLAB gives an error when matrixes are not equal. This is happening becaus the code is not doing what I want it to do, so can anyone hel me with the following?
I have two columns of Xdata: XLI and XRI
What matlab does when I do XLI-XRI is substracting the pairs i.e XLI(1)-XRI(1) etc, but I want to substract each value of XRI of every value of XLI. i.e
XLI(1)-XRI(1,2,3,4 etc)
XLI(2)-XRI(1 2 3 4 etc)
and so on
Can anyone help?
I think you are looking for a way to deduct all combinations from eachother. Here is an example of how you can do that with bsxfun:
xLI = [1 2 3]
xRI = [1 2]
bsxfun(#minus,xLI ,xRI')
I cannot comment on Dennis's post (not enough points on this website) : his solution should work, but depending on your version of Matlab you might get a "Error using ==> bsxfun" and need to transpose either xLI or xRI for that to work :
bsxfun(#minus,xLI' ,xRI)
Best,
Tepp
I have two vectors that happen to be lat and long that I extracted from a shape file. I would like to interpolate the values so I have the same resolution as the points from which I am finding the distance.
I found this question and another question that almost solve my problem. The difference is I do not know the spacing between my vector points (they vary) and I want to make sure I always have at most 0.0042 deg between points. Below are the first 10 points of my lat/long vectors.
latlim=interp1(latlim,1:0.001:numel(latlim)); gets me what I want to avoid any aliasing but I'd like to get exactly 0.0042 between points rather than just 1000 new points for the sake of efficiency. I have a lot of points to iterate on.
latlim=[78.1530 77.9963 77.6970 77.4092 77.7322 78.0511 78.1530 NaN 78.8044 78.6020];
latlim=interp1(latlim,1:0.001:numel(latlim));
lonlim=[-111.2644 -109.8545 -110.1869 -112.0512 -113.5343 -112.7246 -111.2644 NaN -110.9637 -109.6631];
lonlim=interp1(lonlim,1:0.001:numel(lonlim));
Thanks!
I hope I understood your question:
If you want a constant step of 0.042 then try:
lonlim = interp1( lonlim, lonlim(1): 0.042 :lonlim(end) );
This will create a vector starting at the first value of lonlim, which is lonlim(1), with a step of 0.042, until the last value of lonlim, which is lonlim(end).
Hope it works! :)
I'm trying to create a random "path" on a coordinate system on Matlab. I am doing this by creating a for loop where for each iteration it fills in a new value on a matrix that has initial values of zeros.
For example, I have 5 points so I have an initial matrix a=[0 0 0 0 0; 0 0 0 0 0] (row1 = x values, row2 = y values).
The path can move right/left or up/down (no diagonals). In my for loop, I call randi(4) and say something like "if randi(4)=1, then move 1 point to the left (x-1). if randi(4)=2, then move to the right (x+1), etc."
The problem is that you cannot visit a specific point more than once. For example, the path can start at (0,0), then go to (0,1), then (1,1), then (1,0), and then it CANNOT go back to (0,0).. in my current code I don't have this restriction so I was hoping I could get some suggestions..
Since in this example the matrix would look something like a=[0 0 1 1 0; 0 1 1 0 0].
I was thinking of maybe subtracting each new coordinate (here (0,0)) from each column on the matrix a and if any of the columns give me values of zero for both rows (since it's the same coordinate subtracted from itself), then go back one step and let randi(4) run again.. but
How could I tell it to "go back one step" (or two or three)?
How do you compare one column against each column of the already established matrix?
This was just an idea.. are there any functions in Matlab that would let me do this? or maybe compare if two columns are the same within a matrix?
To your questions.
to go back - I suppose this means just throwing away the rightmost columns in your matrix.
to find if it is present you could use ismember
unfortunately it only takes rows so you will need to transpose. Snippet:
a = [1:10; repmat(1:2,1,5)]'
test = ismember(a,[3,2],'rows')
any(test) % not found
test = ismember(a,[3,1],'rows')
any(test) % found
Of course your idea would also work.
I can answer this:
How do you compare one column against each column of the already
established matrix?
Use two different matrices. Compare them using the setdiff() function: http://www.mathworks.com/help/matlab/ref/setdiff.html