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 use the symmetrical Laplacian operator as well # as a asymmetrical version of it (by adding more weight to the # derivative along one direction) # symmetrical L2symop = pylops.Laplacian(dims=(nx, ny), weights=(1, 1), dtype='float64') # asymmetrical L2asymop = pylops.Laplacian(dims=(nx, ny), weights=(3, 1), dtype='float64') Bsym = np.reshape(L2symop * A.flatten(), (nx, ny)) Basym = np.reshape(L2asymop * A.flatten(), (nx, ny)) fig, axs = plt.subplots(1, 3, figsize=(10, 3)) fig.suptitle('Laplacian', 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(Bsym, interpolation='nearest', cmap='rainbow')
# We can now define a set of available samples in the # first and second direction of the array and apply bilinear interpolation. nsamples = 2000 iava = np.vstack( (np.random.uniform(0, nz - 1, nsamples), np.random.uniform(0, nx - 1, nsamples))) Bop = pylops.signalprocessing.Bilinear(iava, (nz, nx)) y = Bop * x.ravel() ############################################################################### # At this point we try to reconstruct the input signal imposing a smooth # solution by means of a regularization term that minimizes the Laplacian of # the solution. D2op = pylops.Laplacian((nz, nx), weights=(1, 1), dtype='float64') xadj = Bop.H * y xinv = pylops.optimization.leastsquares.NormalEquationsInversion( Bop, [D2op], y, epsRs=[np.sqrt(0.1)], returninfo=False, **dict(maxiter=100)) xadj = xadj.reshape(nz, nx) xinv = xinv.reshape(nz, nx) fig, axs = plt.subplots(1, 3, figsize=(10, 4)) fig.suptitle('Bilinear interpolation', fontsize=14, fontweight='bold', y=0.95) axs[0].imshow(x, cmap='gray_r', vmin=0, vmax=250) axs[0].axis('tight')
dims=(nt, nx), sampling=dt, dir=0, halfcurrent=True) y = Cop * x.flatten() y = y.reshape(nt, nx) yn = y + np.random.normal(0, 4e-1, y.shape) # Numerical derivative Dop = pylops.FirstDerivative(nt * nx, dims=(nt, nx), dir=0, sampling=dt) xder = Dop * yn.flatten() xder = xder.reshape(nt, nx) # Regularized derivative Rop = pylops.Laplacian(dims=(nt, nx)) xreg = pylops.RegularizedInversion(Cop, [Rop], yn.flatten(), epsRs=[1e0], **dict(iter_lim=100, atol=1e-5)) xreg = xreg.reshape(nt, nx) # Preconditioned derivative Sop = pylops.Smoothing2D((11, 21), dims=(nt, nx)) xp = pylops.PreconditionedInversion(Cop, Sop, yn.flatten(), **dict(iter_lim=10, atol=1e-2)) xp = xp.reshape(nt, nx) # Visualize data and inversion vmax = 2 * np.max(np.abs(x)) fig, axs = plt.subplots(2, 3, figsize=(18, 12))
# To start we import a 2d image and define our restriction operator to irregularly and randomly # sample the image for 30% of the entire grid im = np.load("../testdata/python.npy")[:, :, 0] Nz, Nx = im.shape N = Nz * Nx # Subsample signal perc_subsampling = 0.2 Nsub2d = int(np.round(N * perc_subsampling)) iava = np.sort(np.random.permutation(np.arange(N))[:Nsub2d]) # Create operators and data Rop = pylops.Restriction(N, iava, dtype="float64") D2op = pylops.Laplacian((Nz, Nx), weights=(1, 1), dtype="float64") x = im.ravel() y = Rop * x y1 = Rop.mask(x) ############################################################################### # We will now use two different routines from our optimization toolbox # to estimate our original image in the regular grid. xcg_reg_lop = pylops.optimization.leastsquares.NormalEquationsInversion( Rop, [D2op], y, epsRs=[np.sqrt(0.1)], returninfo=False, **dict(maxiter=200))
############################################################################### # Finally we take advantage of our different solvers and try to invert the # modelling operator both in a least-squares sense and using TV-reg. Dop = [ pylops.FirstDerivative(ny * nx, dims=(nx, ny), dir=0, edge=True, dtype=np.float), pylops.FirstDerivative(ny * nx, dims=(nx, ny), dir=1, edge=True, dtype=np.float) ] D2op = pylops.Laplacian(dims=(nx, ny), edge=True, dtype=np.float) # L2 xinv_sm = \ pylops.optimization.leastsquares.RegularizedInversion(RLop.H, [D2op], y.T.flatten(), epsRs=[1e1], **dict(iter_lim=20)) xinv_sm = np.real(xinv_sm.reshape(nx, ny)).T # TV mu = 1.5 lamda = [1., 1.] niter = 3 niterinner = 4
def Laplacian(shape: tuple, weights: Tuple[float] = (1, 1), step: Union[tuple, float] = 1., edge: bool = True, dtype: str = 'float64') -> PyLopLinearOperator: r""" Laplacian. Computes the Laplacian of a 2D array. Parameters ---------- shape: tuple Shape of the input array. weights: Tuple[float] Weight to apply to each direction (real laplacian operator if ``weights=[1,1]``) step: Union[float, Tuple[float, ...]] Step size in each direction. edge: bool Use reduced order derivative at edges (``True``) or ignore them (``False``). dtype: str Type of elements in input vector. kind: str Derivative kind (``forward``, ``centered``, or ``backward``). Returns ------- :py:class:`pycsou.core.linop.LinearOperator` Laplacian operator. Examples -------- .. plot:: import numpy as np import matplotlib.pyplot as plt from pycsou.linop.diff import Laplacian from pycsou.util.misc import peaks x = np.linspace(-2.5, 2.5, 25) X,Y = np.meshgrid(x,x) Z = peaks(X, Y) Dop = Laplacian(shape=Z.shape) y = Dop * Z.flatten() plt.figure() h = plt.pcolormesh(X,Y,Z, shading='auto') plt.colorbar(h) plt.title('Signal') plt.figure() h = plt.pcolormesh(X,Y,y.reshape(X.shape), shading='auto') plt.colorbar(h) plt.title('Laplacian') plt.show() Notes ----- The Laplacian operator sums the second directional derivatives of a 2D array along the two canonical directions. It is defined as: .. math:: y[i, j] =\frac{x[i+1, j] + x[i-1, j] + x[i, j-1] +x[i, j+1] - 4x[i, j]} {dx\times dy}. See Also -------- :py:func:`~pycsou.linop.diff.DirectionalLaplacian`, :py:func:`~pycsou.linop.diff.SecondDerivative` """ if isinstance(step, Number): step = [step] * len(shape) return PyLopLinearOperator(pylops.Laplacian(dims=shape, weights=weights, sampling=step, edge=edge, dtype=dtype))