Given an ordered array of values, generate a set of slices that traverse
    all of the values. Each slice contains about `target_len` items. However,
    no slice contains a gap larger than `maxgap`, so a slice may contain only
    a single item (if it is surrounded on both sides by a large gap). If a
    non-gapped run of values does not divide evenly into `target_len`, the
    algorithm errs on the side of making the slices contain more than
    `target_len` items, rather than fewer. It also attempts to keep the slice
    size uniform within each non-gapped run.

def slice_evenly_with_gaps (values, target_len, maxgap):
    """Given an ordered array of values, generate a set of slices that traverse
    all of the values. Each slice contains about `target_len` items. However,
    no slice contains a gap larger than `maxgap`, so a slice may contain only
    a single item (if it is surrounded on both sides by a large gap). If a
    non-gapped run of values does not divide evenly into `target_len`, the
    algorithm errs on the side of making the slices contain more than
    `target_len` items, rather than fewer. It also attempts to keep the slice
    size uniform within each non-gapped run.

    """
    if not (target_len > 0):
        raise ValueError ('target_len must be positive; got %r' % target_len)

    values = np.asarray (values)
    l = values.size

    for gapslice in slice_around_gaps (values, maxgap):
        start, stop, ignored_stride = gapslice.indices (l)
        num_elements = stop - start
        nsegments = int (np.floor (float (num_elements) / target_len))
        nsegments = max (nsegments, 1)
        nsegments = min (nsegments, num_elements)
        segment_len = num_elements / nsegments
        offset = 0.
        prev = start

        for _ in range (nsegments):
            offset += segment_len
            next = start + int (round (offset))
            if next > prev:
                yield slice (prev, next)
            prev = next