コード例 #1
0
def test_identity_single():
    """Test that x = inv_dwt(dwt(x)) for a single level DWT"""

    for filter_name in ["db3", "db4"]:

        for nx in [20, 21, 22, 23]:

            x = np.linspace(1, nx, nx)  # np.random.randn(nx)
            Ux = 0.1 * (1 + np.random.random(nx))

            ld, hd, lr, hr = filter_design(filter_name)

            # single decomposition
            y_approx, U_approx, y_detail, U_detail, _ = dwt(x, Ux, ld, hd)

            # single reconstruction
            xr, Uxr, _ = inv_dwt(y_approx, U_approx, y_detail, U_detail, lr,
                                 hr)

            if x.size % 2 == 0:
                assert x.size == xr.size
                assert Ux.size == Uxr.size
                assert_allclose(x, xr)
            else:
                assert x.size + 1 == xr.size
                assert Ux.size + 1 == Uxr.size
                assert_allclose(x, xr[:-1])
コード例 #2
0
def test_dwt():
    """Compare :func:`dwt` to the implementation of :mod:`PyWavelets`"""

    for filter_name in ["db3", "db4"]:

        for nx in [20, 21, 22, 23]:

            x = np.random.randn(nx)
            Ux = 0.1 * (1 + np.random.random(nx))

            ld, hd, _, _ = filter_design(filter_name)

            # execute single level DWT
            y1, Uy1, y2, Uy2, _ = dwt(x, Ux, ld, hd)

            # all output has same length
            assert y1.size == y2.size
            assert y1.size == Uy1.size
            assert Uy1.size == Uy2.size

            # output is half the length of (input + filter - 1)
            assert (x.size + ld.size - 1) // 2 == y1.size

            # compare to pywt
            ca, cd = pywt.dwt(x, filter_name, mode="constant")
            assert ca.size == y1.size
            assert cd.size == y2.size
            assert_allclose(ca, y1, atol=1e-15)
            assert_allclose(cd, y2, atol=1e-15)
コード例 #3
0
def test_inv_dwt():
    """Compare :func:`inv_dwt` to the implementation of :mod:`PyWavelets`"""

    for filter_name in ["db3", "db4"]:

        for nc in [20, 21, 22, 23]:

            c_approx = np.random.randn(nc)
            Uc_approx = 0.1 * (1 + np.random.random(nc))
            c_detail = np.random.randn(nc)
            Uc_detail = 0.1 * (1 + np.random.random(nc))

            _, _, lr, hr = filter_design(filter_name)

            # execute single level DWT
            x, Ux, _ = inv_dwt(c_approx, Uc_approx, c_detail, Uc_detail, lr,
                               hr)

            # all output has same length
            assert x.size == Ux.size

            # output double the size of input minus filter
            assert 2 * c_approx.size - lr.size + 2 == x.size

            # compare to pywt
            r = pywt.idwt(c_approx, c_detail, filter_name, mode="constant")
            assert_allclose(x, r)
コード例 #4
0
def test_wave_rec():
    """Compare :func:`wave_rec` to the implementation of :mod:`PyWavelets`"""
    for filter_name in ["db2", "db3"]:

        for nx in [20, 21]:
            # generate required coeffs-structure
            coeff_lengths = [
                len(c) for c in pywt.wavedec(
                    np.zeros(nx), filter_name, mode="constant")
            ]

            coeffs = []
            Ucoeffs = []
            for i in coeff_lengths:
                coeffs.append(np.random.random(i))
                Ucoeffs.append(np.random.random(i))

            # define a filter
            _, _, lr, hr = filter_design(filter_name)

            x, _ = wave_rec(coeffs, Ucoeffs, lr, hr)

            # compare to the output of PyWavelet
            result_pywt = pywt.waverec(coeffs, filter_name, mode="constant")

            # compare output of both methods
            assert len(result_pywt) == len(x)
            assert_allclose(result_pywt, x)
コード例 #5
0
def test_filter_design():
    """Check if connection to PyWavelets works as expected."""

    for filter_name in ["db3", "db4", "rbio3.3"]:

        ld, hd, lr, hr = filter_design(filter_name)

        assert isinstance(ld, np.ndarray)
        assert isinstance(hd, np.ndarray)
        assert isinstance(lr, np.ndarray)
        assert isinstance(hr, np.ndarray)
