How to count the number of holes in a numpy 2D grid?

numpy, python, scipy

Solution

You can use scipy.ndimage.measurements.label() to count contiguous areas, and numpy.isnan() to get a mask of the nodata values only. Example:

>>> a = numpy.zeros( (5, 5) )
>>> a[0,0] = numpy.NaN
>>> a[3,3:5] = numpy.NaN
>>> a
array([[ nan,   0.,   0.,   0.,   0.],
       [  0.,   0.,   0.,   0.,   0.],
       [  0.,   0.,   0.,   0.,   0.],
       [  0.,   0.,   0.,  nan,  nan],
       [  0.,   0.,   0.,   0.,   0.]])
>>> labels, num_labels = scipy.ndimage.measurements.label ( numpy.isnan( a ) )
>>> labels
array([[1, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 2, 2],
       [0, 0, 0, 0, 0]])
>>> num_labels
2

This assumes that by "contiguous" you mean "located in adjacent cells in the grid" rather than "having adjacent values".

P.S. This works in any number of dimensions, check the docs for the label function to see how to specify the structuring element for adjacency in multiple dimensions.

Problem

I have good sized numpy 2D float grids (e.g. > 20k x 10k cells). I'd like to count the number of contiguous groups of the nodata values in the grid. I could implement a simple pain fill method in python, but it seems like there must be way to do this efficiently in numpy or scipy, but I'm not finding an obvious approach with ndimage. I was thinking that there must be a way to count patches and I can just create a binary grid and count the patches that correspond to nodata. Is it possible to do this with scipy's fcluster?

Original source