def unmasked_index_ranges(mask, compressed = True):
mask = mask.reshape(mask.size)<EOL>m = np.concatenate(((<NUM_LIT:1>,), mask, (<NUM_LIT:1>,)))<EOL>indices = np.arange(len(mask) + <NUM_LIT:1>)<EOL>mdif = m[<NUM_LIT:1>:] - m[:-<NUM_LIT:1>]<EOL>i0 = np.compress(mdif == -<NUM_LIT:1>, indices)<EOL>i1 = np.compress(mdif == <NUM_LIT:1>, indices)<EOL>assert len(i0) == len(i1)<EOL>if len(i1) == <NUM_LIT:0>:<EOL><INDENT>return None  <EOL><DEDENT>if not compressed:<EOL><INDENT>return np.concatenate((i0[:, np.newaxis], i1[:, np.newaxis]), axis=<NUM_LIT:1>)<EOL><DEDENT>seglengths = i1 - i0<EOL>breakpoints = np.cumsum(seglengths)<EOL>ic0 = np.concatenate(((<NUM_LIT:0>,), breakpoints[:-<NUM_LIT:1>]))<EOL>ic1 = breakpoints<EOL>return np.concatenate((ic0[:, np.newaxis], ic1[:, np.newaxis]), axis=<NUM_LIT:1>)<EOL>
Find index ranges where *mask* is *False*.

*mask* will be flattened if it is not already 1-D.

Returns Nx2 :class:`numpy.ndarray` with each row the start and stop
indices for slices of the compressed :class:`numpy.ndarray`
corresponding to each of *N* uninterrupted runs of unmasked
values.  If optional argument *compressed* is *False*, it returns
the start and stop indices into the original :class:`numpy.ndarray`,
not the compressed :class:`numpy.ndarray`.  Returns *None* if there
are no unmasked values.

Example::

  y = ma.array(np.arange(5), mask = [0,0,1,0,0])
  ii = unmasked_index_ranges(ma.getmaskarray(y))
  # returns array [[0,2,] [2,4,]]

  y.compressed()[ii[1,0]:ii[1,1]]
  # returns array [3,4,]

  ii = unmasked_index_ranges(ma.getmaskarray(y), compressed=False)
  # returns array [[0, 2], [3, 5]]

  y.filled()[ii[1,0]:ii[1,1]]
  # returns array [3,4,]

Prior to the transforms refactoring, this was used to support
masked arrays in Line2D.