Beispiel #1
0
    def _update(self, t):
        """
        Ingress a new data point and update the matrix profile and matrix profile
        indices without egressing the oldest data point
        """
        self._n = self._T.shape[0]
        l = self._n - self._m + 1
        T_new = np.append(self._T, t)
        QT_new = np.empty(self._QT.shape[0] + 1)
        S = T_new[l:]
        t_drop = T_new[l - 1]

        if np.isfinite(t):
            self._T_isfinite = np.append(self._T_isfinite, True)
        else:
            self._T_isfinite = np.append(self._T_isfinite, False)
            t = 0
            T_new[-1] = 0
            S[-1] = 0

        self._T_subseq_isfinite = np.append(
            self._T_subseq_isfinite, np.all(self._T_isfinite[-self._m:]))

        QT_new[1:] = self._QT[:l] - T_new[:l] * t_drop + T_new[self._m:] * t
        QT_new[0] = np.sum(T_new[:self._m] * S[:self._m])

        Q_squared = np.sum(S * S)
        self._T_squared = np.append(
            self._T_squared, np.sum(T_new[-self._m:] * T_new[-self._m:]))
        D = core._mass_absolute(Q_squared, self._T_squared, QT_new)
        D[~self._T_subseq_isfinite] = np.inf
        if np.any(~self._T_isfinite[-self._m:]):
            D[:] = np.inf

        core.apply_exclusion_zone(D, D.shape[0] - 1, self._excl_zone)

        update_idx = np.argwhere(D[:l] < self._P[:l]).flatten()
        self._I[update_idx] = l
        self._P[update_idx] = D[update_idx]

        I_last = np.argmin(D)
        if np.isinf(D[I_last]):
            I_new = np.append(self._I, -1)
            P_new = np.append(self._P, np.inf)
        else:
            I_new = np.append(self._I, I_last)
            P_new = np.append(self._P, D[I_last])
        left_I_new = np.append(self._left_I, I_last)
        left_P_new = np.append(self._left_P, D[I_last])

        self._T = T_new
        self._P = P_new
        self._I = I_new
        self._left_I = left_I_new
        self._left_P = left_P_new
        self._QT = QT_new
Beispiel #2
0
def test_apply_exclusion_zone():
    T = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=float)
    left = np.empty(T.shape)
    right = np.empty(T.shape)
    exclusion_zone = 2

    for i in range(T.shape[0]):
        left[:] = T[:]
        naive.apply_exclusion_zone(left, i, exclusion_zone)

        right[:] = T[:]
        core.apply_exclusion_zone(right, i, exclusion_zone)

        naive.replace_inf(left)
        naive.replace_inf(right)
        npt.assert_array_equal(left, right)
Beispiel #3
0
def test_apply_exclusion_zone():
    T = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=float)
    ref = np.empty(T.shape)
    comp = np.empty(T.shape)
    exclusion_zone = 2

    for i in range(T.shape[0]):
        ref[:] = T[:]
        naive.apply_exclusion_zone(ref, i, exclusion_zone)

        comp[:] = T[:]
        core.apply_exclusion_zone(comp, i, exclusion_zone)

        naive.replace_inf(ref)
        naive.replace_inf(comp)
        npt.assert_array_equal(ref, comp)
Beispiel #4
0
def test_apply_exclusion_zone_bool():
    T = np.ones(10, dtype=bool)
    ref = np.empty(T.shape, dtype=bool)
    comp = np.empty(T.shape, dtype=bool)
    exclusion_zone = 2

    for i in range(T.shape[0]):
        ref[:] = T[:]
        naive.apply_exclusion_zone(ref, i, exclusion_zone, False)

        comp[:] = T[:]
        core.apply_exclusion_zone(comp, i, exclusion_zone, False)

        naive.replace_inf(ref)
        naive.replace_inf(comp)
        npt.assert_array_equal(ref, comp)
Beispiel #5
0
def test_apply_exclusion_zone():
    T = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=float)
    left = np.empty(T.shape)
    right = np.empty(T.shape)
    exclusion_zone = 2

    for i in range(T.shape[0]):
        left[:] = T[:]
        for j in range(max(i - exclusion_zone, 0),
                       min(i + exclusion_zone + 1, T.shape[0])):
            left[j] = np.inf

        right[:] = T[:]
        core.apply_exclusion_zone(right, i, exclusion_zone)

        utils.replace_inf(left)
        utils.replace_inf(right)
        npt.assert_array_equal(left, right)
Beispiel #6
0
def test_apply_exclusion_zone_multidimensional():
    T = np.array(
        [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]],
        dtype=np.float64,
    )
    ref = np.empty(T.shape, dtype=np.float64)
    comp = np.empty(T.shape, dtype=np.float64)
    exclusion_zone = 2

    for i in range(T.shape[1]):
        ref[:, :] = T[:, :]
        naive.apply_exclusion_zone(ref, i, exclusion_zone, np.inf)

        comp[:, :] = T[:, :]
        core.apply_exclusion_zone(comp, i, exclusion_zone, np.inf)

        naive.replace_inf(ref)
        naive.replace_inf(comp)
        npt.assert_array_equal(ref, comp)
