I have a 3D array, for example:
array = np.array([[[ 1., 1., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]],
[[1., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]],
[[ 1., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]]])
I need to find the runs of conected ones for each possible size for different directions. For example, in the direction (1,0,0), horitzontal direction, the output should be:
> **Runs of size 1: 2
> **Runs of size 2: 1
> **Runs of size 3: 0
On the direction (0, 1, 0), accross the vertical axis:
> **Runs of size 1: 4
> **Runs of size 2: 0
> **Runs of size 3: 0
And in the direction (0, 0, 1), accross the z axis:
> **Runs of size 1: 1
> **Runs of size 2: 0
> **Runs of size 3: 1
Is there an effective way to implement this?
EDIT:
I attach the solution I am working on:
dire = np.array(([1, 0, 0], [0, 1, 0], [0, 0, 1])) # Possible directions
results = np.zeros((array.shape[0], len(dire))) # Maximum runs will be 3
# Find all indices
indices = np.argwhere(array == 1)
# Loop over each direction
for idire, dire in enumerate(dire):
results[0, idire] = np.count_nonzero(array) # Count all 1 (conection 0)
indices_to_compare = indices
# Now we compare the list of indices with a displaced list of indices
for irun in range(1, array.shape[0]):
indices_displaced = indices + dire*irun
aset = set([tuple(x) for x in indices_displaced])
bset = set([tuple(x) for x in indices_to_compare])
indices_to_compare = (np.array([x for x in aset & bset]))
results[irun, idire] = len(indices_to_compare)
# Rest the counts off bigger runs to the smaller ones, for duplicates
for indx in np.arange(array.shape[0]-2,-1,-1):
results[indx, idire] -=
np.sum(results[np.arange(array.shape[0]-1,indx,-1), idire])
print(results) # Each column is a direction, each row is the number of bins.
> [[ 2. 4. 3.]
[ 1. 0. 1.]
[ 1. 0. 0.]]
So far this code does not work, only for the direction (0,1,0), which does not have any connection and it is trivial. With this notation, the expected output should be:
> [[ 2. 4. 1.]
[ 1. 0. 0.]
[ 0. 0. 1.]]
The comparision of the arrays is from this link.
EDIT 2:
I had a mistake in the interpretation of the coordinates, it seems that addint to the results of np.argwhere
, (1,0,0) is over the z axist, so the expected result should be:
> [[ 1. 4. 2.]
[ 0. 0. 1.]
[ 1. 0. 0.]]