Example #1
0
def Integral(J, k, l, WaveletCoef, 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.
        WaveletCoef : 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(WaveletCoef) / 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
def DecomBoundary(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.OrthoMatrix(J, h, phi)
    Boundary = BW.BoundaryWavelets(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
Example #3
0
def M_AlphaBeta(alpha, beta, J, WaveletCoef, InteMatrix, Side):
    r'''
    This function calculates an entry in the martix :math:`M` (15).

    INPUT:
        alpha : int
            alpha
        beta : int
            beta
        J : int
            The scale.
        WaveletCoef : 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`).
        InteMatrix : numpy.float64
            A matrix with the values for the integrals calculated with
            the function :py:func:`Integral` for k and l in the
            interval [-2*a+2,0] or [2**J-2*a+1,2**J-1].
        Side : str
            `'L'` for left interval boundary and `'R'` for right
            interval boundary.
    OUTPUT:
        M : numpy.float64
            Entry (alpha,beta) of the martix M

    '''

    a = int(len(WaveletCoef) / 2)
    Moment = BW.Moments(WaveletCoef, a - 1)
    M = 0
    if Side == 'L':
        Interval = range(-2 * a + 2, 1)
        i = 0
        for k in Interval:
            j = 0
            for m in Interval:
                M += (BW.InnerProductPhiX(alpha, 0, k, Moment) *
                      BW.InnerProductPhiX(beta, 0, m, Moment) *
                      InteMatrix[i, j])
                j += 1
            i += 1
    elif Side == 'R':
        Interval = range(2**J - 2 * a + 1, 2**J)
        i = 0
        for k in Interval:
            j = 0
            for m in Interval:
                M += (BW.InnerProductPhiX(alpha, 0, k, Moment) *
                      BW.InnerProductPhiX(beta, 0, m, Moment) *
                      InteMatrix[i, j] * 2**(-J * (alpha + beta)))
                j += 1
            i += 1
    else:
        print('You must choose a side')

    return M
def ReconMirror(WaveletCoef, J, Wavelet, phi):
    '''
    This function reconstructs a 1D signal in time from its wavelet
    coefficients, using mirroring of the signal at the edge.

    INPUT:
        WaveletCoef : numpy.float64
            The wavelet decomposition. Can be made using
            DecomMirror().
        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(WaveletCoef)`.
    '''

    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(WaveletCoef) + (a) * OneStep, dtype=complex)
    for i in range(len(WaveletCoef)):
        x[i * OneStep:i * OneStep +
          len(phi)] += WaveletCoef[i] * phi * 2**(-(J) / 2)
    x = x[OneStep * (a):-OneStep * (a)]
    return x
def DecomMirror(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
def ReconBoundary(WaveletCoef, J, Wavelet, phi):
    '''
    This function reconstructs a 1D signal in time from its wavelet
    coefficients, using boundary wavelets at the edge.

    INPUT:
        WaveletCoef : numpy.float64
            The wavelet decomposition. Can be made using DecomBoundary().
        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(WaveletCoef)`.
    '''
    h = np.flipud(pywt.Wavelet(Wavelet).dec_lo)
    AL, AR = Ot.OrthoMatrix(J, h, phi)
    Q = BW.BoundaryWavelets(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(WaveletCoef), dtype=complex)
    for i in range(a):
        x[:m] += WaveletCoef[i] * Boundary[i]
    k = 1
    for i in range(a, len(WaveletCoef) - a):
        x[k * OneStep:k * OneStep +
          len(phi)] += WaveletCoef[i] * phi * 2**(-(J) / 2)
        k += 1
    for i in range(a):
        x[-m:] += WaveletCoef[-i - 1] * Boundary[-i - 1]
    return x
def GeneralTest(Wavelet='db2',
                J=2,
                epsilon=1 / 7,
                Length=1792,
                TimeOnly=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`.
        TimeOnly=False : bool
            If `TimeOnly=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.OrthoMatrix(J, WaveCoef, phi)
    phiNorm = np.sqrt(1 / OneStep *
                      np.sum(np.abs(BW.DownSample(phi, 0, OneStep, J)**2)))
    BoundaryT = BW.BoundaryWavelets(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 TimeOnly:
        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.FourierBoundaryWavelets(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
def FourierBoundaryWavelets(J,
                            Scheme,
                            WaveletCoef,
                            AL=None,
                            AR=None,
                            Win=Rectangle):
    r'''
    This function evaluates the Fourier transformed boundary functions
    for db2.

    INPUT:
        J : int
            The scale.
        Scheme : numpy.float64
            The sampling scheme in the Fourier domain.
        WaveletCoef : numpy.float64
            The wavelet coefficients, must sum to :math:`\sqrt{2}`.
            For Daubeshies 2 they can be found using
            `np.flipud(pywt.Wavelet('db2').dec_lo)`.
        AL=None : numpy.float64
            The left orthonormalisation matrix, if this is not
            supplied the functions will not be orthonormalized. Can be
            computed using
            :py:func:`boundwave.Orthonormal.OrthoMatrix`.
        AR=None : numpy.float64
            The right orthonormalisation matrix, if this is not
            supplied the functions will not be orthonormalized. Can be
            computed using
            :py:func:`boundwave.Orthonormal.OrthoMatrix`.
        Win= :py:func:`Rectangle` : numpy.complex128
            The window to use on the boundary functions.
    OUTPUT:
        x : numpy.complex128
            2d numpy array with the boundary functions in the columns;
            orthonormalised if `AL` and `AR` given.

    '''

    a = int(len(WaveletCoef) / 2)
    kLeft = np.arange(-2 * a + 2, 1)
    kRight = np.arange(2**J - 2 * a + 1, 2**J)
    xj = np.zeros((len(Scheme), 2 * a), dtype=complex)
    Moment = BW.Moments(WaveletCoef, a - 1)
    FourierPhiLeft = np.zeros((len(kLeft), len(Scheme)), dtype=complex)
    FourierPhiRight = np.zeros((len(kRight), len(Scheme)), dtype=complex)
    Window = Win(Scheme)
    for i in range(len(kLeft)):
        FourierPhiLeft[i] = ScalingFunctionFourier(WaveletCoef, J, kLeft[i],
                                                   Scheme, Window)
        FourierPhiRight[i] = ScalingFunctionFourier(WaveletCoef, J, kRight[i],
                                                    Scheme, Window)
    for b in range(a):
        xj[:, b] = np.sum(np.multiply(BW.InnerProductPhiX(b, J, kLeft, Moment),
                                      np.transpose(FourierPhiLeft)),
                          axis=1)
        xj[:, b + a] = np.sum(np.multiply(
            BW.InnerProductPhiX(b, J, kRight, Moment),
            np.transpose(FourierPhiRight)),
                              axis=1)
    if type(AL) is None or type(AR) is None:
        return xj
    else:
        x = np.zeros(np.shape(xj), dtype=complex)
        for i in range(a):
            for j in range(a):
                x[:, i] += xj[:, j] * AL[i, j]
        for i in range(a):
            for j in range(a):
                x[:, i + a] += xj[:, j + a] * AR[i, j]
        return x