@exporter.export
@preprocess_xarray
def find_bounding_indices(arr, values, axis, from_below=True):
    'Find the indices surrounding the values within arr along axis.\n\n    Returns a set of above, below, good. Above and below are lists of arrays of indices.\n    These lists are formulated such that they can be used directly to index into a numpy\n    array and get the expected results (no extra slices or ellipsis necessary). `good` is\n    a boolean array indicating the "columns" that actually had values to bound the desired\n    value(s).\n\n    Parameters\n    ----------\n    arr : array-like\n        Array to search for values\n\n    values: array-like\n        One or more values to search for in `arr`\n\n    axis : int\n        The dimension of `arr` along which to search.\n\n    from_below : bool, optional\n        Whether to search from "below" (i.e. low indices to high indices). If `False`,\n        the search will instead proceed from high indices to low indices. Defaults to `True`.\n\n    Returns\n    -------\n    above : list of arrays\n        List of broadcasted indices to the location above the desired value\n\n    below : list of arrays\n        List of broadcasted indices to the location below the desired value\n\n    good : array\n        Boolean array indicating where the search found proper bounds for the desired value\n\n    '
    indices_shape = list(arr.shape)
    indices_shape[axis] = len(values)
    indices = np.empty(indices_shape, dtype=np.int)
    good = np.empty(indices_shape, dtype=np.bool)
    store_slice = ([slice(None)] * arr.ndim)
    for (level_index, value) in enumerate(values):
        switches = np.abs(np.diff((arr <= value).astype(np.int), axis=axis))
        good_search = np.any(switches, axis=axis)
        if from_below:
            index = (switches.argmax(axis=axis) + 1)
        else:
            arr_slice = ([slice(None)] * arr.ndim)
            arr_slice[axis] = slice(None, None, (- 1))
            index = ((arr.shape[axis] - 1) - switches[tuple(arr_slice)].argmax(axis=axis))
        index[(~ good_search)] = 0
        store_slice[axis] = level_index
        indices[tuple(store_slice)] = index
        good[tuple(store_slice)] = good_search
    above = broadcast_indices(arr, indices, arr.ndim, axis)
    below = broadcast_indices(arr, (indices - 1), arr.ndim, axis)
    return (above, below, good)
Find the indices surrounding the values within arr along axis.

Returns a set of above, below, good. Above and below are lists of arrays of indices.
These lists are formulated such that they can be used directly to index into a numpy
array and get the expected results (no extra slices or ellipsis necessary). `good` is
a boolean array indicating the "columns" that actually had values to bound the desired
value(s).

Parameters
----------
arr : array-like
    Array to search for values

values: array-like
    One or more values to search for in `arr`

axis : int
    The dimension of `arr` along which to search.

from_below : bool, optional
    Whether to search from "below" (i.e. low indices to high indices). If `False`,
    the search will instead proceed from high indices to low indices. Defaults to `True`.

Returns
-------
above : list of arrays
    List of broadcasted indices to the location above the desired value

below : list of arrays
    List of broadcasted indices to the location below the desired value

good : array
    Boolean array indicating where the search found proper bounds for the desired value
@exporter.export
@preprocess_xarray
def find_bounding_indices(arr, values, axis, from_below=True):
    'Find the indices surrounding the values within arr along axis.\n\n    Returns a set of above, below, good. Above and below are lists of arrays of indices.\n    These lists are formulated such that they can be used directly to index into a numpy\n    array and get the expected results (no extra slices or ellipsis necessary). `good` is\n    a boolean array indicating the "columns" that actually had values to bound the desired\n    value(s).\n\n    Parameters\n    ----------\n    arr : array-like\n        Array to search for values\n\n    values: array-like\n        One or more values to search for in `arr`\n\n    axis : int\n        The dimension of `arr` along which to search.\n\n    from_below : bool, optional\n        Whether to search from "below" (i.e. low indices to high indices). If `False`,\n        the search will instead proceed from high indices to low indices. Defaults to `True`.\n\n    Returns\n    -------\n    above : list of arrays\n        List of broadcasted indices to the location above the desired value\n\n    below : list of arrays\n        List of broadcasted indices to the location below the desired value\n\n    good : array\n        Boolean array indicating where the search found proper bounds for the desired value\n\n    '
    indices_shape = list(arr.shape)
    indices_shape[axis] = len(values)
    indices = np.empty(indices_shape, dtype=np.int)
    good = np.empty(indices_shape, dtype=np.bool)
    store_slice = ([slice(None)] * arr.ndim)
    for (level_index, value) in enumerate(values):
        switches = np.abs(np.diff((arr <= value).astype(np.int), axis=axis))
        good_search = np.any(switches, axis=axis)
        if from_below:
            index = (switches.argmax(axis=axis) + 1)
        else:
            arr_slice = ([slice(None)] * arr.ndim)
            arr_slice[axis] = slice(None, None, (- 1))
            index = ((arr.shape[axis] - 1) - switches[tuple(arr_slice)].argmax(axis=axis))
        index[(~ good_search)] = 0
        store_slice[axis] = level_index
        indices[tuple(store_slice)] = index
        good[tuple(store_slice)] = good_search
    above = broadcast_indices(arr, indices, arr.ndim, axis)
    below = broadcast_indices(arr, (indices - 1), arr.ndim, axis)
    return (above, below, good)