示例#1
0
def test_Diagonal_1dsignal(par):
    """Dot-test and inversion for Diagonal operator for 1d signal
    """
    for ddim in (par['nx'], par['nt']):
        d = (np.arange(0, ddim, dtype=par['dtype']) + 1.) + \
            par['imag']*(np.arange(0, ddim, dtype=par['dtype']) + 1.)
        if par['imag'] == 0:
            d = torch.from_numpy(d).to(dev)
        else:
            d = complextorch_fromnumpy(d).to(dev)

        Dop = Diagonal(d, dtype=d.dtype)
        assert dottest(Dop,
                       ddim,
                       ddim,
                       tol=1e-4,
                       complexflag=0 if par['imag'] == 0 else 3)

        x = np.ones(ddim, dtype=par['dtype']) + \
            par['imag'] * np.ones(ddim, dtype=par['dtype'])
        if par['imag'] == 0:
            x = torch.from_numpy(x).to(dev)
        else:
            x = complextorch_fromnumpy(x).to(dev)
        xcg = cg(Dop, Dop * x, niter=ddim)[0]
        assert_array_almost_equal(x.numpy(), xcg.cpu().numpy(), decimal=4)
示例#2
0
def test_Diagonal_2dsignal(par):
    """Dot-test and inversion for Diagonal operator for 2d signal
    """
    for idim, ddim in enumerate((par['nx'], par['nt'])):
        d = (np.arange(0, ddim, dtype=par['dtype']) + 1.) + \
            par['imag'] * (np.arange(0, ddim, dtype=par['dtype']) + 1.)
        if par['imag'] == 0:
            d = torch.from_numpy(d).to(dev)
        else:
            d = complextorch_fromnumpy(d).to(dev)

        Dop = Diagonal(d,
                       dims=(par['nx'], par['nt']),
                       dir=idim,
                       dtype=par['dtype'])
        assert dottest(Dop,
                       par['nx'] * par['nt'],
                       par['nx'] * par['nt'],
                       tol=1e-4,
                       complexflag=0 if par['imag'] == 0 else 3)

        x = np.ones((par['nx'], par['nt']), dtype=par['dtype']) + \
            par['imag'] * np.ones((par['nx'], par['nt']), dtype=par['dtype'])
        if par['imag'] == 0:
            x = torch.from_numpy(x).to(dev)
        else:
            x = complextorch_fromnumpy(x).to(dev)
        xcg = cg(Dop, Dop * x.flatten(), niter=Dop.shape[0])[0]
        assert_array_almost_equal(x.flatten().numpy(),
                                  xcg.flatten().cpu().numpy(),
                                  decimal=4)
示例#3
0
def test_MatrixMult_repeated(par):
    """Dot-test and inversion for test_MatrixMult operator repeated
    along another dimension
    """
    np.random.seed(10)
    G = np.random.normal(0, 10, (par['ny'], par['nx'])).astype(par['dtype']) + \
        par['imag'] * np.random.normal(0, 10, (par['ny'],
                                               par['nx'])).astype(par['dtype'])
    if par['imag'] == 0:
        G = torch.from_numpy(G).to(dev)
    else:
        G = complextorch_fromnumpy(G).to(dev)
    Gop = MatrixMult(G, dims=5, dtype=G.dtype)
    assert dottest(Gop,
                   par['ny'] * 5,
                   par['nx'] * 5,
                   tol=1e-4,
                   complexflag=0 if par['imag'] == 0 else 3)

    x = (np.ones((par['nx'], 5), dtype=par['dtype'])).flatten() +\
        (par['imag'] * np.ones((par['nx'], 5), dtype=par['dtype'])).flatten()
    if par['imag'] == 0:
        x = torch.from_numpy(x).to(dev)
    else:
        x = complextorch_fromnumpy(x).to(dev)
    y = Gop * x
    xcg = cg(Gop.H * Gop, Gop.H * y, niter=2 * par['nx'])[0]
    if par['imag'] == 0:
        assert_array_almost_equal(x.numpy(), xcg.numpy(), decimal=3)
