def integral(J, k, l, wavelet_coef, phi):
    r'''
    This function calculates the integral (16) numerically.

    INPUT:
        J : int
            The scale.
        k : int
            The translation for the first function.
        l : int
            The translation for the second function.
        wavelet_coef : numpy.float64
            The wavelet coefficients, must sum to :math:`\sqrt{2}`.
            For Daubechies 2 they can be found using
            `np.flipud(pywt.Wavelet('db2').dec_lo)`.
        phi : numpy.float64
            The phi function, can be made with
            `pywt.Wavelet(wavelet).wavefun(level=15)`.
    OUTPUT:
        out : int
            The value of the integral.

    '''

    a = int(len(wavelet_coef) / 2)
    OneStep = len(phi) // (2 * a - 1)
    phiNorm = np.linalg.norm(BW.downsample(phi, 0, OneStep, J))
    phi1 = BW.downsample(phi, k, OneStep, J) / phiNorm
    phi2 = BW.downsample(phi, l, OneStep, J) / phiNorm
    phiProd = phi1 * phi2
    Integ = simps(phiProd)
    return Integ
예제 #2
0
def decom_boundary(signal, J, wavelet, phi):
    '''
    This function makes a wavelet decomposition of a 1D signal in
    time, using boundary wavelets at the edge.

    INPUT:
        signal : numpy.float64
            The signal to be decomposed.
        J : int
            The scale of the wavelet.
        wavelet : str
            The name of the wavelet to use. For instance `'db2'`.
        phi : numpy.float64
            The scaling function at scale 0. (1d array)
    OUTPUT:
        x : numpy.float64
            The decomposition.
    '''
    h = np.flipud(pywt.Wavelet(wavelet).dec_lo)
    a = int(len(h) / 2)
    N = int(np.log2(len(phi) / (len(h) - 1)))
    AL, AR = Ot.ortho_matrix(J, h, phi)
    Boundary = BW.boundary_wavelets(phi, J, h, AL=AL, AR=AR)
    x = np.zeros(2**J)
    for i in range(a):
        x[i] = np.inner(Boundary[:, i], signal)
    for i in range(1, 2**J - 2 * a + 1):
        x[i - 1 + a] = np.inner(
            BW.downsample(phi, i, 2**N, J, zero=True) * np.sqrt(2**J), signal)
    for i in range(a):
        x[-1 - i] = np.inner(Boundary[:, -1 - i], signal)
    x /= len(signal)
    return x
예제 #3
0
def recon_mirror(wavelet_coef, J, wavelet, phi):
    '''
    This function reconstructs a 1D signal in time from its wavelet
    coefficients, using mirroring of the signal at the edge.

    INPUT:
        wavelet_coef : numpy.float64
            The wavelet decomposition. Can be made using
            decom_mirror().
        J : int
            The scale of the wavelet.
        wavelet : str
            The name of the wavelet to use. For instance `'db2'`.
        phi : numpy.float64
            The scaling function at scale 0. (1d array)
    OUTPUT:
        x : numpy.float64
            The reconstructed signal, the length of the signal
            is `2**(N-J)*len(wavelet_coef)`.
    '''

    h = np.flipud(pywt.Wavelet(wavelet).dec_lo)
    N = int(np.log2(len(phi) / (len(h) - 1)))
    phi = BW.downsample(phi, 0, 2**N, J, zero=False)
    OneStep = 2**(N - J)
    a = int(len(phi) / OneStep) - 1
    x = np.zeros(OneStep * len(wavelet_coef) + (a) * OneStep, dtype=complex)
    for i in range(len(wavelet_coef)):
        x[i * OneStep:i * OneStep +
          len(phi)] += wavelet_coef[i] * phi * 2**(-(J) / 2)
    x = x[OneStep * (a):-OneStep * (a)]
    return x