コード例 #6
0
def test_decomposition_realtime():
    """Check if repetitive calls to :func:`wave_dec_realtime` yield the same
    result as a single call to the same function. (Because of different treatment
    of initial conditions, this can't be directly compared to :func:`wave_dec`.)
    """
    for filter_name in ["db2", "db3"]:

        for nx in [20, 21]:

            x = np.random.randn(nx)
            Ux = 0.1 * (1 + np.random.random(nx))

            ld, hd, _, _ = filter_design(filter_name)

            # run x all at once
            coeffs_a, Ucoeffs_a, _, _ = wave_dec_realtime(x, Ux, ld, hd, n=2)

            # slice x into smaller chunks and process them in batches
            # this tests the internal state options
            coeffs_list = []
            Ucoeffs_list = []
            z_b = None
            n_splits = 3
            for x_batch, Ux_batch in zip(np.array_split(x, n_splits),
                                         np.array_split(Ux, n_splits)):
                coeffs_b, Ucoeffs_b, _, z_b = wave_dec_realtime(
                    x_batch, Ux_batch, ld, hd, n=2, level_states=z_b)
                coeffs_list.append(coeffs_b)
                Ucoeffs_list.append(Ucoeffs_b)

            coeffs_b = [
                np.concatenate([coeffs[level] for coeffs in coeffs_list],
                               axis=0) for level in range(len(coeffs_list[0]))
            ]
            Ucoeffs_b = [
                np.concatenate([Ucoeffs[level] for Ucoeffs in Ucoeffs_list],
                               axis=0) for level in range(len(Ucoeffs_list[0]))
            ]

            # compare output depth
            assert len(coeffs_a) == len(coeffs_b)
            assert len(Ucoeffs_a) == len(Ucoeffs_b)

            # compare output in detail
            for a, b in zip(coeffs_a, coeffs_b):
                assert len(a) == len(b)
                assert_allclose(a, b)

            # compare output uncertainty in detail
            for a, b in zip(Ucoeffs_a, Ucoeffs_b):
                assert len(a) == len(b)
                assert_allclose(a, b)