Beispiel #7
0
    def _update(self, t):
        """
        Ingress a new data point and update the matrix profile and matrix profile
        indices without egressing the oldest data point
        """
        self._n = self._T.shape[0]
        l = self._n - self._m + 1
        T_new = np.append(self._T, t)
        QT_new = np.empty(self._QT.shape[0] + 1)
        S = T_new[l:]
        t_drop = T_new[l - 1]

        if np.isfinite(t):
            self._T_isfinite = np.append(self._T_isfinite, True)
        else:
            self._T_isfinite = np.append(self._T_isfinite, False)
            t = 0
            T_new[-1] = 0
            S[-1] = 0

        T_subseq_isfinite = np.all(core.rolling_window(self._T_isfinite,
                                                       self._m),
                                   axis=1)

        for j in range(l, 0, -1):
            QT_new[j] = (self._QT[j - 1] - T_new[j - 1] * t_drop +
                         T_new[j + self._m - 1] * t)
        QT_new[0] = 0

        for j in range(self._m):
            QT_new[0] = QT_new[0] + T_new[j] * S[j]

        Q_squared = np.sum(S * S)
        T_squared = np.sum(core.rolling_window(T_new * T_new, self._m), axis=1)
        D = core._mass_absolute(Q_squared, T_squared, QT_new)
        D[~T_subseq_isfinite] = np.inf
        if np.any(~self._T_isfinite[-self._m:]):
            D[:] = np.inf

        core.apply_exclusion_zone(D, D.shape[0] - 1, self._excl_zone)

        for j in range(l):
            if D[j] < self._P[j]:
                self._I[j] = l
                self._P[j] = D[j]

        I_last = np.argmin(D)
        if np.isinf(D[I_last]):
            I_new = np.append(self._I, -1)
            P_new = np.append(self._P, np.inf)
        else:
            I_new = np.append(self._I, I_last)
            P_new = np.append(self._P, D[I_last])
        left_I_new = np.append(self._left_I, I_last)
        left_P_new = np.append(self._left_P, D[I_last])

        self._T = T_new
        self._P = P_new
        self._I = I_new
        self._left_I = left_I_new
        self._left_P = left_P_new
        self._QT = QT_new
Beispiel #8
0
    def _update_egress(self, t):
        """
        Ingress a new data point, egress the oldest data point, and update the matrix
        profile and matrix profile indices
        """
        self._n = self._T.shape[0]
        l = self._n - self._m + 1 - 1  # Subtract 1 due to egress
        self._T[:] = np.roll(self._T, -1)
        self._T[-1] = t
        self._n_appended += 1
        self._QT[:] = np.roll(self._QT, -1)
        S = self._T[l:]
        t_drop = self._T[l - 1]
        self._T_isfinite[:] = np.roll(self._T_isfinite, -1)

        self._I[:] = np.roll(self._I, -1)
        self._P[:] = np.roll(self._P, -1)
        self._left_I[:] = np.roll(self._left_I, -1)
        self._left_P[:] = np.roll(self._left_P, -1)

        if np.isfinite(t):
            self._T_isfinite[-1] = True
        else:
            self._T_isfinite[-1] = False
            t = 0
            self._T[-1] = 0
            S[-1] = 0

        T_subseq_isfinite = np.all(core.rolling_window(self._T_isfinite,
                                                       self._m),
                                   axis=1)

        for j in range(l, 0, -1):
            self._QT_new[j] = (self._QT[j - 1] - self._T[j - 1] * t_drop +
                               self._T[j + self._m - 1] * t)
        self._QT_new[0] = 0

        for j in range(self._m):
            self._QT_new[0] = self._QT_new[0] + self._T[j] * S[j]

        Q_squared = np.sum(S * S)
        T_squared = np.sum(core.rolling_window(self._T * self._T, self._m),
                           axis=1)
        D = core._mass_absolute(Q_squared, T_squared, self._QT_new)
        D[~T_subseq_isfinite] = np.inf
        if np.any(~self._T_isfinite[-self._m:]):
            D[:] = np.inf

        core.apply_exclusion_zone(D, D.shape[0] - 1, self._excl_zone)

        for j in range(D.shape[0]):
            if D[j] < self._P[j]:
                self._I[j] = D.shape[0] + self._n_appended - 1
                self._P[j] = D[j]

        I_last = np.argmin(D)

        if np.isinf(D[I_last]):
            self._I[-1] = -1
            self._P[-1] = np.inf
        else:
            self._I[-1] = I_last + self._n_appended
            self._P[-1] = D[I_last]

        self._left_I[-1] = I_last + self._n_appended
        self._left_P[-1] = D[I_last]

        self._QT[:] = self._QT_new