示例#4
0
def test_MatrixMult(par):
    """Dot-test and inversion for MatrixMult operator
    """
    np.random.seed(10)
    G = np.random.normal(0, 10, (par['ny'],
                                 par['nx'])).astype(par['dtype']) + \
        par['imag']*np.random.normal(0, 10, (par['ny'],
                                             par['nx'])).astype(par['dtype'])
    if par['imag'] == 0:
        G = torch.from_numpy(G).to(dev)
    else:
        G = complextorch_fromnumpy(G).to(dev)
    Gop = MatrixMult(G, dtype=G.dtype)
    assert dottest(Gop,
                   par['ny'],
                   par['nx'],
                   tol=1e-4,
                   complexflag=0 if par['imag'] == 0 else 3)

    x = np.ones(par['nx'], dtype=par['dtype']) + \
        par['imag']*np.ones(par['nx'], dtype=par['dtype'])
    if par['imag'] == 0:
        x = torch.from_numpy(x).to(dev)
    else:
        x = complextorch_fromnumpy(x).to(dev)
    y = Gop * x
    xcg = cg(Gop.H * Gop, Gop.H * y, niter=2 * par['nx'])[0]
    if par['imag'] == 0:  # need to also get test to work with complex numbers!
        assert_array_almost_equal(x.numpy(), xcg.numpy(), decimal=3)
示例#5
0
def test_VStack(par):
    """Dot-test and inversion for VStack operator
    """
    np.random.seed(10)
    G1 = torch.from_numpy(np.random.normal(0, 10, (par['ny'], par['nx'])).astype('float32'))
    G2 = torch.from_numpy(np.random.normal(0, 10, (par['ny'], par['nx'])).astype('float32'))
    x = torch.ones(par['nx'], dtype=torch.float32) + \
        par['imag']*torch.ones(par['nx'], dtype=torch.float32)

    Vop = VStack([MatrixMult(G1, dtype=torch.float32),
                  MatrixMult(G2, dtype=torch.float32)],
                 dtype=torch.float32)
    assert dottest(Vop, 2*par['ny'], par['nx'],
                   complexflag=0 if par['imag'] == 0 else 3)

    xcg = cg(Vop.H * Vop, Vop.H * (Vop * x), niter=300)[0]
    assert_array_almost_equal(x.numpy(), xcg.numpy(), decimal=4)
示例#6
0
                                             dtype=torch.float32)
y = Cop*x

xinv = Cop / y

fig, ax = plt.subplots(1, 1, figsize=(10, 3))
ax.plot(t, x.cpu().numpy(), 'k', lw=2, label=r'$x$')
ax.plot(t, y.cpu().numpy(), 'r', lw=2, label=r'$y=Ax$')
ax.plot(t, xinv.cpu().numpy(), '--g', lw=2, label=r'$x_{ext}$')
ax.set_title('Convolve in 1st direction', fontsize=14, fontweight='bold')
ax.legend()
ax.set_xlim(1.9, 2.1)

###############################################################################
# We show now that also a filter with mixed phase (i.e., not centered around zero)
# can be applied and inverted for using the :py:class:`pylops.signalprocessing.Convolve1D`
# operator.
Cop = pylops_gpu.signalprocessing.Convolve1D(nt, h=h, offset=hcenter - 3,
                                             dtype=torch.float32)
y = Cop * x
y1 = Cop.H * x
xinv = cg(Cop.H*Cop, Cop.H*y, niter=100)[0]