예제 #4
0
def decom_mirror(signal, J, wavelet, phi):
    '''
    This function makes a wavelet decomposition of a 1D signal in
    time, using mirroring of the signal at the edge.

    INPUT:
        signal : numpy.float64
            The signal to be decomposed.
        J : int
            The scale of the wavelet.
        wavelet : str
            The name of the wavelet to use. For instance `'db2'`.
        phi : numpy.float64
            The scaling function at scale 0. (1d array)
    OUTPUT:
        x : numpy.float64
            The decomposition.
    '''
    h = np.flipud(pywt.Wavelet(wavelet).dec_lo)
    N = int(np.log2(len(phi) / (len(h) - 1)))
    OneStep = 2**(N - J)
    a = int(len(h) / 2)
    x = np.zeros(2**J + (2 * a - 2))
    for i in range(2 * a - 2):
        phi1 = BW.downsample(phi, 0, 2**N, J, zero=False) * np.sqrt(2**J)
        signal1 = np.concatenate(
            (np.flipud(signal[:OneStep * (i + 1)]), signal))
        signal1 = signal1[:len(phi1)]
        x[i] = np.inner(phi1, signal1)
    for i in range(2**J - 2 * a + 2):
        x[i + 2 * a - 2] = np.inner(
            BW.downsample(phi, i, 2**N, J, zero=True) * np.sqrt(2**J), signal)
    for i in range(2 * a - 2):
        phi1 = BW.downsample(phi, 0, 2**N, J, zero=False) * np.sqrt(2**J)
        signal1 = np.concatenate(
            (signal, np.flipud(signal[-OneStep * (i + 1):])))
        signal1 = signal1[-len(phi1):]
        x[2**J + i] = np.inner(phi1, signal1)
    x /= len(signal)
    return x
예제 #5
0
def recon_boundary(wavelet_coef, J, wavelet, phi):
    '''
    This function reconstructs a 1D signal in time from its wavelet
    coefficients, using boundary wavelets at the edge.

    INPUT:
        wavelet_coef : numpy.float64
            The wavelet decomposition. Can be made using decom_boundary().
        J : int
            The scale of the wavelet.
        avelet : str
            The name of the wavelet to use. For instance `'db2'`.
        phi : numpy.float64
            The scaling function at scale 0. (1d array)
    OUTPUT:
        x : numpy.float64
            The reconstructed signal, the length of the signal
            is `2**(N-J)*len(wavelet_coef)`.
    '''
    h = np.flipud(pywt.Wavelet(wavelet).dec_lo)
    AL, AR = Ot.ortho_matrix(J, h, phi)
    Q = BW.boundary_wavelets(phi, J, h, AL=AL, AR=AR)
    N = int(np.log2(len(phi) / (len(h) - 1)))
    phi = BW.downsample(phi, 0, 2**N, J, zero=False)
    OneStep = 2**(N - J)
    m = np.shape(Q)[0]
    a = np.shape(Q)[1] // 2
    Boundary = np.transpose(Q)
    x = np.zeros(OneStep * len(wavelet_coef), dtype=complex)
    for i in range(a):
        x[:m] += wavelet_coef[i] * Boundary[i]
    k = 1
    for i in range(a, len(wavelet_coef) - a):
        x[k * OneStep:k * OneStep +
          len(phi)] += wavelet_coef[i] * phi * 2**(-(J) / 2)
        k += 1
    for i in range(a):
        x[-m:] += wavelet_coef[-i - 1] * Boundary[-i - 1]
    return x
