Repository: scipy/scipy
File: scipy/ndimage/_filters.py (Python)

Code before:

    The callback function must return an integer error status that is zero
    if something went wrong and one otherwise. If an error occurs, you should
    normally set the python error status with an informative message
    before returning, otherwise a default error message is set by the
    calling function.

    In addition, some other low-level function pointer specifications
    are accepted, but these are for backward compatibility only and should
    not be used in new code.

    Examples
    --------
    Apply a custom one-dimensional filter to an array.

    The filtering function operates on one-dimensional input and output
    lines and must modify the output in-place.

    >>> import numpy as np
    >>> from scipy.ndimage import generic_filter1d

    >>> def local_range(input_line, output_line):
    ...     # input_line includes padded values according to `filter_size` and `mode`
    ...     for i in range(len(output_line)):
    ...         window = input_line[i:i + 3]
    ...         output_line[i] = window.max() - window.min()

    >>> x = np.array([1, 2, 3, 4, 5], dtype=np.float64)
    >>> generic_filter1d(x, local_range, filter_size=3)
    array([1., 2., 2., 2., 1.])

    """
    if extra_keywords is None:
        extra_keywords = {}
    input = np.asarray(input)
    if np.iscomplexobj(input):
        raise TypeError('Complex type not supported')
    output = _ni_support._get_output(output, input)
    if filter_size < 1:
        raise RuntimeError('invalid filter size')
    axis = normalize_axis_index(axis, input.ndim)
    if (filter_size // 2 + origin < 0) or (filter_size // 2 + origin >=
                                           filter_size):
        raise ValueError('invalid origin')
    mode = _ni_support._extend_mode_to_code(mode)
    _nd_image.generic_filter1d(input, function, filter_size, axis, output,
                               mode, cval, origin, extra_arguments,
                               extra_keywords)
    return output



Review comment (suggestion):
This should use `sliding_window_view` rather than a for loop. Something along the lines of

```
In [1]: from numpy.lib.stride_tricks import sliding_window_view

In [2]: x = np.array([1, 2, 3, 4, 5], dtype=np.float64)

In [3]: v = sliding_window_view(x, 3)

In [4]: v.max()
Out[4]: np.float64(5.0)

In [5]: v.max(axis=1)
Out[5]: array([3., 4., 5.])

In [6]: v
Out[6]: 
array([[1., 2., 3.],
       [2., 3., 4.],
       [3., 4., 5.]])

In [7]: v.max(axis=1) - v.min(axis=1)
Out[7]: array([2., 2., 2.])
```

Code after:

    The callback function must return an integer error status that is zero
    if something went wrong and one otherwise. If an error occurs, you should
    normally set the python error status with an informative message
    before returning, otherwise a default error message is set by the
    calling function.

    In addition, some other low-level function pointer specifications
    are accepted, but these are for backward compatibility only and should
    not be used in new code.

    Examples
    --------
    This example defines and applies a custom callback function that computes
    the range (maximum minus minimum) within a sliding window of size 3.
    It utilizes `numpy.lib.stride_tricks.sliding_window_view` and demonstrates the
    required in-place modification of the ``output_line`` array.

    >>> import numpy as np
    >>> from scipy.ndimage import generic_filter1d
    >>> from numpy.lib.stride_tricks import sliding_window_view

    >>> def local_range(input_line, output_line):
    ...     # input_line includes padded values according to `filter_size` and `mode`
    ...     v = sliding_window_view(input_line, 3)
    ...     # modify `output_line` in-place rather than returning the result
    ...     output_line[:] = v.max(axis=1) - v.min(axis=1)

    >>> x = np.array([1, 2, 3, 4, 5], dtype=np.float64)
    >>> generic_filter1d(x, local_range, filter_size=3)
    array([1., 2., 2., 2., 1.])

    """
    if extra_keywords is None:
        extra_keywords = {}
    input = np.asarray(input)
    if np.iscomplexobj(input):
        raise TypeError('Complex type not supported')
    output = _ni_support._get_output(output, input)
    if filter_size < 1:
        raise RuntimeError('invalid filter size')
    axis = normalize_axis_index(axis, input.ndim)
    if (filter_size // 2 + origin < 0) or (filter_size // 2 + origin >=
                                           filter_size):
        raise ValueError('invalid origin')
    mode = _ni_support._extend_mode_to_code(mode)
    _nd_image.generic_filter1d(input, function, filter_size, axis, output,
                               mode, cval, origin, extra_arguments,
                               extra_keywords)
    return output