Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
PPop_reg = MatrixMult(PP, dims=nspatprod)
minv = lsqr(PPop_reg, datar.flatten(), **kwargs_solver)[0]
else:
# create regularized normal eqs. and solve them simultaneously
PP = np.dot(PPop.A.T, PPop.A) + epsI * np.eye(nt0)
datarn = PPop.A.T * datar.reshape(nt0, nspatprod)
PPop_reg = MatrixMult(PP, dims=nspatprod)
minv = lstsq(PPop_reg.A, datarn.flatten(), **kwargs_solver)[0]
else:
# solve unregularized normal equations simultaneously with lop
minv = lsqr(PPop, datar, **kwargs_solver)[0]
else:
if epsRL1 is None:
# L2 inversion with spatial regularization
if dims == 1:
Regop = SecondDerivative(nt0, dtype=PPop.dtype)
elif dims == 2:
Regop = Laplacian((nt0, nx), dtype=PPop.dtype)
else:
Regop = Laplacian((nt0, nx, ny), dirs=(1, 2), dtype=PPop.dtype)
minv = RegularizedInversion(PPop, [Regop], data.flatten(),
x0=None if m0 is None else m0.flatten(),
epsRs=[epsR], returninfo=False,
**kwargs_solver)
else:
# Blockiness-promoting inversion with spatial regularization
if dims == 1:
RegL1op = FirstDerivative(nt0, dtype=PPop.dtype)
RegL2op = None
elif dims == 2:
RegL1op = FirstDerivative(nt0*nx, dims=(nt0, nx),
Iop = pylops.Identity(nx)
n = np.random.normal(0, 1, nx)
y = Iop*(x + n)
plt.figure(figsize=(10, 5))
plt.plot(x, 'k', lw=3, label='x')
plt.plot(y, '.k', label='y=x+n')
plt.legend()
plt.title('Model and data')
###############################################################################
# To start we will try to use a simple L2 regularization that enforces
# smoothness in the solution. We can see how denoising is succesfully achieved
# but the solution is much smoother than we wish for.
D2op = pylops.SecondDerivative(nx, edge=True)
lamda = 1e2
xinv = \
pylops.optimization.leastsquares.RegularizedInversion(Iop, [D2op], y,
epsRs=[np.sqrt(lamda/2)],
**dict(iter_lim=30))
plt.figure(figsize=(10, 5))
plt.plot(x, 'k', lw=3, label='x')
plt.plot(y, '.k', label='y=x+n')
plt.plot(xinv, 'r', lw=5, label='xinv')
plt.legend()
plt.title('L2 inversion')
###############################################################################
# Now we impose blockiness in the solution using the Split Bregman solver
# solve is highly ill-posed and requires some prior knowledge from the user.
#
# We will now see how to add prior information to the inverse process in the
# form of regularization (or preconditioning). This can be done in two different ways
#
# * regularization via :py:func:`pylops.optimization.leastsquares.NormalEquationsInversion` or
# :py:func:`pylops.optimization.leastsquares.RegularizedInversion`)
# * preconditioning via :py:func:`pylops.optimization.leastsquares.PreconditionedInversion`
#
# Let's start by regularizing the normal equations using a second derivative operator
#
# .. math::
# \mathbf{x} = (\mathbf{R^TR}+\epsilon_\nabla^2\nabla^T\nabla)^{-1} \mathbf{R^Ty}
# Create regularization operator
D2op = pylops.SecondDerivative(N, dims=None, dtype='float64')
# Regularized inversion
epsR = np.sqrt(0.1)
epsI = np.sqrt(1e-4)
xne = pylops.optimization.leastsquares.NormalEquationsInversion(Rop, [D2op], y, epsI=epsI,
epsRs=[epsR], returninfo=False,
**dict(maxiter=50))
###############################################################################
# We can do the same while using :py:func:`pylops.optimization.leastsquares.RegularizedInversion`
# which solves the following augmented problem
#
# .. math::
# \begin{bmatrix}
# \mathbf{R} \\
axs[2].imshow(dn, cmap='gray', extent=(theta[0], theta[-1], t0[-1], t0[0]),
vmin=-0.1, vmax=0.1)
axs[2].axis('tight')
axs[2].set_title('Noisy Data with zero-phase wavelet', fontsize=10)
axs[2].set_xlabel(r'$\Theta$')
###############################################################################
# We can invert the data. First we will consider noise-free data, subsequently
# we will add some noise and add a regularization terms in the inversion
# process to obtain a well-behaved wavelet also under noise conditions.
wav_est = Wavesop / d.T.flatten()
wav_phase_est = Wavesop_phase / d_phase.T.flatten()
wavn_est = Wavesop / dn.T.flatten()
# Create regularization operator
D2op = pylops.SecondDerivative(ntwav, dtype='float64')
# Invert for wavelet
wavn_reg_est, istop, itn, r1norm, r2norm = \
pylops.optimization.leastsquares.RegularizedInversion(Wavesop, [D2op], dn.T.flatten(),
epsRs=[np.sqrt(0.1)], returninfo=True,
**dict(damp=np.sqrt(1e-4),
iter_lim=200, show=0))
###############################################################################
# As expected, the regularization helps to retrieve a smooth wavelet
# even under noisy conditions.
# sphinx_gallery_thumbnail_number = 3
fig, axs = plt.subplots(2, 1, sharex=True, figsize=(8, 6))
axs[0].plot(wav, 'k', lw=6, label='True')
axs[0].plot(wav_est, '--r', lw=4, label='Estimated (noise-free)')
# form of regularization (or preconditioning). This can be done in two
# different ways
#
# * regularization via :py:func:`pylops.optimization.leastsquares.NormalEquationsInversion`
# or :py:func:`pylops.optimization.leastsquares.RegularizedInversion`)
# * preconditioning via :py:func:`pylops.optimization.leastsquares.PreconditionedInversion`
#
# Let's start by regularizing the normal equations using a second
# derivative operator
#
# .. math::
# \mathbf{x} = (\mathbf{R^TR}+\epsilon_\nabla^2\nabla^T\nabla)^{-1}
# \mathbf{R^Ty}
# Create regularization operator
D2op = pylops.SecondDerivative(N, dims=None, dtype='float64')
# Regularized inversion
epsR = np.sqrt(0.1)
epsI = np.sqrt(1e-4)
xne = \
pylops.optimization.leastsquares.NormalEquationsInversion(Rop, [D2op], y,
epsI=epsI,
epsRs=[epsR],
returninfo=False,
**dict(maxiter=50))
###############################################################################
# Note that in case we have access to a fast implementation for the chain of
# forward and adjoint for the regularization operator
# (i.e., :math:`\nabla^T\nabla`), we can modify our call to
axs[0].axis('tight')
axs[0].set_title('x')
plt.colorbar(im, ax=axs[0])
im = axs[1].imshow(B, interpolation='nearest', cmap='rainbow')
axs[1].axis('tight')
axs[1].set_title('y')
plt.colorbar(im, ax=axs[1])
plt.tight_layout()
plt.subplots_adjust(top=0.8)
###############################################################################
# We can now do the same for the second derivative
A = np.zeros((nx, ny))
A[nx//2, ny//2] = 1.
D2op = pylops.SecondDerivative(nx * ny, dims=(nx, ny), dir=0, dtype='float64')
B = np.reshape(D2op * A.flatten(), (nx, ny))
fig, axs = plt.subplots(1, 2, figsize=(10, 3))
fig.suptitle('Second Derivative in 1st direction', fontsize=12,
fontweight='bold', y=0.95)
im = axs[0].imshow(A, interpolation='nearest', cmap='rainbow')
axs[0].axis('tight')
axs[0].set_title('x')
plt.colorbar(im, ax=axs[0])
im = axs[1].imshow(B, interpolation='nearest', cmap='rainbow')
axs[1].axis('tight')
axs[1].set_title('y')
plt.colorbar(im, ax=axs[1])
plt.tight_layout()
plt.subplots_adjust(top=0.8)
axs[1].legend()
axs[1].set_title('Inverse causal integration = Derivative')
###############################################################################
# As expected we obtain the same result. Let's see what happens if we now
# add some random noise to our data.
# 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')
else:
Regop = Laplacian((nt0, nx, ny), dirs=(1, 2), dtype=PPop.dtype)
minv = RegularizedInversion(PPop, [Regop], data.flatten(),
x0=None if m0 is None else m0.flatten(),
epsRs=[epsR], returninfo=False,
**kwargs_solver)
else:
# Blockiness-promoting inversion with spatial regularization
if dims == 1:
RegL1op = FirstDerivative(nt0, dtype=PPop.dtype)
RegL2op = None
elif dims == 2:
RegL1op = FirstDerivative(nt0*nx, dims=(nt0, nx),
dir=0, dtype=PPop.dtype)
RegL2op = SecondDerivative(nt0*nx, dims=(nt0, nx),
dir=1, dtype=PPop.dtype)
else:
RegL1op = FirstDerivative(nt0*nx*ny, dims=(nt0, nx, ny),
dir=0, dtype=PPop.dtype)
RegL2op = Laplacian((nt0, nx, ny), dirs=(1, 2),
dtype=PPop.dtype)
if 'mu' in kwargs_solver.keys():
mu = kwargs_solver['mu']
kwargs_solver.pop('mu')
else:
mu = 1.
if 'niter_outer' in kwargs_solver.keys():
niter_outer = kwargs_solver['niter_outer']
kwargs_solver.pop('niter_outer')
else:
#
# * regularized inversion with second derivative along the spatial axis
#
# .. math::
# J = ||\mathbf{y} - \mathbf{R} \mathbf{x}||_2 +
# \epsilon_\nabla ^2 ||\nabla \mathbf{x}||_2
#
# * sparsity-promoting inversion with :py:class:`pylops.FFT2` operator used
# as sparsyfing transform
#
# .. math::
# J = ||\mathbf{y} - \mathbf{R} \mathbf{F}^H \mathbf{x}||_2 +
# \epsilon ||\mathbf{F}^H \mathbf{x}||_1
# smooth inversion
D2op = pylops.SecondDerivative(par['nx']*par['nt'],
dims=(par['nx'], par['nt']),
dir=0, dtype='float64')
xsmooth, _, _ = \
pylops.waveeqprocessing.SeismicInterpolation(y, par['nx'], iava,
kind='spatial',
**dict(epsRs=[np.sqrt(0.1)],
damp=np.sqrt(1e-4),
iter_lim=50, show=0))
# sparse inversion with FFT2
nfft = 2**8
FFTop = pylops.signalprocessing.FFT2D(dims=[par['nx'], par['nt']],
nffts=[nfft, nfft],
sampling=[par['dx'], par['dt']])
X = FFTop*x.flatten()