Beispiel #9
0
    def update(self, t):
        """
        Append a single new data point, `t`, to the existing time series `T` and update
        the matrix profile and matrix profile indices.

        Parameters
        ----------
        t : float
            A single new data point to be appended to `T`

        Notes
        -----
        `DOI: 10.1007/s10618-017-0519-9 \
        <https://www.cs.ucr.edu/~eamonn/MP_journal.pdf>`__

        See Table V

        Note that line 11 is missing an important `sqrt` operation!
        """
        n = self._T.shape[0]
        l = n - self._m + 1
        T_new = np.append(self._T, t)
        QT_new = np.empty(self._QT.shape[0] + 1)
        S = T_new[l:]
        t_drop = T_new[l - 1]

        if np.isinf(t) or np.isnan(t):
            self._illegal = np.append(self._illegal, True)
            t = 0
            T_new[-1] = 0
            S[-1] = 0
        else:
            self._illegal = np.append(self._illegal, False)

        if np.any(self._illegal[-self._m:]):
            μ_Q = np.inf
            σ_Q = np.nan
        else:
            μ_Q, σ_Q = core.compute_mean_std(S, self._m)
            μ_Q = μ_Q[0]
            σ_Q = σ_Q[0]

        M_T_new = np.append(self._M_T, μ_Q)
        Σ_T_new = np.append(self._Σ_T, σ_Q)

        for j in range(l, 0, -1):
            QT_new[j] = (self._QT[j - 1] - T_new[j - 1] * t_drop +
                         T_new[j + self._m - 1] * t)
        QT_new[0] = 0

        for j in range(self._m):
            QT_new[0] = QT_new[0] + T_new[j] * S[j]

        D = core.calculate_distance_profile(self._m, QT_new, μ_Q, σ_Q, M_T_new,
                                            Σ_T_new)
        if np.any(self._illegal[-self._m:]):
            D[:] = np.inf

        core.apply_exclusion_zone(D, D.shape[0] - 1, self._excl_zone)

        for j in range(l):
            if D[j] < self._P[j]:
                self._I[j] = l
                self._P[j] = D[j]

        I_last = np.argmin(D)
        if np.isinf(D[I_last]):
            I_new = np.append(self._I, -1)
            P_new = np.append(self._P, np.inf)
        else:
            I_new = np.append(self._I, I_last)
            P_new = np.append(self._P, D[I_last])
        left_I_new = np.append(self._left_I, I_last)
        left_P_new = np.append(self._left_P, D[I_last])

        self._T = T_new
        self._P = P_new
        self._I = I_new
        self._left_I = left_I_new
        self._left_P = left_P_new
        self._QT = QT_new
        self._M_T = M_T_new
        self._Σ_T = Σ_T_new
Beispiel #10
0
    def _update_egress(self, t):
        """
        Ingress a new data point, egress the oldest data point, and update the matrix
        profile and matrix profile indices
        """
        self._n = self._T.shape[0]
        l = self._n - self._m + 1 - 1  # Subtract 1 due to egress
        self._T[:-1] = self._T[1:]
        self._T[-1] = t
        self._n_appended += 1
        self._QT[:-1] = self._QT[1:]
        S = self._T[l:]
        t_drop = self._T[l - 1]
        self._T_isfinite[:-1] = self._T_isfinite[1:]
        self._T_subseq_isfinite[:-1] = self._T_subseq_isfinite[1:]
        self._T_squared[:-1] = self._T_squared[1:]

        self._I[:-1] = self._I[1:]
        self._P[:-1] = self._P[1:]
        self._left_I[:-1] = self._left_I[1:]
        self._left_P[:-1] = self._left_P[1:]

        if np.isfinite(t):
            self._T_isfinite[-1] = True
        else:
            self._T_isfinite[-1] = False
            t = 0
            self._T[-1] = 0
            S[-1] = 0

        self._T_subseq_isfinite[-1] = np.all(self._T_isfinite[-self._m:])

        self._QT_new[
            1:] = self._QT[:l] - self._T[:l] * t_drop + self._T[self._m:] * t
        self._QT_new[0] = np.sum(self._T[:self._m] * S[:self._m])

        Q_squared = np.sum(S * S)
        self._T_squared[-1] = np.sum(self._T[-self._m:] * self._T[-self._m:])
        D = core._mass_absolute(Q_squared, self._T_squared, self._QT_new)
        D[~self._T_subseq_isfinite] = np.inf
        if np.any(~self._T_isfinite[-self._m:]):
            D[:] = np.inf

        core.apply_exclusion_zone(D, D.shape[0] - 1, self._excl_zone)

        update_idx = np.argwhere(D < self._P).flatten()
        self._I[update_idx] = D.shape[
            0] + self._n_appended - 1  # D.shape[0] is base-1
        self._P[update_idx] = D[update_idx]

        I_last = np.argmin(D)

        if np.isinf(D[I_last]):
            self._I[-1] = -1
            self._P[-1] = np.inf
        else:
            self._I[-1] = I_last + self._n_appended
            self._P[-1] = D[I_last]

        self._left_I[-1] = I_last + self._n_appended
        self._left_P[-1] = D[I_last]

        self._QT[:] = self._QT_new