1

I'm trying to write a function that will check for undirected percolation in a numpy array. In this case, undirected percolation occurs when there is some kind of path that the liquid can follow (the liquid can travel up, down, and sideways, but not diagonally). Below is an example of an array that could be given to us.

1 0 1 1 0  
1 0 0 0 1
1 0 1 0 0
1 1 1 0 0
1 0 1 0 1

The result of percolation in this scenario is below.

1 0 1 1 0 
1 0 0 0 0 
1 0 1 0 0 
1 1 1 0 0 
1 0 1 0 0 

In the scenario above, the liquid could follow a path and everything with a 1 currently would refill except for the 1's in positions [1,4] and [4,4].

The function I'm trying to write starts at the top of the array and checks to see if it's a 1. If it's a 1, it writes it to a new array. What I want it to do next is check the positions above, below, left, and right of the 1 that has just been assigned.

What I currently have is below.

def flow_from(sites,full,i,j)

    n = len(sites) 

    if j>=0 and j<n and i>=0 and i<n:     #Check to see that value is in array bounds 
        if sites[i,j] == 0: 
            full[i,j] = 0
        else: 
            full[i,j] = 1 
            flow_from(sites, full, i, j + 1)
            flow_from(sites, full, i, j - 1)
            flow_from(sites, full, i + 1, j)
            flow_from(sites, full, i - 1, j) 

In this case, sites is the original matrix, for example the one shown above. New is the matrix that has been replaced with it's flow matrix. Second matrix shown. And i and j are used to iterate through.

Whenever I run this, I get an error that says "RuntimeError: maximum recursion depth exceeded in comparison." I looked into this and I don't think I need to adjust my recursion limit, but I have a feeling there's something blatantly obvious with my code that I just can't see. Any pointers?

vic
  • 21
  • 3

1 Answers1

0

Forgot about your code block. This is a known problem with a known solution from the scipy library. Adapting the code from this answer and assume your data is in an array named A.

from scipy.ndimage import measurements
# Identify the clusters
lw, num = measurements.label(A)
area = measurements.sum(A, lw, index=np.arange(lw.max() + 1))
print A
print area

This gives:

[[1 0 1 1 0]
 [1 0 0 0 1]
 [1 0 1 0 0]
 [1 1 1 0 0]
 [1 0 1 0 1]]

[[1 0 2 2 0]
 [1 0 0 0 3]
 [1 0 1 0 0]
 [1 1 1 0 0]
 [1 0 1 0 4]]

[ 0.  9.  2.  1.  1.]

That is, it's labeled all the "clusters" for you and identified the size! From here you can see that the clusters labeled 3 and 4 have size 1 which is what you want to filter away. This is a much more powerful approach because now you can filter for any size.

Community
  • 1
  • 1
Hooked
  • 84,485
  • 43
  • 192
  • 261