<gh_stars>0
import numpy as np
from numpy.lib.stride_tricks import as_strided
from numba import njit
from sklearn.utils import check_array


def segmentation(ts_size, window_size, overlapping=False, n_segments=None):
    """Compute the indices for Piecewise Agrgegate Approximation.

    Parameters
    ----------
    ts_size : int
        The size of the time series.

    window_size : int
        The size of the window.

    overlapping : bool (default = False)
        If True, overlapping windows may be used. If False, non-overlapping
        are used.

    n_segments : int or None (default = None)
        The number of windows. If None, the number is automatically
        computed using ``window_size``.

    Returns
    -------
    start : array
        The lower bound for each window.

    end : array
        The upper bound for each window.

    size : int
        The size of ``start``.

    Examples
    --------
    >>> from pyts.utils import segmentation
    >>> start, end, size = segmentation(ts_size=12, window_size=3)
    >>> print(start)
    [0 3 6 9]
    >>> print(end)
    [ 3  6  9 12]
    >>> size
    4

    """
    if not isinstance(ts_size, (int, np.integer)):
        raise TypeError("'ts_size' must be an integer.")
    if not ts_size >= 2:
        raise ValueError(
            "'ts_size' must be an integer greater than or equal "
            "to 2 (got {0}).".format(ts_size)
        )
    if not isinstance(window_size, (int, np.integer)):
        raise TypeError("'window_size' must be an integer.")
    if not window_size >= 1:
        raise ValueError(
            "'window_size' must be an integer greater than or "
            "equal to 1 (got {0}).".format(window_size)
        )
    if not window_size <= ts_size:
        raise ValueError(
            "'window_size' must be lower than or equal to "
            "'ts_size' ({0} > {1}).".format(window_size, ts_size)
        )
    if not (n_segments is None or isinstance(n_segments, (int, np.integer))):
        raise TypeError("'n_segments' must be None or an integer.")
    if isinstance(n_segments, (int, np.integer)):
        if not n_segments >= 2:
            raise ValueError(
                "If 'n_segments' is an integer, it must be greater than or "
                "equal to 2 (got {0}).".format(n_segments)
            )
        if not n_segments <= ts_size:
            raise ValueError(
                "If 'n_segments' is an integer, it must be lower than or "
                "equal to 'ts_size' ({0} > {1}).".format(n_segments, ts_size)
            )

    if n_segments is None:
        quotient, remainder = divmod(ts_size, window_size)
        n_segments = quotient if remainder == 0 else quotient + 1

    if not overlapping:
        bounds = np.linspace(0, ts_size, n_segments + 1).astype("int64")
        start = bounds[:-1]
        end = bounds[1:]
        size = start.size
        return start, end, size
    else:
        n_overlapping = (n_segments * window_size) - ts_size
        n_overlaps = n_segments - 1
        overlaps = np.linspace(0, n_overlapping, n_overlaps + 1).astype("int64")
        bounds = np.arange(0, (n_segments + 1) * window_size, window_size)
        start = bounds[:-1] - overlaps
        end = bounds[1:] - overlaps
        size = start.size
        return start, end, size


