Example #1
0
###############################################################################
# We can also write a preconditioned problem, whose cost function is
#
#   .. math::
#       J= ||\mathbf{y} - \mathbf{R} \mathbf{P} \mathbf{p}||_2^2
#
# where :math:`\mathbf{P}` is the precondioned operator, :math:`\mathbf{p}` is
# the projected model in the preconditioned space, and
# :math:`\mathbf{x}=\mathbf{P}\mathbf{p}` is the model in the original model
# space we want to solve for. Note that a preconditioned problem converges
# much faster to its solution than its corresponding regularized problem.
# This can be done using the routine
# :py:func:`pylops.optimization.leastsquares.PreconditionedInversion`.

# Create regularization operator
Sop = pylops.Smoothing1D(nsmooth=11, dims=[N], dtype='float64')

# Invert for interpolated signal
xprec = \
    pylops.optimization.leastsquares.PreconditionedInversion(Rop, Sop, y,
                                                             returninfo=False,
                                                             **dict(damp=np.sqrt(1e-9),
                                                                    iter_lim=20,
                                                                    show=0))

###############################################################################
# Let's finally visualize these solutions

# sphinx_gallery_thumbnail_number=4
fig = plt.figure(figsize=(12, 4))
plt.plot(t[iava], y, '.k', ms=20, label='available samples')
# Add noise
yn = y + np.random.normal(0, 4e-1, y.shape)

# Numerical derivative
Dop = pylops.FirstDerivative(nt, sampling=dt)
xder = Dop * yn

# Regularized derivative
Rop = pylops.SecondDerivative(nt)
xreg = pylops.RegularizedInversion(Cop, [Rop],
                                   yn,
                                   epsRs=[1e0],
                                   **dict(iter_lim=100, atol=1e-5))

# Preconditioned derivative
Sop = pylops.Smoothing1D(41, nt)
xp = pylops.PreconditionedInversion(Cop, Sop, yn, **dict(iter_lim=10,
                                                         atol=1e-3))

# Visualize data and inversion
fig, axs = plt.subplots(1, 2, figsize=(18, 5))
axs[0].plot(t, y, 'k', LineWidth=3, label='data')
axs[0].plot(t, yn, '--g', LineWidth=3, label='noisy data')
axs[0].legend()
axs[0].set_title('Causal integration')
axs[1].plot(t, x, 'k', LineWidth=8, label='original')
axs[1].plot(t[1:-1],
            xder[1:-1],
            'r',
            LineWidth=3,
            label='numerical derivative')
Example #3
0
import matplotlib.pyplot as plt

import pylops

plt.close('all')

###############################################################################
# Define the input parameters: number of samples of input signal (``N``) and
# lenght of the smoothing filter regression coefficients (:math:`n_{smooth}`).
# In this first case the input signal is one at the center and zero elsewhere.
N = 31
nsmooth = 7
x = np.zeros(N)
x[int(N/2)] = 1

Sop = pylops.Smoothing1D(nsmooth=nsmooth, dims=[N], dtype='float32')

y = Sop*x
xadj = Sop.H*y

fig, ax = plt.subplots(1, 1, figsize=(10, 3))
ax.plot(x, 'k', lw=2, label=r'$x$')
ax.plot(y, 'r', lw=2, label=r'$y=Ax$')
ax.set_title('Smoothing in 1st direction', fontsize=14, fontweight='bold')
ax.legend()

###############################################################################
# Let's repeat the same exercise with a random signal as input. After applying smoothing,
# we will also try to invert it.
N = 120
nsmooth = 13
Example #4
0
axs[1].grid()
axs[1].legend(loc='upper right')
axs[1].axis('tight')

###############################################################################
# Finally we repeat the same exercise, but this time we use a *preconditioner*.
# Initially, our preconditioner is a :py:class:`pylops.Symmetrize` operator
# to ensure that our estimated wavelet is zero-phase. After we chain
# the :py:class:`pylops.Symmetrize` and the :py:class:`pylops.Smoothing1D`
# operators to also guarantee a smooth wavelet.

# Create symmetrize operator
Sop = pylops.Symmetrize((ntwav + 1) // 2)

# Create smoothing operator
Smop = pylops.Smoothing1D(5, dims=((ntwav + 1) // 2, ), dtype='float64')

# Invert for interpolated signal
wavn_prec_est = \
    pylops.optimization.leastsquares.PreconditionedInversion(Wavesop, Sop,
                                                             dn.T.flatten(),
                                                             returninfo=False,
                                                             **dict(damp=np.sqrt(1e-4),
                                                                    iter_lim=200,
                                                                    show=0))

wavn_smooth_est = \
    pylops.optimization.leastsquares.PreconditionedInversion(Wavesop, Sop*Smop,
                                                             dn.T.flatten(),
                                                             returninfo=False,
                                                             **dict(damp=np.sqrt(1e-4),
Example #5
0
def MovingAverage1D(window_size: int,
                    shape: tuple,
                    axis: int = 0,
                    dtype='float64'):
    r"""
    1D moving average.

    Apply moving average to a multi-dimensional array along a specific axis.

    Parameters
    ----------
    window_size: int
        Size of the window for moving average (must be *odd*).
    shape: tuple
        Shape of the input array.
    axis: int
        Axis along which moving average is applied.
    dtype: str
        Type of elements in input array.

    Returns
    -------
    :py:class:`pycsou.linop.base.PyLopLinearOperator`
        1D moving average operator.

    Examples
    --------

    .. plot::

       import numpy as np
       import matplotlib.pyplot as plt
       from pycsou.linop.conv import MovingAverage1D
       from scipy import signal
       sig = np.zeros(shape=(100,100))
       sig[sig.shape[0] // 2 - 2:sig.shape[0] // 2 + 3, sig.shape[1] // 2 - 2:sig.shape[1] // 2 + 3] = 1
       MAOp = MovingAverage1D(window_size=25, shape=sig.shape, axis=0)
       moving_average = (MAOp * sig.ravel()).reshape(sig.shape)
       plt.figure()
       plt.subplot(1,2,1)
       plt.imshow(sig, cmap='plasma'); plt.title('Signal')
       plt.subplot(1,2,2)
       plt.imshow(moving_average, cmap='plasma'); plt.title('Moving Average')
       plt.show()

    Notes
    -----
    The ``MovingAverage1D`` operator is a special type of convolution operator that
    convolves along a specific axis an array with a constant filter of size :math:`n_{smooth}`:

    .. math::
        \mathbf{h} = [ 1/n_{smooth}, 1/n_{smooth}, ..., 1/n_{smooth} ]

    For example, for a 3D array :math:`x`,  ``MovingAverage1D`` applied to the first axis yields:

    .. math::
        y[i,j,k] = 1/n_{smooth} \sum_{l=-(n_{smooth}-1)/2}^{(n_{smooth}-1)/2}
        x[l,j,k].

    Note that since the filter is symmetrical, the ``MovingAverage1D`` operator is
    self-adjoint.

    """
    PyLop = pylops.Smoothing1D(nsmooth=window_size,
                               dims=shape,
                               dir=axis,
                               dtype=dtype)
    return PyLopLinearOperator(PyLop)