for loop only through certain elements of an array

Hello all,
I would like to do this more time efficiently. Lets say I have a 4D (xn,yn,zn,N) data array and a 3D (xn,yn,zn) mask array. I would like to go through 4D array and calculate something from the numbers in the 4th dimension, but I want only elements from the mask. Is there a way of doing this more efficiently, than going through xn*yn*zn elements and checking if they are withing the mask?
This is the brute force way:
for x=1:xn
for y=1:yn
for z=1:zn
if mask(x,y,z)==1
do something with data(x,y,z,:);
end
end
end
end
Thank you.
Edit: I think I need to explain the task at hand better. The 4D data is several 3D images combined along the 4th dimension, which corresponds to certain image acquisition parameters. I want to do
f=fit(Par, data(x,y,z,:), 'exp1');
for each image voxel from the mask.

6 comentarios

Adam
Adam el 22 de Nov. de 2017
You can just do a find on your mask, store the indices and loop over only those instead. A lot depends on the density of 1s in the mask as to how fast one approach would be over another.
Greg
Greg el 22 de Nov. de 2017
Depending on the something you're calculating, you could set all masked values to NaN. Many statistics functions (min, max, mean, etc.) have the 'omitnan' flag.
Renat
Renat el 22 de Nov. de 2017
Adam: I thought of that, but doing find will return a 1-D array of indices. I dont know how to access elements in 3D array with 1D indices.
Greg: Please see edited question. I am doing an exponential fit.
Greg
Greg el 22 de Nov. de 2017
Editada: Greg el 22 de Nov. de 2017
"I dont know how to access elements in 3D array with 1D indices." -- You just do it.
a = cat(3,[1,3;2,4],[5,7;6,8]);
b = a(7);
The value of "b" is the seventh element of "a" - 7. Look up MATLAB's documentation on Linear Indexing, as well as functions like sub2ind.
Also, I'm not an expert in exponential fits. Would NaN values skew the result of the fit?
Renat
Renat el 23 de Nov. de 2017
Wow, so simple and straightforward. Thank you, Adam and Greg. This will do it, and will make my life easier in the future!
So you're doing something like this:
for k = 1 : xn*yn*zn
if mask(k)
% do something with data(x,y,z,:);
% Now need x, y, and z so need to use ind2sub().
[x, y, z] = ind2sub(size(data), k);
thisData = data(x, y, z);
end
end
Note that arrays not not normally indexed as (x, y, z) though. They're indexed (row, column, z) which is (y, x, z). So the above code just assumes that x is the row, which is fine, just realize that it's not the x as you usually think of it.

Iniciar sesión para comentar.

Respuestas (1)

Image Analyst
Image Analyst el 22 de Nov. de 2017
Try looping over the 4th dimension
for n = 1 : N
this3DArray = data(:,:,:,n);
dataOnlyWithInMask = this3DArray(mask); % 1-D vector.
% Now do something with dataOnlyWithInMask .
end

2 comentarios

Renat
Renat el 22 de Nov. de 2017
Please see additional information. This wont work, as I am fitting data(x,y,z,:).
If it's something like a video where you have color images, and then a bunch of them over time, then you need to extract just one pixel's color channel over time. So you'd do this:
redChannelOverTime = squeeze(data(y, x, 1, :));
Note how y and x area flipped because y is rows which is the first index. I think this will provide a 1-D array along the time dimension. Then do whatever fitting you want to it.

Iniciar sesión para comentar.

Categorías

Preguntada:

el 22 de Nov. de 2017

Comentada:

el 23 de Nov. de 2017

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by