@njit()
def _windowed_view(X, n_samples, n_timestamps, window_size, window_step):
    overlap = window_size - window_step
    shape_new = (n_samples, (n_timestamps - overlap) // window_step, window_size // 1)
    s0, s1 = X.strides
    strides_new = (s0, window_step * s1, s1)
    return as_strided(X, shape=shape_new, strides=strides_new)


def windowed_view(X, window_size, window_step=1):
    """Return a windowed view of a 2D array.

    Parameters
    ----------
    X : array-like, shape = (n_samples, n_timestamps)
        Input data.

    window_size : int
        The size of the window. It must be between 1 and ``n_timestamps``.

    window_step : int (default = 1)
        The step of the sliding window

    Returns
    -------
    X_new : array, shape = (n_samples, n_windows, window_size)
        Windowed view of the input data. ``n_windows`` is computed as
        ``(n_timestamps - window_size + window_step) // window_step``.

    Examples
    --------
    >>> import numpy as np
    >>> from pyts.utils import windowed_view
    >>> windowed_view(np.arange(6).reshape(1, -1), window_size=2)
    array([[[0, 1],
            [1, 2],
            [2, 3],
            [3, 4],
            [4, 5]]])

    """
    X = check_array(X, dtype=None)
    n_samples, n_timestamps = X.shape

    if not isinstance(window_size, (int, np.integer)):
        raise TypeError("'window_size' must be an integer.")
    if not 1 <= window_size <= n_timestamps:
        raise ValueError(
            "'window_size' must be an integer between 1 and " "n_timestamps."
        )
    if not isinstance(window_step, (int, np.integer)):
        raise TypeError("'window_step' must be an integer.")
    if not 1 <= window_step <= n_timestamps:
        raise ValueError(
            "'window_step' must be an integer between 1 and " "n_timestamps."
        )

    return _windowed_view(X, n_samples, n_timestamps, window_size, window_step)


def rolling_window(a, window):
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

import numpy as np
from numpy.lib.stride_tricks import as_strided
from numba import njit
from sklearn.utils import check_array


def segmentation(ts_size, window_size, overlapping=False, n_segments=None):
    """Compute the indices for Piecewise Agrgegate Approximation.

    Parameters
    ----------
    ts_size : int
        The size of the time series.

    window_size : int
        The size of the window.

    overlapping : bool (default = False)
        If True, overlapping windows may be used. If False, non-overlapping
        are used.

    n_segments : int or None (default = None)
        The number of windows. If None, the number is automatically
        computed using ``window_size``.

    Returns
    -------
    start : array
        The lower bound for each window.

    end : array
        The upper bound for each window.

    size : int
        The size of ``start``.

    Examples
    --------
    >>> from pyts.utils import segmentation
    >>> start, end, size = segmentation(ts_size=12, window_size=3)
    >>> print(start)
    [0 3 6 9]
    >>> print(end)
    [ 3  6  9 12]
    >>> size
    4

    """
    if not isinstance(ts_size, (int, np.integer)):
        raise TypeError("'ts_size' must be an integer.")
    if not ts_size >= 2:
        raise ValueError(
            "'ts_size' must be an integer greater than or equal "
            "to 2 (got {0}).".format(ts_size)
        )
    if not isinstance(window_size, (int, np.integer)):
        raise TypeError("'window_size' must be an integer.")
    if not window_size >= 1:
        raise ValueError(
            "'window_size' must be an integer greater than or "
            "equal to 1 (got {0}).".format(window_size)
        )
    if not window_size <= ts_size:
        raise ValueError(
            "'window_size' must be lower than or equal to "
            "'ts_size' ({0} > {1}).".format(window_size, ts_size)
        )
    if not (n_segments is None or isinstance(n_segments, (int, np.integer))):
        raise TypeError("'n_segments' must be None or an integer.")
    if isinstance(n_segments, (int, np.integer)):
        if not n_segments >= 2:
            raise ValueError(
                "If 'n_segments' is an integer, it must be greater than or "
                "equal to 2 (got {0}).".format(n_segments)
            )
        if not n_segments <= ts_size:
            raise ValueError(
                "If 'n_segments' is an integer, it must be lower than or "
                "equal to 'ts_size' ({0} > {1}).".format(n_segments, ts_size)
            )

    if n_segments is None:
        quotient, remainder = divmod(ts_size, window_size)
        n_segments = quotient if remainder == 0 else quotient + 1

    if not overlapping:
        bounds = np.linspace(0, ts_size, n_segments + 1).astype("int64")
        start = bounds[:-1]
        end = bounds[1:]
        size = start.size
        return start, end, size
    else:
        n_overlapping = (n_segments * window_size) - ts_size
        n_overlaps = n_segments - 1
        overlaps = np.linspace(0, n_overlapping, n_overlaps + 1).astype("int64")
        bounds = np.arange(0, (n_segments + 1) * window_size, window_size)
        start = bounds[:-1] - overlaps
        end = bounds[1:] - overlaps
        size = start.size
        return start, end, size


@njit()
def _windowed_view(X, n_samples, n_timestamps, window_size, window_step):
    overlap = window_size - window_step
    shape_new = (n_samples, (n_timestamps - overlap) // window_step, window_size // 1)
    s0, s1 = X.strides
    strides_new = (s0, window_step * s1, s1)
    return as_strided(X, shape=shape_new, strides=strides_new)


def windowed_view(X, window_size, window_step=1):
    """Return a windowed view of a 2D array.

    Parameters
    ----------
    X : array-like, shape = (n_samples, n_timestamps)
        Input data.

    window_size : int
        The size of the window. It must be between 1 and ``n_timestamps``.

    window_step : int (default = 1)
        The step of the sliding window

    Returns
    -------
    X_new : array, shape = (n_samples, n_windows, window_size)
        Windowed view of the input data. ``n_windows`` is computed as
        ``(n_timestamps - window_size + window_step) // window_step``.

    Examples
    --------
    >>> import numpy as np
    >>> from pyts.utils import windowed_view
    >>> windowed_view(np.arange(6).reshape(1, -1), window_size=2)
    array([[[0, 1],
            [1, 2],
            [2, 3],
            [3, 4],
            [4, 5]]])

    """
    X = check_array(X, dtype=None)
    n_samples, n_timestamps = X.shape

    if not isinstance(window_size, (int, np.integer)):
        raise TypeError("'window_size' must be an integer.")
    if not 1 <= window_size <= n_timestamps:
        raise ValueError(
            "'window_size' must be an integer between 1 and " "n_timestamps."
        )
    if not isinstance(window_step, (int, np.integer)):
        raise TypeError("'window_step' must be an integer.")
    if not 1 <= window_step <= n_timestamps:
        raise ValueError(
            "'window_step' must be an integer between 1 and " "n_timestamps."
        )

    return _windowed_view(X, n_samples, n_timestamps, window_size, window_step)


def rolling_window(a, window):
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)
Compute the indices for Piecewise Agrgegate Approximation.      Parameters     ----------     ts_size : int         The size of the time series.      window_size : int         The size of the window.      overlapping : bool (default = False)         If True, overlapping windows may be used. If False, non-overlapping         are used.      n_segments : int or None (default = None)         The number of windows. If None, the number is automatically         computed using ``window_size``.      Returns     -------     start : array         The lower bound for each window.      end : array         The upper bound for each window.      size : int         The size of ``start``.      Examples     --------     >>> from pyts.utils import segmentation     >>> start, end, size = segmentation(ts_size=12, window_size=3)     >>> print(start)     [0 3 6 9]     >>> print(end)     [ 3  6  9 12]     >>> size     4 Return a windowed view of a 2D array.      Parameters     ----------     X : array-like, shape = (n_samples, n_timestamps)         Input data.      window_size : int         The size of the window. It must be between 1 and ``n_timestamps``.      window_step : int (default = 1)         The step of the sliding window      Returns     -------     X_new : array, shape = (n_samples, n_windows, window_size)         Windowed view of the input data. ``n_windows`` is computed as         ``(n_timestamps - window_size + window_step) // window_step``.      Examples     --------     >>> import numpy as np     >>> from pyts.utils import windowed_view     >>> windowed_view(np.arange(6).reshape(1, -1), window_size=2)     array([[[0, 1],             [1, 2],             [2, 3],             [3, 4],             [4, 5]]])