fig, ax = plt.subplots(1, 1, figsize=(10, 3))
ax.plot(t, x.cpu().numpy(), 'k', lw=2, label=r'$x$')
ax.plot(t, y.cpu().numpy(), 'r', lw=2, label=r'$y=Ax$')
ax.plot(t, y1.cpu().numpy(), 'b', lw=2, label=r'$y=A^Hx$')
ax.plot(t, xinv.cpu().numpy(), '--g', lw=2, label=r'$x_{ext}$')
ax.set_title('Convolve in 1st direction', fontsize=14, fontweight='bold')
ax.set_xlim(1.9, 2.1)
ax.legend()
示例#7
0
def PoststackInversion(data,
                       wav,
                       m0=None,
                       explicit=False,
                       simultaneous=False,
                       epsI=None,
                       epsR=None,
                       dottest=False,
                       epsRL1=None,
                       device='cpu',
                       togpu=(False, False),
                       tocpu=(False, False),
                       **kwargs_solver):
    r"""Post-stack linearized seismic inversion.

    Invert post-stack seismic operator to retrieve an acoustic
    impedance profile from band-limited seismic post-stack data.
    Depending on the choice of input parameters, inversion can be
    trace-by-trace with explicit operator or global with either
    explicit or linear operator.

    Parameters
    ----------
    data : :obj:`np.ndarray`
        Band-limited seismic post-stack data of size
        :math:`[n_{t0} (\times n_x \times n_y)]`
    wav : :obj:`np.ndarray`
        Wavelet in time domain (must have odd number of elements
        and centered to zero). If 1d, assume stationary wavelet for the entire
        time axis. If 2d of size :math:`[n_{t0} \times n_h]` use as
        non-stationary wavelet
    m0 : :obj:`np.ndarray`, optional
        Background model of size :math:`[n_{t0} (\times n_x \times n_y)]`
    explicit : :obj:`bool`, optional
        Create a chained linear operator (``False``, preferred for large data)
        or a ``MatrixMult`` linear operator with dense matrix
        (``True``, preferred for small data)
    simultaneous : :obj:`bool`, optional
        Simultaneously invert entire data (``True``) or invert
        trace-by-trace (``False``) when using ``explicit`` operator
        (note that the entire data is always inverted when working
        with linear operator)
    epsI : :obj:`float`, optional
        Damping factor for Tikhonov regularization term
    epsR : :obj:`float`, optional
        Damping factor for additional Laplacian regularization term
    dottest : :obj:`bool`, optional
        Apply dot-test
    epsRL1 : :obj:`float`, optional
        Damping factor for additional blockiness regularization term
    device : :obj:`str`, optional
        Device to be used
    togpu : :obj:`tuple`, optional
        Move model and data from cpu to gpu prior to applying ``matvec`` and
        ``rmatvec``, respectively (only when ``device='gpu'``)
    tocpu : :obj:`tuple`, optional
        Move data and model from gpu to cpu after applying ``matvec`` and
        ``rmatvec``, respectively (only when ``device='gpu'``)
    **kwargs_solver
        Arbitrary keyword arguments for :py:func:`scipy.linalg.lstsq`
        solver (if ``explicit=True`` and  ``epsR=None``)
        or :py:func:`scipy.sparse.linalg.lsqr` solver (if ``explicit=False``
        and/or ``epsR`` is not ``None``)

    Returns
    -------
    minv : :obj:`np.ndarray`
        Inverted model of size :math:`[n_{t0} (\times n_x \times n_y)]`
    datar : :obj:`np.ndarray`
        Residual data (i.e., data - background data) of
        size :math:`[n_{t0} (\times n_x \times n_y)]`

    Notes
    -----
    Refer to :class:`pylops.avo.poststack.PoststackInversion` for
    implementation details.

    """
    # check if background model and data have same shape
    if m0 is not None and data.shape != m0.shape:
        raise ValueError('data and m0 must have same shape')

    # find out dimensions
    if len(data.shape) == 1:
        dims = 1
        nt0 = data.shape[0]
        nspat = None
        nspatprod = nx = 1
    elif len(data.shape) == 2:
        dims = 2
        nt0, nx = data.shape
        nspat = (nx, )
        nspatprod = nx
    else:
        dims = 3
        nt0, nx, ny = data.shape
        nspat = (nx, ny)
        nspatprod = nx * ny
        data = data.reshape(nt0, nspatprod)

    # create operator
    PPop = PoststackLinearModelling(wav,
                                    nt0=nt0,
                                    spatdims=nspat,
                                    explicit=explicit,
                                    tocpu=tocpu,
                                    togpu=togpu,
                                    device=device)
    if dottest:
        Dottest(PPop,
                nt0 * nspatprod,
                nt0 * nspatprod,
                raiseerror=True,
                verb=True)

    # create and remove background data from original data
    datar = data.flatten() if m0 is None else \
        data.flatten() - PPop * m0.flatten()
    # invert model
    if epsR is None:
        # inversion without spatial regularization
        if explicit:
            if epsI is None and not simultaneous:
                # solve unregularized equations indipendently trace-by-trace
                minv = torch.solve(
                    datar.reshape(nt0, nspatprod),
                    PPop.A.reshape(nt0, nt0) +
                    1e-3 * torch.eye(nt0, dtype=torch.float32)).solution
            elif epsI is None and simultaneous:
                # solve unregularized equations simultaneously
                minv = cg(PPop.H * PPop, PPop.H * datar, **kwargs_solver)[0]
            elif epsI is not None:
                # create regularized normal equations
                PP = torch.matmul(PPop.A.t(), PPop.A) + \
                     epsI * torch.eye(nt0, dtype=torch.float32)
                datarn = torch.matmul(PPop.A.t(),
                                      datar.reshape(nt0, nspatprod))
                if not simultaneous:
                    # solve regularized normal eqs. trace-by-trace
                    minv = torch.solve(datarn.reshape(nt0, nspatprod),
                                       PP).solution
                else:
                    # solve regularized normal equations simultaneously
                    PPop_reg = gMatrixMult(PP,
                                           dims=nspatprod,
                                           device=device,
                                           togpu=togpu,
                                           tocpu=tocpu)
                    minv = cg(PPop_reg.H * PPop_reg,
                              PPop_reg.H * 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 = gMatrixMult(PP,
                                       dims=nspatprod,
                                       device=device,
                                       togpu=togpu,
                                       tocpu=tocpu)
                minv = torch.solve(datarn.reshape(nt0, nspatprod),
                                   PPop_reg.A).solution
        else:
            # solve unregularized normal equations simultaneously with lop
            minv = cg(PPop.H * PPop, PPop.H * datar, **kwargs_solver)[0]
    else:
        if epsRL1 is None:
            # L2 inversion with spatial regularization
            if dims == 1:
                Regop = gSecondDerivative(nt0,
                                          device=device,
                                          togpu=togpu,
                                          tocpu=tocpu,
                                          dtype=PPop.dtype)
            elif dims == 2:
                Regop = gLaplacian((nt0, nx),
                                   device=device,
                                   togpu=togpu,
                                   tocpu=tocpu,
                                   dtype=PPop.dtype)
            else:
                Regop = gLaplacian((nt0, nx, ny),
                                   dirs=(1, 2),
                                   device=device,
                                   togpu=togpu,
                                   tocpu=tocpu,
                                   dtype=PPop.dtype)

            minv = RegularizedInversion(
                PPop, [Regop],
                data.flatten(),
                x0=None if m0 is None else m0.flatten(),
                epsRs=[epsR],
                **kwargs_solver)[0]
        else:
            # Blockiness-promoting inversion with spatial regularization
            raise NotImplementedError('SplitBregman not available...')

    # compute residual
    if epsR is None:
        datar -= PPop * minv.flatten()
    else:
        datar = data.flatten() - PPop * minv.flatten()

    # reshape inverted model and residual data
    if dims == 1:
        minv = minv.squeeze()
        datar = datar.squeeze()
    elif dims == 2:
        minv = minv.reshape(nt0, nx)
        datar = datar.reshape(nt0, nx)
    else:
        minv = minv.reshape(nt0, nx, ny)
        datar = datar.reshape(nt0, nx, ny)

    if m0 is not None and epsR is None:
        minv = minv + m0

    return minv, datar
示例#8
0
 def __truediv__(self, y, niter=None, tol=1e-4):
     xest = cg(self,
               y,
               niter=self.shape[1] if niter is None else niter,
               tol=tol)[0]
     return xest
示例#9
0
def test_Convolve1D(par):
    """Dot-test, comparison with pylops and inversion for Convolve1D
    operator
    """
    np.random.seed(10)

    #1D
    if par['dir'] == 0:
        gCop = gConvolve1D(par['nx'],
                           h=h1,
                           offset=par['offset'],
                           dtype=torch.float32)
        assert dottest(gCop, par['nx'], par['nx'], tol=1e-3)

        x = torch.zeros((par['nx']), dtype=torch.float32)
        x[par['nx'] // 2] = 1.

        # comparison with pylops
        Cop = Convolve1D(par['nx'],
                         h=h1.cpu().numpy(),
                         offset=par['offset'],
                         dtype='float32')
        assert_array_almost_equal(gCop * x, Cop * x.cpu().numpy(), decimal=3)
        #assert_array_equal(gCop * x, Cop * x.cpu().numpy())

        # inversion
        if par['offset'] == nfilt[0] // 2:
            # zero phase
            xcg = cg(gCop, gCop * x, niter=100)[0]
        else:
            # non-zero phase
            xcg = cg(gCop.H * gCop, gCop.H * (gCop * x), niter=100)[0]
        assert_array_almost_equal(x, xcg, decimal=1)

    # 1D on 2D
    gCop = gConvolve1D(par['ny'] * par['nx'],
                       h=h1,
                       offset=par['offset'],
                       dims=(par['ny'], par['nx']),
                       dir=par['dir'],
                       dtype=torch.float32)
    assert dottest(gCop,
                   par['ny'] * par['nx'],
                   par['ny'] * par['nx'],
                   tol=1e-3)

    x = torch.zeros((par['ny'], par['nx']), dtype=torch.float32)
    x[int(par['ny'] / 2 - 3):int(par['ny'] / 2 + 3),
      int(par['nx'] / 2 - 3):int(par['nx'] / 2 + 3)] = 1.
    x = x.flatten()

    # comparison with pylops
    Cop = Convolve1D(par['ny'] * par['nx'],
                     h=h1.cpu().numpy(),
                     offset=par['offset'],
                     dims=(par['ny'], par['nx']),
                     dir=par['dir'],
                     dtype='float32')
    assert_array_almost_equal(gCop * x, Cop * x.cpu().numpy(), decimal=3)
    # assert_array_equal(gCop * x, Cop * x.cpu().numpy())

    # inversion
    if par['offset'] == nfilt[0] // 2:
        # zero phase
        xcg = cg(gCop, gCop * x, niter=100)[0]
    else:
        # non-zero phase
        xcg = cg(gCop.H * gCop, gCop.H * (gCop * x), niter=100)[0]
    assert_array_almost_equal(x, xcg, decimal=1)

    # 1D on 3D
    gCop = gConvolve1D(par['nz'] * par['ny'] * par['nx'],
                       h=h1,
                       offset=par['offset'],
                       dims=(par['nz'], par['ny'], par['nx']),
                       dir=par['dir'],
                       dtype=torch.float32)
    assert dottest(gCop,
                   par['nz'] * par['ny'] * par['nx'],
                   par['nz'] * par['ny'] * par['nx'],
                   tol=1e-3)

    x = torch.zeros((par['nz'], par['ny'], par['nx']), dtype=torch.float32)
    x[int(par['nz'] / 2 - 3):int(par['nz'] / 2 + 3),
      int(par['ny'] / 2 - 3):int(par['ny'] / 2 + 3),
      int(par['nx'] / 2 - 3):int(par['nx'] / 2 + 3)] = 1.
    x = x.flatten()

    # comparison with pylops
    Cop = Convolve1D(par['nz'] * par['ny'] * par['nx'],
                     h=h1.cpu().numpy(),
                     offset=par['offset'],
                     dims=(par['nz'], par['ny'], par['nx']),
                     dir=par['dir'],
                     dtype='float32')
    assert_array_almost_equal(gCop * x, Cop * x.cpu().numpy(), decimal=3)

    # inversion
    if par['offset'] == nfilt[0] // 2:
        # zero phase
        xcg = cg(gCop, gCop * x, niter=100)[0]
    else:
        # non-zero phase
        xcg = cg(gCop.H * gCop, gCop.H * (gCop * x), niter=100)[0]
    assert_array_almost_equal(x, xcg, decimal=1)