예제 #6
0
def general_test(wavelet='db2',
                 J=2,
                 epsilon=1 / 7,
                 length=1792,
                 time_only=False):
    '''
    A test function used in the paper. Plots the boundary wavelets in time and
    compare them with the boundary wavelets created in frequency by using an
    inverse Fourier transform.

    INPUT:
        wavelet='db2' : str
            The wavelet to use in the test.
        J=2 : int
            The scale. If `J` is too small for the scaling function
            to be supported within the interval [0,1] it is changed to
            the smallest possible `J`.
        epsilon=1/7 : float
            The sampling dencity in the frequency domain,
            i.e. the distance between samples. In Generalized sampling
            this must be at least 1/7 for db2.
        length=1792 : int
            The number of samples in the frequency domain. The
            standard is chosen because :math:`1792/7=256`.
        time_only=False : bool
            If `time_only=True` the boundary functions are only
            constructed in time, not in frequency.
    '''

    WaveCoef = np.flipud(pywt.Wavelet(wavelet).dec_lo)
    phi = pywt.Wavelet(wavelet).wavefun(level=15)[0][1:]
    a = int(len(WaveCoef) / 2)
    OneStep = len(phi) // (2 * a - 1)
    if J < a:
        J = a
        print('J has been changed to', J)
    AL, AR = ot.ortho_matrix(J, WaveCoef, phi)
    phiNorm = np.sqrt(1 / OneStep *
                      np.sum(np.abs(bw.downsample(phi, 0, OneStep, J)**2)))
    BoundaryT = bw.boundary_wavelets(phi / phiNorm, J, WaveCoef, AL=AL, AR=AR)
    NormT = np.zeros(2 * a)
    for i in range(2 * a):
        NormT[i] = np.sqrt(1 / OneStep * np.sum(np.abs(BoundaryT[:, i])**2))
    IP = 0
    for i in range(a):
        IP += i
    LeftInnerProdT = np.zeros(IP)
    ij = 0
    for i in range(a):
        for j in range(i + 1, a):
            LeftInnerProdT[ij] = 1 / OneStep * np.sum(
                BoundaryT[:, i] * BoundaryT[:, j])
            ij += 1
    RightInnerProdT = np.zeros(IP)
    ij = 0
    for i in range(a):
        for j in range(i + 1, a):
            RightInnerProdT[ij] = 1 / OneStep * np.sum(
                BoundaryT[:, i + a] * BoundaryT[:, j + a])
            ij += 1
    if time_only:
        print('Norms of functions in time', NormT)
        print('Inner products in time', LeftInnerProdT, RightInnerProdT)
        plt.figure()
        for i in range(a):
            plt.plot(np.linspace(0, 1, len(BoundaryT[:, i])),
                     BoundaryT[:, i],
                     label=r'$\phi^L_{' + f'{J},{i}' + r'}$')
        for i in range(a):
            plt.plot(np.linspace(0, 1, len(BoundaryT[:, i + a])),
                     BoundaryT[:, i + a],
                     label=r'$\phi^R_{' + f'{J},{i}' + r'}$')
        plt.legend()
        plt.xlabel('Time')
        plt.ylabel('Amplitude')
    else:
        s = int(length * epsilon)
        d = 1 / epsilon
        scheme = np.linspace(-length * epsilon / 2,
                             length * epsilon / 2,
                             length,
                             endpoint=False)
        BoundaryF = fbw.fourier_boundary_wavelets(J,
                                                  scheme,
                                                  WaveCoef,
                                                  AL=AL,
                                                  AR=AR)
        NormF = np.zeros(2 * a)
        for i in range(2 * a):
            NormF[i] = np.sqrt(epsilon * np.sum(np.abs(BoundaryF[:, i])**2))
        LeftInnerProdF = np.zeros(IP, dtype=complex)
        ij = 0
        for i in range(a):
            for j in range(i + 1, a):
                LeftInnerProdF[ij] = epsilon * np.sum(
                    BoundaryF[:, i] * BoundaryF[:, j])
                ij += 1
        RightInnerProdF = np.zeros(IP, dtype=complex)
        ij = 0
        for i in range(a):
            for j in range(i + 1, a):
                RightInnerProdF[ij] = epsilon * np.sum(
                    BoundaryF[:, i + a] * BoundaryF[:, j + a])
                ij += 1
        print('Norms of functions in time', NormT)
        print('Norms of functions i frequency', NormF)
        print('Inner products in time', LeftInnerProdT, RightInnerProdT)
        print('Inner products in frequency', LeftInnerProdF, RightInnerProdF)
        InverseBoundaryF = np.zeros((s, 2 * a), dtype=complex)
        for i in range(2 * a):
            InverseBoundaryF[:, i] = d**(1 / 2) * np.fft.ifft(
                d**(-1 / 2) * np.concatenate(
                    (BoundaryF[len(BoundaryF[:, i]) // 2:,
                               i], BoundaryF[:len(BoundaryF[:, i]) // 2, i])),
                norm='ortho')[:s]
            Fnorm = np.sqrt(1 / 256 *
                            np.sum(np.abs(InverseBoundaryF[:, i])**2))
            InverseBoundaryF[:, i] /= Fnorm
        plt.figure()
        plt.plot(np.linspace(0, 1, len(BoundaryT[:, 0])),
                 BoundaryT[:, 0],
                 label='Scaling functions in time',
                 color='C0')
        plt.plot(np.linspace(0, 1, s),
                 np.real(InverseBoundaryF[:, 0]),
                 label='Scaling functions in frequency',
                 color='C1')
        for i in range(1, a):
            plt.plot(np.linspace(0, 1, len(BoundaryT[:, 0])),
                     BoundaryT[:, i],
                     color='C0')
            plt.plot(np.linspace(0, 1, s),
                     np.real(InverseBoundaryF[:, i]),
                     color='C1')
        for i in range(a):
            plt.plot(np.linspace(0, 1, len(BoundaryT[:, 0])),
                     BoundaryT[:, i + a],
                     color='C0')
            plt.plot(np.linspace(0, 1, s),
                     np.real(InverseBoundaryF[:, i + a]),
                     color='C1')
        plt.legend()
        plt.xlabel('Time')
        plt.ylabel('Amplitude')
    return