def test_MDC_Nvirtualsources(par): """Dot-test and comparison with pylops for MDC operator of N virtual source """ if par['twosided']: par['nt2'] = 2*par['nt'] - 1 else: par['nt2'] = par['nt'] v = 1500 it0_m = 25 t0_m = it0_m * par['dt'] theta_m = 0 phi_m = 0 amp_m = 1. it0_G = np.array([25, 50, 75]) t0_G = it0_G * par['dt'] theta_G = (0, 0, 0) phi_G = (0, 0, 0) amp_G = (1., 0.6, 2.) # Create axis t, _, x, y = makeaxis(par) # Create wavelet wav = ricker(t[:41], f0=par['f0'])[0] # Generate model _, mwav = linear3d(x, x, t, v, t0_m, theta_m, phi_m, amp_m, wav) # Generate operator _, Gwav = linear3d(x, y, t, v, t0_G, theta_G, phi_G, amp_G, wav) # Add negative part to data and model if par['twosided']: mwav = np.concatenate((np.zeros((par['nx'], par['nx'], par['nt'] - 1)), mwav), axis=-1) Gwav = np.concatenate((np.zeros((par['ny'], par['nx'], par['nt'] - 1)), Gwav), axis=-1) # Define MDC linear operator Gwav_fft = np.fft.fft(Gwav, par['nt2'], axis=-1) Gwav_fft = Gwav_fft[..., :par['nfmax']] dMDCop = dMDC(da.from_array(Gwav_fft.transpose(2, 0, 1)), nt=par['nt2'], nv=par['nx'], dt=par['dt'], dr=par['dx'], twosided=par['twosided']) MDCop = MDC(Gwav_fft.transpose(2, 0, 1), nt=par['nt2'], nv=par['nx'], dt=par['dt'], dr=par['dx'], twosided=par['twosided'], transpose=False, dtype='float32') dottest(dMDCop, par['nt2'] * par['ny'] * par['nx'], par['nt2'] * par['nx'] * par['nx'], chunks=((par['nt2'] * par['ny'] * par['nx'], par['nt2'] * par['nx'] * par['nx']))) mwav = mwav.T dy = (dMDCop * da.from_array(mwav.flatten())).compute() y = MDCop * mwav.flatten() assert_array_almost_equal(dy, y, decimal=5)
def MakeSeismic_paper(samples, img_size=128, freq_low=5, freq_high=30, num_events=6): """Simple generation of noisy synthetic linear seismic events. Input: samples = Number of samples in your dataset you want Output: clean_signal, noise, noisy_signal""" random.seed(101) # empty list to be filled with numpy arrays clean_signal = [] noise = [] noisy_signal = [] # Parameters for the seismic canvas par = { 'ox': 0, 'dx': 12.5, 'nx': img_size, # offsets 'ot': 0, 'dt': 0.004, 'nt': img_size, # time 'f0': 20, 'nfmax': 50 } # Make canvas t, t2, x, y = makeaxis(par) # Make wavelet wav = ricker(np.arange(41) * par['dt'], f0=par['f0'])[0] # Parameters for events v = 1500 ang_range = 50 amp_range = 2 i = 0 amp_lim = 0.2 t0 = [0.2, 0.3, 0.5, 0.8] amp = [-0.5, 1.2, -1.5, 0.8] theta = [10, -10, 5, -30] while i < samples: # Making events mlin, mlinwav = linear2d(x, t, v, t0, theta, amp, wav) # Creating noise n = np.random.normal(loc=0, scale=0.25, size=( img_size, img_size)) * random.uniform(-2, 2) # Adding noise s = mlinwav ns = s + n clean_signal.append(s) noise.append(n) noisy_signal.append(ns) i += 1 return np.array(clean_signal).reshape( samples, img_size, img_size, 1), np.array(noise).reshape( samples, img_size, img_size, 1), np.array(noisy_signal).reshape(samples, img_size, img_size, 1)
def test_ChirpRadon3D(par): """Dot-test, forward, analytical inverse and sparse inverse for ChirpRadon3D operator """ parmod = { "ot": 0, "dt": 0.004, "nt": par["nt"], "ox": par["nhx"] * 10 / 2, "dx": 10, "nx": par["nhx"], "oy": par["nhy"] * 10 / 2, "dy": 10, "ny": par["nhy"], "f0": 40, } theta = [ 20, ] phi = [ 0, ] t0 = [ 0.1, ] amp = [ 1.0, ] # Create axis t, t2, hx, hy = makeaxis(parmod) # Create wavelet wav, _, wav_c = ricker(t[:41], f0=parmod["f0"]) # Generate model _, x = linear3d(hy, hx, t, 1500.0, t0, theta, phi, amp, wav) Rop = ChirpRadon3D( t, hy, hx, (par["pymax"], par["pxmax"]), engine=par["engine"], dtype="float64", **dict(flags=("FFTW_ESTIMATE",), threads=2) ) assert dottest( Rop, par["nhy"] * par["nhx"] * par["nt"], par["nhy"] * par["nhx"] * par["nt"] ) y = Rop * x.ravel() xinvana = Rop.inverse(y) assert_array_almost_equal(x.ravel(), xinvana, decimal=3) xinv, _, _ = FISTA(Rop, y, 30, eps=1e0, returninfo=True) assert_array_almost_equal(x.ravel(), xinv, decimal=3)
def test_ricker(par): """Create ricker wavelet and check size and central value""" t = np.arange(par["nt"]) * par["dt"] wav, twav, wcenter = ricker(t, f0=20) assert twav.size == (par["nt"] - 1 if par["nt"] % 2 == 0 else par["nt"]) * 2 - 1 assert wav.shape[0] == (par["nt"] - 1 if par["nt"] % 2 == 0 else par["nt"]) * 2 - 1 assert wav[wcenter] == 1
def test_MDC_1virtualsource(par): """Dot-test and inversion for MDC operator of 1 virtual source """ if par['twosided']: par['nt2'] = 2*par['nt'] - 1 else: par['nt2'] = par['nt'] v = 1500 t0_m = 0.2 theta_m = 0 amp_m = 1. t0_G = (0.1, 0.2, 0.3) theta_G = (0, 0, 0) phi_G = (0, 0, 0) amp_G = (1., 0.6, 2.) # Create axis t, _, x, y = makeaxis(par) # Create wavelet wav = ricker(t[:41], f0=par['f0'])[0] # Generate model _, mwav = linear2d(x, t, v, t0_m, theta_m, amp_m, wav) # Generate operator _, Gwav = linear3d(x, y, t, v, t0_G, theta_G, phi_G, amp_G, wav) # Add negative part to data and model if par['twosided']: mwav = np.concatenate((np.zeros((par['nx'], par['nt'] - 1)), mwav), axis=-1) Gwav = np.concatenate((np.zeros((par['ny'], par['nx'], par['nt'] - 1)), Gwav), axis=-1) # Define MDC linear operator Gwav_fft = np.fft.fft(Gwav, par['nt2'], axis=-1) Gwav_fft = Gwav_fft[..., :par['nfmax']] MDCop = MDC(Gwav_fft, nt=par['nt2'], nv=1, dt=par['dt'], dr=par['dx'], twosided=par['twosided'], dtype='float32') dottest(MDCop, par['nt2']*par['ny'], par['nt2']*par['nx']) # Create data d = MDCop * mwav.flatten() d = d.reshape(par['ny'], par['nt2']) # Apply mdd function minv = MDD(Gwav[:, :, par['nt']-1:] if par['twosided'] else Gwav, d[:, par['nt']-1:] if par['twosided'] else d, dt=par['dt'], dr=par['dx'], nfmax=par['nfmax'], twosided=par['twosided'], adjoint=False, psf=False, dtype='complex64', dottest=False, **dict(damp=1e-10, iter_lim=50, show=1)) assert_array_almost_equal(mwav, minv, decimal=2)
def test_ChirpRadon3D(par): """Dot-test, forward, analytical inverse and sparse inverse for ChirpRadon3D operator """ parmod = { 'ot': 0, 'dt': 0.004, 'nt': par['nt'], 'ox': par['nhx'] * 10 / 2, 'dx': 10, 'nx': par['nhx'], 'oy': par['nhy'] * 10 / 2, 'dy': 10, 'ny': par['nhy'], 'f0': 40 } theta = [ 20, ] phi = [ 0, ] t0 = [ 0.1, ] amp = [ 1., ] # Create axis t, t2, hx, hy = makeaxis(parmod) # Create wavelet wav, _, wav_c = ricker(t[:41], f0=parmod['f0']) # Generate model _, x = linear3d(hy, hx, t, 1500., t0, theta, phi, amp, wav) Rop = ChirpRadon3D(t, hy, hx, (par['pymax'], par['pxmax']), engine=par['engine'], dtype='float64', **dict(flags=('FFTW_ESTIMATE', ), threads=2)) assert dottest(Rop, par['nhy'] * par['nhx'] * par['nt'], par['nhy'] * par['nhx'] * par['nt']) y = Rop * x.ravel() xinvana = Rop.inverse(y) assert_array_almost_equal(x.ravel(), xinvana, decimal=3) xinv, _, _ = FISTA(Rop, y, 30, eps=1e0, returninfo=True) assert_array_almost_equal(x.ravel(), xinv, decimal=3)
def test_MDC_compute(par): """Ensure that forward and adjoint of MDC return numpy array when compute=True """ par['nt2'] = par['nt'] v = 1500 it0_m = 25 t0_m = it0_m * par['dt'] theta_m = 0 amp_m = 1. it0_G = np.array([25, 50, 75]) t0_G = it0_G * par['dt'] theta_G = (0, 0, 0) phi_G = (0, 0, 0) amp_G = (1., 0.6, 2.) # Create axis t, _, x, y = makeaxis(par) # Create wavelet wav = ricker(t[:41], f0=par['f0'])[0] # Generate model _, mwav = linear2d(x, t, v, t0_m, theta_m, amp_m, wav) # Generate operator _, Gwav = linear3d(x, y, t, v, t0_G, theta_G, phi_G, amp_G, wav) # Define MDC linear operator Gwav_fft = np.fft.fft(Gwav, par['nt2'], axis=-1) Gwav_fft = Gwav_fft[..., :par['nfmax']] dMDCop = dMDC(da.from_array(Gwav_fft.transpose(2, 0, 1)), nt=par['nt2'], nv=1, dt=par['dt'], dr=par['dx'], twosided=par['twosided'], todask=(True, True), compute=(True, True)) assert isinstance(dMDCop.matvec(np.ones(dMDCop.shape[1])), np.ndarray) assert isinstance(dMDCop.rmatvec(np.ones(dMDCop.shape[0])), np.ndarray)
def test_ChirpRadon2D(par): """Dot-test, forward, analytical inverse and sparse inverse for ChirpRadon2D operator """ parmod = { 'ot': 0, 'dt': 0.004, 'nt': par['nt'], 'ox': par['nhx'] * 10 / 2, 'dx': 10, 'nx': par['nhx'], 'f0': 40 } theta = [ 20, ] t0 = [ 0.1, ] amp = [ 1., ] # Create axis t, t2, hx, _ = makeaxis(parmod) # Create wavelet wav, _, wav_c = ricker(t[:41], f0=parmod['f0']) # Generate model _, x = linear2d(hx, t, 1500., t0, theta, amp, wav) Rop = ChirpRadon2D(t, hx, par['pxmax'], dtype='float64') assert dottest(Rop, par['nhx'] * par['nt'], par['nhx'] * par['nt']) y = Rop * x.ravel() xinvana = Rop.inverse(y) assert_array_almost_equal(x.ravel(), xinvana, decimal=3) xinv, _, _ = FISTA(Rop, y, 30, eps=1e0, returninfo=True) assert_array_almost_equal(x.ravel(), xinv, decimal=3)
def test_ChirpRadon2D(par): """Dot-test, forward, analytical inverse and sparse inverse for ChirpRadon2D operator """ parmod = { "ot": 0, "dt": 0.004, "nt": par["nt"], "ox": par["nhx"] * 10 / 2, "dx": 10, "nx": par["nhx"], "f0": 40, } theta = [ 20, ] t0 = [ 0.1, ] amp = [ 1.0, ] # Create axis t, t2, hx, _ = makeaxis(parmod) # Create wavelet wav, _, wav_c = ricker(t[:41], f0=parmod["f0"]) # Generate model _, x = linear2d(hx, t, 1500.0, t0, theta, amp, wav) Rop = ChirpRadon2D(t, hx, par["pxmax"], dtype="float64") assert dottest(Rop, par["nhx"] * par["nt"], par["nhx"] * par["nt"]) y = Rop * x.ravel() xinvana = Rop.inverse(y) assert_array_almost_equal(x.ravel(), xinvana, decimal=3) xinv, _, _ = FISTA(Rop, y, 30, eps=1e0, returninfo=True) assert_array_almost_equal(x.ravel(), xinv, decimal=3)
def test_MDC_1virtualsource(par): """Dot-test and inversion for MDC operator of 1 virtual source""" if par["twosided"]: par["nt2"] = 2 * par["nt"] - 1 else: par["nt2"] = par["nt"] v = 1500 it0_m = 25 t0_m = it0_m * par["dt"] theta_m = 0 amp_m = 1.0 it0_G = np.array([25, 50, 75]) t0_G = it0_G * par["dt"] theta_G = (0, 0, 0) phi_G = (0, 0, 0) amp_G = (1.0, 0.6, 2.0) # Create axis t, _, x, y = makeaxis(par) # Create wavelet wav = ricker(t[:41], f0=par["f0"])[0] # Generate model _, mwav = linear2d(x, t, v, t0_m, theta_m, amp_m, wav) # Generate operator _, Gwav = linear3d(x, y, t, v, t0_G, theta_G, phi_G, amp_G, wav) # Add negative part to data and model if par["twosided"]: mwav = np.concatenate((np.zeros((par["nx"], par["nt"] - 1)), mwav), axis=-1) Gwav = np.concatenate((np.zeros( (par["ny"], par["nx"], par["nt"] - 1)), Gwav), axis=-1) # Define MDC linear operator Gwav_fft = np.fft.fft(Gwav, par["nt2"], axis=-1) Gwav_fft = Gwav_fft[..., :par["nfmax"]] MDCop = MDC( Gwav_fft, nt=par["nt2"], nv=1, dt=par["dt"], dr=par["dx"], fftengine="fftw", twosided=par["twosided"], dtype="float32", ) dottest(MDCop, par["nt2"] * par["ny"], par["nt2"] * par["nx"]) # Create data d = MDCop * mwav.ravel() d = d.reshape(par["ny"], par["nt2"]) # Check that events are at correct time and correct amplitude for it, amp in zip(it0_G, amp_G): ittot = it0_m + it if par["twosided"]: ittot += par["nt"] - 1 assert (np.abs(d[par["ny"] // 2, ittot] - np.abs(wav**2).sum() * amp_m * amp * par["nx"] * par["dx"] * par["dt"] * np.sqrt(par["nt2"])) < 1e-2) # Check that MDC with prescaled=True gives same result MDCpreop = MDC( np.sqrt(par["nt2"]) * par["dt"] * par["dx"] * Gwav_fft, nt=par["nt2"], nv=1, dt=par["dt"], dr=par["dx"], fftengine="fftw", twosided=par["twosided"], prescaled=True, dtype="float32", ) dottest(MDCpreop, par["nt2"] * par["ny"], par["nt2"] * par["nx"]) dpre = MDCpreop * mwav.ravel() dpre = dpre.reshape(par["ny"], par["nt2"]) assert_array_equal(d, dpre) # Apply mdd function minv = MDD(Gwav[:, :, par["nt"] - 1:] if par["twosided"] else Gwav, d[:, par["nt"] - 1:] if par["twosided"] else d, dt=par["dt"], dr=par["dx"], nfmax=par["nfmax"], twosided=par["twosided"], adjoint=False, psf=False, dtype="complex64", dottest=False, **dict(damp=1e-10, iter_lim=50, show=0)) assert_array_almost_equal(mwav, minv, decimal=2) # Same tests for future behaviour (remove tests above in v2.0.0) MDCop = MDC( Gwav_fft.transpose(2, 0, 1), nt=par["nt2"], nv=1, dt=par["dt"], dr=par["dx"], twosided=par["twosided"], transpose=False, dtype="float32", ) dottest(MDCop, par["nt2"] * par["ny"], par["nt2"] * par["nx"]) mwav = mwav.T d = MDCop * mwav.ravel() d = d.reshape(par["nt2"], par["ny"]) for it, amp in zip(it0_G, amp_G): ittot = it0_m + it if par["twosided"]: ittot += par["nt"] - 1 assert (np.abs(d[ittot, par["ny"] // 2] - np.abs(wav**2).sum() * amp_m * amp * par["nx"] * par["dx"] * par["dt"] * np.sqrt(par["nt2"])) < 1e-2) minv = MDD(Gwav[:, :, par["nt"] - 1:] if par["twosided"] else Gwav, d[par["nt"] - 1:].T if par["twosided"] else d.T, dt=par["dt"], dr=par["dx"], nfmax=par["nfmax"], twosided=par["twosided"], add_negative=True, adjoint=False, psf=False, dtype="complex64", dottest=False, **dict(damp=1e-10, iter_lim=50, show=0)) assert_array_almost_equal(mwav, minv.T, decimal=2)
m = np.log(vp * rho) mback = filtfilt(np.ones(nsmooth) / float(nsmooth), 1, m) # 2d model inputfile = 'testdata/avo/poststack_model.npz' model = np.load(inputfile) x, z, m2d = model['x'][::3], model['z'][::3], \ np.log(model['model'][::3, ::3]) nx, nz = len(x), len(z) mback2d = filtfilt(np.ones(nsmooth) / float(nsmooth), 1, m2d, axis=0) mback2d = filtfilt(np.ones(nsmooth) / float(nsmooth), 1, mback2d, axis=1) # wavelet wav = ricker(t0[:ntwav // 2 + 1], 20)[0] par1 = { 'epsR': None, 'epsRL1': None, 'epsI': None, 'simultaneous': False } # unregularized par2 = { 'epsR': 1e-4, 'epsRL1': None, 'epsI': 1e-6, 'simultaneous': False } # regularized par3 = { 'epsR': None,
par1 = PAR.copy() # analytical par1['kind'] = 'analytical' par2 = PAR.copy() # inverse par2['kind'] = 'inverse' # separation params vel_sep = 1000.0 # velocity at separation level rho_sep = 1000.0 # density at separation level critical = 0.9 ntaper = 41 nfftf = 2**8 nfftk = 2**7 # axes and wavelet t, t2, x, y = makeaxis(PAR) wav = ricker(t[:41], f0=PAR['f0'])[0] @pytest.fixture(scope="module") def create_data2D(): """Create 2d dataset """ t0_plus = np.array([0.05, 0.12]) t0_minus = t0_plus + 0.04 vrms = np.array([1400., 1800.]) amp = np.array([1., -0.6]) _, p2d_minus = hyperbolic2d(x, t, t0_minus, vrms, amp, wav) _, p2d_plus = hyperbolic2d(x, t, t0_plus, vrms, amp, wav) UPop = \
sy = np.linspace(y.min(), y.max(), PAR['nsy']) sx = np.linspace(x.min(), x.max(), PAR['nsx']) syy, sxx = np.meshgrid(sy, sx, indexing='ij') s2d = np.vstack((sx, 2 * np.ones(PAR['nsx']))) s3d = np.vstack( (syy.ravel(), sxx.ravel(), 2 * np.ones(PAR['nsx'] * PAR['nsy']))) ry = np.linspace(y.min(), y.max(), PAR['nry']) rx = np.linspace(x.min(), x.max(), PAR['nrx']) ryy, rxx = np.meshgrid(ry, rx, indexing='ij') r2d = np.vstack((rx, 2 * np.ones(PAR['nrx']))) r3d = np.vstack( (ryy.ravel(), rxx.ravel(), 2 * np.ones(PAR['nrx'] * PAR['nry']))) wav, _, wavc = ricker(t[:41], f0=40) par1 = {'mode': 'analytic'} par2 = {'mode': 'eikonal'} par3 = {'mode': 'byot'} def test_identify_geometry(): """Identify geometry, check expected outputs """ # 2d ndims, shiftdim, dims, ny, nx, nz, ns, nr, dy, dx, dz, dsamp, origin = \ _identify_geometry(z, x, s2d, r2d) assert ndims == 2 assert shiftdim == 0 assert [1, 2] == [1, 2]
def test_MDC_Nvirtualsources(par): """Dot-test and inversion for MDC operator of N virtual source """ if par['twosided']: par['nt2'] = 2 * par['nt'] - 1 else: par['nt2'] = par['nt'] v = 1500 it0_m = 25 t0_m = it0_m * par['dt'] theta_m = 0 phi_m = 0 amp_m = 1. it0_G = np.array([25, 50, 75]) t0_G = it0_G * par['dt'] theta_G = (0, 0, 0) phi_G = (0, 0, 0) amp_G = (1., 0.6, 2.) # Create axis t, _, x, y = makeaxis(par) # Create wavelet wav = ricker(t[:41], f0=par['f0'])[0] # Generate model _, mwav = linear3d(x, x, t, v, t0_m, theta_m, phi_m, amp_m, wav) # Generate operator _, Gwav = linear3d(x, y, t, v, t0_G, theta_G, phi_G, amp_G, wav) # Add negative part to data and model if par['twosided']: mwav = np.concatenate((np.zeros( (par['nx'], par['nx'], par['nt'] - 1)), mwav), axis=-1) Gwav = np.concatenate((np.zeros( (par['ny'], par['nx'], par['nt'] - 1)), Gwav), axis=-1) # Define MDC linear operator Gwav_fft = np.fft.fft(Gwav, par['nt2'], axis=-1) Gwav_fft = Gwav_fft[..., :par['nfmax']] MDCop = MDC(Gwav_fft, nt=par['nt2'], nv=par['nx'], dt=par['dt'], dr=par['dx'], twosided=par['twosided'], dtype='float32') dottest(MDCop, par['nt2'] * par['ny'] * par['nx'], par['nt2'] * par['nx'] * par['nx']) # Create data d = MDCop * mwav.flatten() d = d.reshape(par['ny'], par['nx'], par['nt2']) # Check that events are at correct time for it, amp in zip(it0_G, amp_G): ittot = it0_m + it if par['twosided']: ittot += par['nt'] - 1 assert d[par['ny'] // 2, par['nx'] // 2, ittot] > \ d[par['ny'] // 2, par['nx'] // 2, ittot - 1] assert d[par['ny'] // 2, par['nx'] // 2, ittot] > \ d[par['ny'] // 2, par['nx'] // 2, ittot + 1] # Apply mdd function minv = MDD(Gwav[:, :, par['nt'] - 1:] if par['twosided'] else Gwav, d[:, :, par['nt'] - 1:] if par['twosided'] else d, dt=par['dt'], dr=par['dx'], nfmax=par['nfmax'], twosided=par['twosided'], adjoint=False, psf=False, dtype='complex64', dottest=False, **dict(damp=1e-10, iter_lim=50, show=1)) assert_array_almost_equal(mwav, minv, decimal=2) # Same tests for future behaviour (remove tests above in v2.0.0) MDCop = MDC(Gwav_fft.transpose(2, 0, 1), nt=par['nt2'], nv=par['nx'], dt=par['dt'], dr=par['dx'], twosided=par['twosided'], transpose=False, dtype='float32') dottest(MDCop, par['nt2'] * par['ny'] * par['nx'], par['nt2'] * par['nx'] * par['nx']) mwav = mwav.transpose(2, 0, 1) d = MDCop * mwav.flatten() d = d.reshape(par['nt2'], par['ny'], par['nx']) for it, amp in zip(it0_G, amp_G): ittot = it0_m + it if par['twosided']: ittot += par['nt'] - 1 assert d[ittot, par['ny'] // 2, par['nx'] // 2] > \ d[ittot - 1, par['ny'] // 2, par['nx'] // 2] assert d[ittot, par['ny'] // 2, par['nx'] // 2] > \ d[ittot + 1, par['ny'] // 2, par['nx'] // 2] minv = MDD( Gwav[:, :, par['nt'] - 1:] if par['twosided'] else Gwav, d[par['nt'] - 1:].transpose(1, 2, 0) if par['twosided'] else d.transpose(1, 2, 0), dt=par['dt'], dr=par['dx'], nfmax=par['nfmax'], twosided=par['twosided'], add_negative=True, adjoint=False, psf=False, dtype='complex64', dottest=False, **dict(damp=1e-10, iter_lim=50, show=1)) assert_array_almost_equal(mwav, minv.transpose(2, 0, 1), decimal=2)
m = np.log(vp * rho) mback = filtfilt(np.ones(nsmooth) / float(nsmooth), 1, m) # 2d model inputfile = 'testdata/avo/poststack_model.npz' model = np.load(inputfile) x, z, m2d = model['x'][::3], model['z'][::3], \ np.log(model['model'][::3, ::3]) nx, nz = len(x), len(z) mback2d = filtfilt(np.ones(nsmooth) / float(nsmooth), 1, m2d, axis=0) mback2d = filtfilt(np.ones(nsmooth) / float(nsmooth), 1, mback2d, axis=1) # stationary wavelet wav = ricker(t0[:ntwav // 2 + 1], 20)[0] # non-stationary wavelet f0s = np.flip(np.arange(nt0) * 0.05 + 3) wavs = np.array([ricker(t0[:ntwav], f0)[0] for f0 in f0s]) wavc = np.argmax(wavs[0]) par1 = { 'epsR': None, 'epsRL1': None, 'epsI': None, 'simultaneous': False } # unregularized par2 = { 'epsR': 1e-4, 'epsRL1': None,
# steps, such as angle muting. # # To get started, let us create a 2D seismic dataset containing some hyperbolic # events representing reflections from flat reflectors. # Events are created with a true RMS velocity, which we will be using as if we # picked them from, for example, a semblance panel. par = dict(ox=0, dx=40, nx=80, ot=0, dt=0.004, nt=520) t, _, x, _ = makeaxis(par) t0s_true = np.array([0.5, 1.22, 1.65]) vrms_true = np.array([2000.0, 2400.0, 2500.0]) amps = np.array([1, 0.2, 0.5]) freq = 10 # Hz wav, *_ = ricker(t[:41], f0=freq) _, data = hyperbolic2d(x, t, t0s_true, vrms_true, amp=amps, wav=wav) ############################################################################### # NMO correction plot pclip = 0.5 dmax = np.max(np.abs(data)) opts = dict( cmap="gray_r", extent=[x[0], x[-1], t[-1], t[0]], aspect="auto", vmin=-pclip * dmax, vmax=pclip * dmax,
############################################################################### # Let's start by creating a very simple 2d data composed of 3 linear events # input parameters par = {'ox': 0, 'dx': 2, 'nx': 70, 'ot': 0, 'dt': 0.004, 'nt': 80, 'f0': 20} v = 1500 t0_m = [0.1, 0.2, 0.28] theta_m = [0, 30, -80] phi_m = [0] amp_m = [1., -2, 0.5] # axis taxis, t2, xaxis, y = makeaxis(par) # wavelet wav = ricker(taxis[:41], f0=par['f0'])[0] # model _, x = linear2d(xaxis, taxis, v, t0_m, theta_m, amp_m, wav) ############################################################################### # We can now define the spatial locations along which the data has been # sampled. In this specific example we will assume that we have access only to # 40% of the 'original' locations. perc_subsampling = 0.6 nxsub = int(np.round(par['nx'] * perc_subsampling)) iava = np.sort(np.random.permutation(np.arange(par['nx']))[:nxsub]) # restriction operator Rop = pylops.Restriction(par['nx'] * par['nt'],
dt0 = 0.004 t0 = np.arange(nt0) * dt0 vp = 1200 + np.arange(nt0) + filtfilt( np.ones(5) / 5., 1, np.random.normal(0, 80, nt0)) rho = 1000 + vp + filtfilt(np.ones(5) / 5., 1, np.random.normal(0, 30, nt0)) vp[201:] += 500 rho[201:] += 100 m = np.log(vp * rho) # smooth model nsmooth = 100 mback = filtfilt(np.ones(nsmooth) / float(nsmooth), 1, m) # wavelet ntwav = 41 wav, twav, wavc = ricker(t0[:ntwav // 2 + 1], 20) # dense operator PPop_dense = pylops.avo.poststack.PoststackLinearModelling(wav, nt0=nt0, explicit=True) # lop operator PPop = pylops.avo.poststack.PoststackLinearModelling(wav, nt0=nt0) # data d_dense = PPop_dense * m.flatten() d = PPop * m # add noise dn_dense = d_dense + np.random.normal(0, 2e-2, d_dense.shape)
v = 1500 t0 = [0.1, 0.2, 0.3] theta = [0, 0, 0] amp = [1.0, -2, 0.5] # parabolic event tp0 = [0.13] px = [0] pxx = [5e-7] ampp = [0.7] # create axis taxis, taxis2, xaxis, yaxis = pylops.utils.seismicevents.makeaxis(par) # create wavelet wav = ricker(taxis[:41], f0=par["f0"])[0] # generate model y = (pylops.utils.seismicevents.linear2d(xaxis, taxis, v, t0, theta, amp, wav)[1] + pylops.utils.seismicevents.parabolic2d(xaxis, taxis, tp0, px, pxx, ampp, wav)[1]) ############################################################################### # We can now create the :py:class:`pylops.signalprocessing.Radon2D` operator. # We also apply its adjoint to the data to obtain a representation of those # 3 linear events overlapping to a parabolic event in the Radon domain. # Similarly, we feed the operator to a sparse solver like # :py:class:`pylops.optimization.sparsity.FISTA` to obtain a sparse # represention of the data in the Radon domain. At this point we try to filter # out the unwanted event. We can see how this is much easier for the sparse
import pytest import numpy as np from numpy.testing import assert_array_equal from pylops.utils.wavelets import ricker from pylops.utils.seismicevents import makeaxis, linear2d, linear3d from pylops.utils.seismicevents import parabolic2d, hyperbolic2d, hyperbolic3d # Wavelet wav = ricker(np.arange(41) * 0.004, f0=10)[0] par1 = { 'ot': 0, 'dt': 1, 'nt': 300, 'ox': 0, 'dx': 2, 'nx': 200, 'oy': 0, 'dy': 2, 'ny': 100 } # even axis par2 = { 'ot': 0, 'dt': 1, 'nt': 301, 'ox': -200, 'dx': 2, 'nx': 201,
rho[131:] += 100 vsvp = 0.5 m = np.stack((np.log(vp), np.log(vs), np.log(rho)), axis=1) # background model nsmooth = 50 mback = filtfilt(np.ones(nsmooth) / float(nsmooth), 1, m, axis=0) # angles ntheta = 21 thetamin, thetamax = 0, 40 theta = np.linspace(thetamin, thetamax, ntheta) # wavelet ntwav = 41 wav = ricker(t0[: ntwav // 2 + 1], 15)[0] # lop PPop = pylops.avo.prestack.PrestackLinearModelling( wav, theta, vsvp=vsvp, nt0=nt0, linearization="akirich" ) # dense PPop_dense = pylops.avo.prestack.PrestackLinearModelling( wav, theta, vsvp=vsvp, nt0=nt0, linearization="akirich", explicit=True ) # data lop dPP = PPop * m.ravel() dPP = dPP.reshape(nt0, ntheta)
def test_MDC_1virtualsource(par): """Dot-test and comparison with pylops for MDC operator of 1 virtual source """ if par['twosided']: par['nt2'] = 2 * par['nt'] - 1 else: par['nt2'] = par['nt'] v = 1500 it0_m = 25 t0_m = it0_m * par['dt'] theta_m = 0 amp_m = 1. it0_G = np.array([25, 50, 75]) t0_G = it0_G * par['dt'] theta_G = (0, 0, 0) phi_G = (0, 0, 0) amp_G = (1., 0.6, 2.) # Create axis t, _, x, y = makeaxis(par) # Create wavelet wav = ricker(t[:41], f0=par['f0'])[0] # Generate model _, mwav = linear2d(x, t, v, t0_m, theta_m, amp_m, wav) # Generate operator _, Gwav = linear3d(x, y, t, v, t0_G, theta_G, phi_G, amp_G, wav) # Add negative part to data and model if par['twosided']: mwav = np.concatenate((np.zeros((par['nx'], par['nt'] - 1)), mwav), axis=-1) Gwav = np.concatenate((np.zeros( (par['ny'], par['nx'], par['nt'] - 1)), Gwav), axis=-1) # Define MDC linear operator Gwav_fft = np.fft.fft(Gwav, par['nt2'], axis=-1) Gwav_fft = Gwav_fft[..., :par['nfmax']] dGwav_fft = da.from_array(Gwav_fft.transpose(2, 0, 1)) dMDCop = dMDC(dGwav_fft, nt=par['nt2'], nv=1, dt=par['dt'], dr=par['dx'], twosided=par['twosided']) MDCop = MDC(Gwav_fft.transpose(2, 0, 1), nt=par['nt2'], nv=1, dt=par['dt'], dr=par['dx'], twosided=par['twosided'], transpose=False, dtype='float32') dottest(dMDCop, par['nt2'] * par['ny'], par['nt2'] * par['nx'], chunks=((par['nt2'] * par['ny'], par['nt2'] * par['nx']))) # Compare results with pylops implementation mwav = mwav.T dy = dMDCop * da.from_array(mwav.flatten()) y = MDCop * mwav.flatten() assert_array_almost_equal(dy.compute(), y, decimal=5) # Apply mdd function dy = dy.reshape(par['nt2'], par['ny']) print(dy) minv = MDD(dGwav_fft, dy[par['nt'] - 1:] if par['twosided'] else dy, dt=par['dt'], dr=par['dx'], nfmax=par['nfmax'], twosided=par['twosided'], adjoint=False, dottest=False, **dict(niter=50)) print('minv', minv) assert_array_almost_equal(mwav, minv.compute(), decimal=2)
t0_m = [0.2] vrms_m = [700.0] amp_m = [1.0] t0_G = [0.2, 0.5, 0.7] vrms_G = [800.0, 1200.0, 1500.0] amp_G = [1.0, 0.6, 0.5] # Taper tap = taper3d(par["nt"], [par["ny"], par["nx"]], (5, 5), tapertype="hanning") # Create axis t, t2, x, y = makeaxis(par) # Create wavelet wav = ricker(t[:41], f0=par["f0"])[0] # Generate model m, mwav = hyperbolic2d(x, t, t0_m, vrms_m, amp_m, wav) # Generate operator G, Gwav = np.zeros((par["ny"], par["nx"], par["nt"])), np.zeros( (par["ny"], par["nx"], par["nt"])) for iy, y0 in enumerate(y): G[iy], Gwav[iy] = hyperbolic2d(x - y0, t, t0_G, vrms_G, amp_G, wav) G, Gwav = G * tap, Gwav * tap # Add negative part to data and model m = np.concatenate((np.zeros((par["nx"], par["nt"] - 1)), m), axis=-1) mwav = np.concatenate((np.zeros((par["nx"], par["nt"] - 1)), mwav), axis=-1) Gwav2 = np.concatenate((np.zeros((par["ny"], par["nx"], par["nt"] - 1)), Gwav),
par1 = PAR.copy() # analytical par1["kind"] = "analytical" par2 = PAR.copy() # inverse par2["kind"] = "inverse" # separation params vel_sep = 1000.0 # velocity at separation level rho_sep = 1000.0 # density at separation level critical = 0.99 ntaper = 5 nfftf = 2**6 nfftk = 2**6 # axes and wavelet t, t2, x, y = makeaxis(PAR) wav = ricker(t[:41], f0=PAR["f0"])[0] @pytest.fixture(scope="module") def create_data2D(): """Create 2d dataset""" t0_plus = np.array([0.05, 0.12]) t0_minus = t0_plus + 0.04 vrms = np.array([1400.0, 1800.0]) amp = np.array([1.0, -0.6]) _, p2d_minus = hyperbolic2d(x, t, t0_minus, vrms, amp, wav) _, p2d_plus = hyperbolic2d(x, t, t0_plus, vrms, amp, wav) UPop = UpDownComposition2D( PAR["nt"],
'nt': 200, 'f0': 40 } t0_plus = np.array([0.2, 0.5, 0.7]) t0_minus = t0_plus + 0.04 vrms = np.array([1400., 1500., 2000.]) amp = np.array([1., -0.6, 0.5]) vel_sep = 1000.0 # velocity at separation level rho_sep = 1000.0 # density at separation level # Create axis t, t2, x, y = makeaxis(par) # Create wavelet wav = ricker(t[:41], f0=par['f0'])[0] # Create data _, p_minus = hyperbolic2d(x, t, t0_minus, vrms, amp, wav) _, p_plus = hyperbolic2d(x, t, t0_plus, vrms, amp, wav) ############################################################################### # We can now combine them to create pressure and particle velocity data critical = 1.1 ntaper = 51 nfft = 2**10 # 2d fft operator FFTop = pylops.signalprocessing.FFT2D(dims=[par['nx'], par['nt']], nffts=[nfft, nfft], sampling=[par['dx'], par['dt']])
def MakeSeismic(samples, img_size=128, freq_low=5, freq_high=30, num_events=6): """Simple generation of noisy synthetic linear seismic events. Input: samples = Number of samples in your dataset you want Output: clean_signal, noise, noisy_signal""" random.seed(101) # empty list to be filled with numpy arrays clean_signal = [] noise = [] noisy_signal = [] # Parameters for the seismic canvas par = { 'ox': 0, 'dx': 12.5, 'nx': img_size, # offsets 'ot': 0, 'dt': 0.004, 'nt': img_size, # time 'f0': random.randint(5, 70), 'nfmax': 50 } # initial tests, max freq was 30 # Make canvas t, t2, x, y = makeaxis(par) # Make wavelet wav = ricker(np.arange(41) * par['dt'], f0=par['f0'])[0] # Parameters for events v = 1500 ang_range = 50 amp_range = 2 i = 0 amp_lim = 0.2 while i < samples: iEv = 0 t0 = [] theta = [] amp = [] while iEv <= num_events: # Time of events t0.append(random.uniform(t.min(), t.max()) * 0.7) # Angle of events theta.append(random.uniform(-ang_range, ang_range)) # Amplitude of events amp.append(random.uniform(-amp_range, amp_range)) # clipping events to be above -0.2 and 0.2 if amp[iEv] < 0: amp[iEv] = np.min([-amp_lim, amp[iEv]]) else: amp[iEv] = np.max([amp_lim, amp[iEv]]) iEv += 1 # Making events mlin, mlinwav = linear2d(x, t, v, t0, theta, amp, wav) # Creating noise n = np.random.normal(loc=0, scale=0.25, size=(img_size, img_size)) # Adding noise s = mlinwav ns = s + n clean_signal.append(s) noise.append(n) noisy_signal.append(ns) i += 1 return np.array(clean_signal).reshape( samples, img_size, img_size, 1), np.array(noise).reshape( samples, img_size, img_size, 1), np.array(noisy_signal).reshape(samples, img_size, img_size, 1)
print('PyLops-gpu working on %s...' % dev) plt.close('all') ############################################################################### # We will start by creating a zero signal of length :math:`nt` and we will # place a unitary spike at its center. We also create our filter to be # applied by means of :py:class:`pylops_gpu.signalprocessing.Convolve1D` # operator. nt = 1001 dt = 0.004 t = np.arange(nt)*dt x = torch.zeros(nt, dtype=torch.float32) x[int(nt/2)] = 1 h, th, hcenter = ricker(t[:101], f0=30) h = torch.from_numpy(h.astype(np.float32)) Cop = pylops_gpu.signalprocessing.Convolve1D(nt, h=h, offset=hcenter, 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)
def MakeSeismic_VN(samples, img_size=256, num_events=10): """Simple generation of noisy synthetic linear seismic events. Input: samples = Number of samples in your dataset you want Output: clean_signal, noise, noisy_signal""" random.seed(101) # empty list to be filled with numpy arrays clean_signal = [] noise = [] noisy_signal = [] # Parameters for the seismic canvas par = { 'ox': 0, 'dx': 12.5, 'nx': img_size, # offsets 'ot': 0, 'dt': 0.004, 'nt': img_size, # time 'f0': random.randint(5, 70), 'nfmax': 50 } # initial tests, max freq was 50 # Make canvas t, t2, x, y = makeaxis(par) # Make wavelet wav = ricker(np.arange(41) * par['dt'], f0=par['f0'])[0] # Parameters for events v = 1500 # orig amp range was 50 ang_range = 80 amp_range = 2 i = 0 amp_lim = 0.8 lv = 1500 hv = 5000 while i < samples: iEv_l = 0 iEv_h = 0 t0_l = [] t0_h = [] theta_l = [] amp_l = [] amp_h = [] vel_h = [] num_lin = random.randint(2, num_events) num_hyp = num_events - num_lin while iEv_l <= num_lin: # Time of events t0_l.append(random.uniform(t.min(), t.max()) * 0.7) # Angle of events theta_l.append(random.uniform(-ang_range, ang_range)) # Amplitude of events amp_l.append(random.uniform(-amp_range, amp_range)) # clipping events to be above -0.2 and 0.2 if amp_l[iEv_l] < 0: amp_l[iEv_l] = np.min([-amp_lim, amp_l[iEv_l]]) else: amp_l[iEv_l] = np.max([amp_lim, amp_l[iEv_l]]) iEv_l += 1 while iEv_h <= num_hyp: # Time of events t0_h.append(random.uniform(t.min(), t.max()) * 0.7) # Amplitude of events amp_h.append(random.uniform(-amp_range, amp_range)) # velocity of hyperbolic events vel_h.append(random.uniform(lv, hv)) # clipping events to be above -0.2 and 0.2 if amp_h[iEv_h] < 0: amp_h[iEv_h] = np.min([-amp_lim, amp_h[iEv_h]]) else: amp_h[iEv_h] = np.max([amp_lim, amp_h[iEv_h]]) iEv_h += 1 # Making events mlin, mlinwav = linear2d(x, t, v, t0_l, theta_l, amp_l, wav) # print (t0_h, vel_h, amp_h) # Generate model m, mwav = hyperbolic2d(x, t, t0_h, vel_h, amp_h, wav) s = mwav + mlinwav # Creating and adding noise ns1 = random_noise(s, 'speckle', clip=False, var=random.uniform(0.2, 2)) ns2 = random_noise(s, 'gaussian', clip=False, var=random.uniform(0.05, 0.5)) ns3 = random_noise(s, 's&p', clip=False, amount=random.uniform(0.05, 0.2)) # Noise n1 = ns1 - s n2 = ns2 - s n3 = ns3 - s clean_signal.append(s) clean_signal.append(s) clean_signal.append(s) noise.append(n1) noise.append(n2) noise.append(n3) noisy_signal.append(ns1) noisy_signal.append(ns2) noisy_signal.append(ns3) i += 1 return np.array(clean_signal).reshape( samples * 3, img_size, img_size, 1), np.array(noise).reshape( samples * 3, img_size, img_size, 1), np.array(noisy_signal).reshape(samples * 3, img_size, img_size, 1)