On Nov 29, 10:11 am, Rob <rj...@le.ac.uk> wrote:
> I was hoping that there was a nice way to do the following. I have a
> 4D array and I want to check if the 4th dimension contains a 0 in any
> of it's values for each value of the other 3 dimensions, if it does I
> want that whole column set to 0.
>
> This is how I'm doing it with a loop:
>
> FOR i=0, 1 DO BEGIN
> FOR k = 0, 359 DO BEGIN
> FOR j = 0, 5 DO BEGIN
> test = where(array[i,j,k,*] eq 0)
> IF max(test) gt -1 THEN array[i,j,k,*] = 0
> ENDFOR
> ENDFOR
> ENDFOR
>
> which is obviously horrible and slow.
>
> Any help/advice would be great.
>
> Thanks
>
> Rob
Interesting problem, which really depends a lot on the size of the 4th
dimension, and the number of expected zeros in the array.
(1) The original loop is better like this.
FOR k = 0, 359 DO FOR j = 0, 5 DO FOR i=0,1 DO $
IF (total(array[i,j,k,*]) gt 0) THEN array[i,j,k,*] = 0
Here, we write it as a one-liner (no BEGIN/END), which is usually
slightly faster in IDL. Also we avoid WHERE/MAX, and use instead
TOTAL, which is very fast.
(2) If the number of zeros in the array is low, this one should be
fast.
ind = where(array eq 0, count)
if (count gt 0) then begin
dim = size(array, /dimensions)
nrow = dim[0]*dim[1]*dim[2]
ind mod= nrow
ind = ind[uniq(ind[sort(ind)])] ; Unique rows containing zeros
ind = array_indices(array,ind)
for i=0L,n_elements(ind[0,*])-1 do
array[ind[0,i],ind[1,i],ind[2,i],*]=0
endif
(3) Since you are operating only on one dimension, it should really be
the first one for efficiency reasons. So it is better to actually keep
the data stored that way. If that is not possible, a transpose before
and after the operation might help you:
array = transpose(temporary(array), [3,0,1,2]) ; Or keep the array
like this in the first place
dim = size(array, /dimensions)
nrow = dim[1]*dim[2]*dim[3]
array = reform(array, dim[0], nrow)
for ii=0L, nrow-1 do if (total(A[*,ii] eq 0) gt 0) then A[*,ii] = 0
array = reform(array, dim)
array = transpose(temporary(array), [1,2,3,0])
--
Yngvar
|