コード例 #7
0
def test_identity_multi():
    """Test that x = inv_dwt(dwt(x)) for a multi level DWT"""
    for filter_name in ["db3", "db4"]:

        for nx in [20, 21, 203]:

            x = np.linspace(1, nx, nx)
            Ux = np.ones(nx)
            Ux[nx // 2:] = 2
            Ux = 0.1 * Ux

            ld, hd, lr, hr = filter_design(filter_name)

            # full decomposition
            coeffs, Ucoeffs, ol = wave_dec(x, Ux, ld, hd)

            # full reconstruction
            xr, Uxr = wave_rec(coeffs, Ucoeffs, lr, hr, original_length=ol)

            assert x.size == xr.size
            assert_allclose(x, xr)
            assert Ux.size == Uxr.size
コード例 #8
0
def test_wave_dec():
    """Compare :func:`wave_dec` to the implementation of :mod:`PyWavelets`"""
    for filter_name in ["db2", "db3"]:

        for nx in [20, 21]:

            x = np.random.randn(nx)
            Ux = 0.1 * (1 + np.random.random(nx))

            ld, hd, _, _ = filter_design(filter_name)

            coeffs, _, _ = wave_dec(x, Ux, ld, hd)

            # compare to the output of PyWavelet
            result_pywt = pywt.wavedec(x, filter_name, mode="constant")

            # compare output depth
            assert len(result_pywt) == len(coeffs)

            # compare output in detail
            for a, b in zip(result_pywt, coeffs):
                assert len(a) == len(b)
                assert_allclose(a, b, atol=1e-15)
コード例 #9
0
from PyDynamic.uncertainty.propagate_DWT import dwt, filter_design, inv_dwt

# monte carlo validation
n_mc = 1000  # monte carlo runs

for filter_name in ["db9"]:

    for nx in [101]:

        # define input signal and uncertainty of input signal
        x = np.clip(np.linspace(1, nx, nx), -10, 30)
        Ux = np.ones(nx)
        Ux[nx // 2:] = 2
        Ux = 1.0 * Ux

        ld, hd, lr, hr = filter_design(filter_name)

        # single decomposition with uncertainty
        c_approx, U_approx, c_detail, U_detail, _ = dwt(x, Ux, ld, hd)

        # single reconstruction with uncertainty
        xr, Uxr, _ = inv_dwt(c_approx, U_approx, c_detail, U_detail, lr, hr)

        # actual monte carlo

        # MC: decomposition
        tmp_c = []
        for i in range(n_mc):
            x_mc = x + np.random.randn(nx) * Ux
            c_approx_mc, c_detail_mc = pywt.dwt(x_mc,
                                                filter_name,
コード例 #10
0
def main():
    # basics
    buffer_length = 120
    signal = Buffer(maxlen=buffer_length, return_type="arrays")
    cycle_duration = 0.1  # seconds
    plot_counter = 0
    dwt_counter = 0
    cycle_counter = 0

    # init wavelet stuff
    ld, hd, _, _ = wavelet.filter_design("db2")
    dwt_length = 21

    # init multi level wavelet stuff
    n_levels = 4
    output_multi_level = [n_levels] + [
        level for level in list(range(1, n_levels + 1))[::-1]
    ]  # highest level twice because we store detail + approx
    output_multi_buffer_maxlen = [
        buffer_length // 2 ** level for level in output_multi_level
    ]
    output_multi = [
        Buffer(maxlen=maxlen, return_type="arrays")
        for maxlen in output_multi_buffer_maxlen
    ]  # list of buffer (different lengths to approximately cover the same timespan)
    level_states = None

    # init plot
    plt.ion()
    fig = plt.figure()
    ax = fig.subplots(nrows=1 + len(output_multi), ncols=1, sharex=True)

    # init signal plot
    ax[0].set_ylabel("$x^{(0)}$")
    ax[0].set_ylim([-2, 2])
    (sm,) = ax[0].plot(0, 0, "-k")  # signal
    (su,) = ax[0].plot(0, 0, ":k", linewidth=0.8)  # upper unc
    (sl,) = ax[0].plot(0, 0, ":k", linewidth=0.8)  # lower unc

    # init coefficient plots
    c_lines = []
    for i, (level, _ax) in enumerate(zip(output_multi_level[::-1], ax[1:])):
        if i == len(ax[1:]) - 1:
            _ax.set_ylabel("$a^{{({0})}}$".format(level))
        else:
            _ax.set_ylabel("$d^{{({0})}}$".format(level))
        _ax.set_ylim(auto=True)
        ce = _ax.errorbar(
            0, 0, yerr=0, linewidth=0, elinewidth=2, color="gray", capsize=5
        )
        cm = _ax.scatter([0], [0], c="r", s=10)  # (detail) coeffs
        c_lines.append([cm, ce])
        _ax.set_ylim([-3, 3])

    # simulate infinite stream of data
    while True:
        cycle_counter += 1

        # ti = tm.time()
        ti = cycle_counter * cycle_duration
        ui = 0.15 * (np.sin(2 * ti) + 2)
        xi = np.sin(ti) + np.random.randn() * ui

        signal.add(time=ti, val=xi, val_unc=ui)

        # run DWT every <dwt_length> iterations
        dwt_counter += 1
        if dwt_counter % dwt_length == 0:
            t, _, v, u = signal.show(dwt_length)

            # multi level dwt with uncertainty
            coeffs, Ucoeffs, _, level_states = wavelet.wave_dec_realtime(
                v, u, ld, hd, n=n_levels, level_states=level_states
            )

            # assign correct timestamps to the coefficients
            i0_old = (level_states["counter"] - len(t)) % 2 ** n_levels
            time_indices = np.arange(i0_old, i0_old + len(t))

            # save results to data structure
            for c, u, buffer, level in zip(
                coeffs, Ucoeffs, output_multi, output_multi_level
            ):
                time_indices_level = (time_indices + 1) % 2 ** level == 0
                if (
                    time_indices_level.sum() > 0
                ):  # otherwise error from time-series-buffer
                    buffer.add(time=t[time_indices_level], val=c, val_unc=u)

            dwt_counter = 0

            # set dwt length until next cycle
            dwt_length = random.choice(
                [1, 2, 10, 21]
            )  # could also be constant, e.g. dwt_length = 20
            print(dwt_length)

        # update plot every 5 iterations
        plot_counter += 1
        if (
            plot_counter % 5 == 0 and cycle_counter > buffer_length
        ):  # skip plotting at startup, when buffer is still not fully filled
            # update plot

            # get data to plot
            t_signal, _, v_signal, u_signal = signal.show(-1)

            # update signal lines
            sm.set_xdata(t_signal)
            su.set_xdata(t_signal)
            sl.set_xdata(t_signal)
            sm.set_ydata(v_signal)
            su.set_ydata(v_signal + u_signal)
            sl.set_ydata(v_signal - u_signal)
            ax[0].set_xlim([min(t_signal), max(t_signal)])

            # update dwt lines
            for buffer, _ax, c_line in zip(output_multi[::-1], ax[1:], c_lines):
                if len(buffer) > 0:  # otherwise error from time-series-buffer
                    t_coeff, _, v_coeff, u_coeff = buffer.show(-1)

                    # change the scatter
                    data = np.c_[t_coeff, v_coeff]
                    c_line[0].set_offsets(data)
                    c_line[0].set_facecolor(["r"] * len(t_coeff))

                    # change the error bars
                    c_line[1].remove()
                    c_line[1] = _ax.errorbar(
                        t_coeff,
                        v_coeff,
                        yerr=u_coeff,
                        linewidth=0,
                        elinewidth=1.5,
                        color="gray",
                        capsize=3,
                        zorder=0,
                    )
                    upper_unc = v_coeff + u_coeff
                    lower_unc = v_coeff - u_coeff

                    if v_coeff.size != 0:
                        lim = [np.min(lower_unc), np.max(upper_unc)]
                        _ax.set_ylim(lim)

            # finally update the plot itself
            fig.tight_layout()
            fig.align_ylabels(ax)
            fig.canvas.draw()
            fig.canvas.flush_events()

            # reset plot counter
            plot_counter = 0