Find "external" elements bigger than a threshold value in a 3D matrix - matlab

I was wondering if someone could help me come up with a code for a 3D image I'm working on wright now.
I've got a simple 3D matrix:
A(:,:,1) =
0 7 4
0 32 9
4 3 1
A(:,:,2) =
6 0 4
3 4 6
2 3 11
A(:,:,3) =
12 2 4
10 20 6
14 3 2
I would like to find those values that are bigger than a threshold value (for example biger than 7). However I only want those that are exterior elements, that is, not "central" elements (the 32 on the first layer of the matrix shouldn't be marked as a maximum)
(I'm working with a bigger matrix but I guess that once I'm able to do this for the small 3D matrix from above, it won't be difficult to do it for larger ones).
Thank you a lot

Try this:
A = randn(4,4,4); % data. Arbitrary size
th = 1; % threshold
ind = find(A>th);
[x y z] = ind2sub(size(A), ind);
ext = find((x==1)|(x==size(A,1))|(y==1)|(y==size(A,2))|(z==1)|(z==size(A,3)));
ind_solution = ind(ext); % linear index of desired values
solution = A(ind_solution) % desired values

I'm guessing you could extract vectors from those matrices... so it's a matter of getting the external vectors and looping trough their elements.
I think this link will help you extract a vector.

Related

Directly create sparse adjacency matrix - (matrix exceeds maxium array size preference)

Problem
I am using an adjacency matrix in my algorithm, which worked fine as long as I tested it an small matrixes (3000) points. But my actual problem includes 167620 points and I would like to create an adjacency matrix for that problem.
But obviously due to the length I get the following problem:
Requested 167620x167620 (209.3GB) array exceeds maximum array size preference. Creation of arrays greater than this limit may take a
long time and cause MATLAB to become unresponsive.
I use the following code:
adjMat = zeros(size(NB_list_all,1));
for ind = 1:size(NB_list_all,1)
adjMat(ind, nonzeros(NB_list_all(ind,2:end))) = 1;
end
adjMatS=sparse(adjMat);
G=digraph(adjMatS);
E=table2array(G.Edges);
As you can see I basically need the Edge-list.
Question
Hence the question: Is there a way to directly compute a sparse adjacency matrix or is there a different way of getting the Edge list from an adjacency list ?
My NB_list_all contains the points in column 1 and neighbours in column 2-5?
EDIT
My NB_list_all is an adajency list of the following form:
1 2 0
2 3 1
3 4 2
4 5 3
5 6 4
6 7 5
7 8 6
8 9 7
9 0 8
Column one the point indize and columns 2:5 the indizes of the points it is adjacent to. 0 if there is no neighbour. The matrix I want to create an Edge list for is 167620x5. I created the edge list before using the E=table2array(G.Edges); graph function of matlab. Now I basically have two questions:
How would i create a sparse adjacency matrix from this adjacency list directly?
Is there an easier way of creating an edge list for this kind of adjacency list ?
Thanks a lot!
If you know all the indexes and values, and the end size of the matrix, a sparse matrix can be created with
adjMat = sparse(indexi,indexj,value,size1,size2);
in a single go. Actually, this is the preffered way of creating a sparse matrix.
Example:
You want the following matrix:
0 1 1
1 0 0
0 0 1
you would build it as:
sparse([1 1 2 3], [2 3 1 3],[1 1 1 1],3,3)
with the example you gave:
NB_list_all=[
1 2 0
2 3 1
3 4 2
4 5 3
5 6 4
6 7 5
7 8 6
8 9 7
9 0 8];
% if the first index contains all numbers we can safely do this
% this is almost indexJ, but we have some zeroes that we dont like
indexJ=NB_list_all(:,2:end);
% create indexI
indexI=repmat(1:size(indexJ,1),size(indexJ,2),1).';
% lets unroll the matrices
indexI=indexI(:);
indexJ=indexJ(:);
% lets remove the indexI and NB_list_all that have a zero somewhere, because those are not real
notzero=find(indexJ);
indexI=indexI(notzero);
indexJ=indexJ(notzero);
adjMat=sparse(indexI,indexJ,1,size(NB_list_all,1),size(NB_list_all,1));

Apply 2D threshold to 3D array

With a geographical grid the size 20x30, I have two (temperature) variables:
The data A with the size 20x30x100
and a threshold the size 20x30
I'd like to apply the threshold to the data, i.e. to cut out the values in A that are above threshold, with every grid point having its own threshold. Since that will give a different number of values for each grid point, I thought to pad the rest with zeros, so that the resulting variable, let's call it B, will also be of the size 20x30x100.
I was thinking to do something like this, but there's something wrong with the loop:
B = sort(A,3); %// sort third dimension in ascending order
threshold_3d = repmat(threshold,1,1,100); %// make threshold into same size as B
for i=1:20
for j=1:30
if B(i,j,:) > threshold_3d(i,j,:); %// if B is above threshold
B(i,j,:); %// keep values
else
B(i,j,:) = 0; %// otherwise set to zero
end
end
end
What is the correct way to do the loop?
What other options to do this are there?
Thanks for any help!
You can use bsxfun for a much more efficient solution which will internally take care of the replication being done with repmat, like so -
B = bsxfun(#times,B,bsxfun(#gt,B,threshold))
A more efficient solution might be to use logical indexing to set the False elements from the mask created by bsxfun(gt, i.e. True ones with the use of bsxfun(#le in B to zeros thereby avoiding the use of bsxfun(#times, which for huge multidimensional arrays could be a bit expensive, like so -
B(bsxfun(#le,B,threshold)) = 0
Note on efficiency : Being a relational operation, going with the vectorized operation with bsxfun would provide both memory and runtime efficiency. The memory efficiency part has been discussed here - BSXFUN on memory efficiency with relational operations and the performance numbers have been researched here - Comparing BSXFUN and REPMAT.
Sample run -
>> B
B(:,:,1) =
8 3 9
2 8 3
B(:,:,2) =
4 1 8
4 5 6
B(:,:,3) =
4 8 5
5 6 5
>> threshold
threshold =
1 3 9
1 9 1
>> B(bsxfun(#le,B,threshold)) = 0
B(:,:,1) =
8 0 0
2 0 3
B(:,:,2) =
4 0 0
4 0 6
B(:,:,3) =
4 8 0
5 0 5

Checking values of two vectors against eachother and then using the column location of equal entries to extract colums from a matrix in matlab

I'm doing a curve fitting problem in Matlab and so far I've set up some orthonormal polynomials along a specified range of x-values with x = (0:0.0001:40);
The polynomials themselves are each a manipulation of that x vector and are stored as a row in a matrix. I also have some have data entries in the form of two vectors - one for the data x-coords and one for the actual values. I need a way to use the x-coords of my data points to find the same values in my continuous x-vector and then take the corresponding columns from my polynomial matrix and add them to a new matrix.
EDIT: To be more clear. I have, for example:
x = [0 1 2 3 4 5]
Polynomial =
1 1 1 1 1 1
0 1 2 3 4 5
0 1 4 9 16 25
% Data values:
x-coord = [1 3 4]
values = [5 3 8]
I want to check the x-coord values against 'x' to find the corresponding columns and then pull out those columns from the polynomial matrix to get:
Polynomial =
1 1 1
1 3 4
1 9 16
If your x, Polynomial, and xcoord are the same length you could use logical indexing which is elegant; something along the lines of Polynomial(x==xcoord). But since this doesn't seem to be the case, there's a less fancy solution with a for-loop and find(xcoord(i)==x)

How to convert 1D to 2D by Matlab program

I would like to ask a question about Matlab program.
I have vector a
a = [1 2 3 4 5 6 7 8 9 10 11 12];
I would like to convert vector a to 2D array. Normally, I use this code to convert it.
m =1;
for i=1:4
for j=1:3
b(i,j) = a(m);
m=m+1;
end
end
Then b is a 2D matrix.
b =
1 2 3
4 5 6
7 8 9
10 11 12
Anybody, have an idea to convert 1D to 2D without using loop.
Thanks,
Check out the reshape function and help page.
In particular,
B = reshape(A,m,n)
returns the m-by-n matrix B whose elements are taken column-wise from A. An error results if A does not have m*n elements.
Note that it is column-wise, so I suggest you make a matrix with 3 rows and 4 columns and then tip it on its side (A.' will take the transpose of a matrix).

Reconstruct matrix from diagonals in matlab

Given a vector of the counter-diagonals of a matrix in matlab, is there an easy way to reconstruct the matrix?
For example, given
x = [1 2 3 4 5 6 7 8 9]
is there any easy way to reconstruct it to the following?
1 2 4
3 5 7
6 8 9
This is made slightly easier by the fact that the dimensions of the original block are known. Reconstructing a rotation or transposition of the original matrix is fine, since rotating and transposing are easy to undo. Faster is better, this calculation has to be done on many xs.
Thanks!
You can create the corresponding Hankel matrix and use it for sorting (works only if the output is a square matrix!):
x = [1 2 3 4 5 6 7 8 9];
%# find size of output (works only with square arrays)
n=sqrt(length(x));
%# create Hankel matrix
hh = hankel(1:n,n:(2*n-1));
%# sort to get order of elements (conveniently, sort doesn't disturb ties)
[~,sortIdx]=sort(hh(:));
%# reshape and transpose
out = reshape(x(sortIdx),n,n)'; %'# SO formatting
out =
1 2 4
3 5 7
6 8 9