Skip to content

Commit 3e48cbf

Browse files
authored
Merge pull request #555 from mrava87/feat-vzdegh
feature: vz deghosting
2 parents 5f32e0b + a227115 commit 3e48cbf

File tree

2 files changed

+56
-29
lines changed

2 files changed

+56
-29
lines changed

pylops/waveeqprocessing/oneway.py

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ def Deghosting(
193193
dr: Sequence[float],
194194
vel: float,
195195
zrec: float,
196+
kind: Optional[str] = "p",
196197
pd: Optional[NDArray] = None,
197198
win: Optional[NDArray] = None,
198199
npad: Union[Tuple[int], Tuple[int, int]] = (11, 11),
@@ -206,13 +207,15 @@ def Deghosting(
206207
) -> Tuple[NDArray, NDArray]:
207208
r"""Wavefield deghosting.
208209
209-
Apply seismic wavefield decomposition from single-component (pressure)
210-
data. This process is also generally referred to as model-based deghosting.
210+
Apply seismic wavefield decomposition from single-component (pressure or
211+
vertical velocity) data. This process is also generally referred to as
212+
model-based deghosting.
211213
212214
Parameters
213215
----------
214216
p : :obj:`np.ndarray`
215-
Pressure data of of size :math:`\lbrack n_{r_x}\,(\times n_{r_y})
217+
Pressure (or vertical velocity) data of of size
218+
:math:`\lbrack n_{r_x}\,(\times n_{r_y})
216219
\times n_t \rbrack` (or :math:`\lbrack n_{r_{x,\text{sub}}}\,
217220
(\times n_{r_{y,\text{sub}}}) \times n_t \rbrack`
218221
in case a ``restriction`` operator is provided. Note that
@@ -231,6 +234,8 @@ def Deghosting(
231234
Velocity along the receiver array (must be constant)
232235
zrec : :obj:`float`
233236
Depth of receiver array
237+
kind : :obj:`str`, optional
238+
Type of data (``p`` or ``vz``)
234239
pd : :obj:`np.ndarray`, optional
235240
Direct arrival to be subtracted from ``p``
236241
win : :obj:`np.ndarray`, optional
@@ -260,14 +265,19 @@ def Deghosting(
260265
Returns
261266
-------
262267
pup : :obj:`np.ndarray`
263-
Up-going wavefield
268+
Up-going pressure (or particle velocity) wavefield
264269
pdown : :obj:`np.ndarray`
265-
Down-going wavefield
270+
Down-going (or particle velocity) wavefield
271+
272+
Raises
273+
------
274+
ValueError
275+
If ``kind`` is not "p" or "vz".
266276
267277
Notes
268278
-----
269-
Up- and down-going components of seismic data :math:`p^-(x, t)`
270-
and :math:`p^+(x, t)` can be estimated from single-component data
279+
The up- and down-going components of a seismic data (:math:`p^-(x, t)`
280+
and :math:`p^+(x, t)`) can be estimated from single-component data
271281
:math:`p(x, t)` using a ghost model.
272282
273283
The basic idea [1]_ is that of using a one-way propagator in the f-k domain
@@ -284,16 +294,22 @@ def Deghosting(
284294
In a matrix form we can thus write the total wavefield as:
285295
286296
.. math::
287-
\mathbf{p} - \mathbf{p_d} = (\mathbf{I} + \Phi) \mathbf{p}^-
297+
\mathbf{p} - \mathbf{p_d} = (\mathbf{I} \pm \Phi) \mathbf{p}^-
288298
289299
where :math:`\Phi` is one-way propagator implemented via the
290-
:class:`pylops.waveeqprocessing.PhaseShift` operator.
300+
:class:`pylops.waveeqprocessing.PhaseShift` operator. Note that :math:`+` is
301+
used for the pressure data, whilst :math:`-` is used for the vertical velocity
302+
data.
291303
292304
.. [1] Amundsen, L., 1993, Wavenumber-based filtering of marine point-source
293305
data: GEOPHYSICS, 58, 1335–1348.
294306
295-
296307
"""
308+
# Check kind
309+
if kind not in ["p", "vz"]:
310+
raise ValueError("kind must be p or vz")
311+
312+
# Identify dimensions
297313
ndims = p.ndim
298314
if ndims == 2:
299315
dims = (nt, nr)
@@ -328,7 +344,11 @@ def Deghosting(
328344
)
329345

330346
# Decomposition operator
331-
Dupop = Identity(nt * nrs, dtype=p.dtype) + Pop
347+
if kind == "p":
348+
Dupop = Identity(nt * nrs, dtype=p.dtype) + Pop
349+
else:
350+
Dupop = Identity(nt * nrs, dtype=p.dtype) - Pop
351+
332352
if dottest:
333353
Dottest(Dupop, nt * nrs, nt * nrs, verb=True)
334354

pytests/test_oneway.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
"f0": 40,
2323
}
2424

25-
par1 = {"ny": 8, "nx": 10, "nt": 20, "dtype": "float32"} # even
26-
par2 = {"ny": 9, "nx": 11, "nt": 21, "dtype": "float32"} # odd
25+
par1 = {"ny": 8, "nx": 10, "nt": 20, "kind": "p", "dtype": "float32"} # even, p
26+
par2 = {"ny": 9, "nx": 11, "nt": 21, "kind": "p", "dtype": "float32"} # odd, p
27+
par1v = {"ny": 8, "nx": 10, "nt": 20, "kind": "vz", "dtype": "float32"} # even, vz
28+
par2v = {"ny": 9, "nx": 11, "nt": 21, "kind": "vz", "dtype": "float32"} # odd, vz
2729

2830
# deghosting params
2931
vel_sep = 1000.0 # velocity at separation level
@@ -34,27 +36,31 @@
3436
wav = ricker(t[:41], f0=parmod["f0"])[0]
3537

3638

37-
@pytest.fixture(scope="module")
39+
@pytest.fixture
3840
def create_data2D():
3941
"""Create 2d dataset"""
40-
t0_plus = np.array([0.02, 0.08])
41-
t0_minus = t0_plus + 0.04
42-
vrms = np.array([1400.0, 1800.0])
43-
amp = np.array([1.0, -0.6])
4442

45-
p2d_minus = hyperbolic2d(x, t, t0_minus, vrms, amp, wav)[1].T
43+
def core(datakind):
44+
t0_plus = np.array([0.02, 0.08])
45+
t0_minus = t0_plus + 0.04
46+
vrms = np.array([1400.0, 1800.0])
47+
amp = np.array([1.0, -0.6])
4648

47-
kx = np.fft.ifftshift(np.fft.fftfreq(parmod["nx"], parmod["dx"]))
48-
freq = np.fft.rfftfreq(parmod["nt"], parmod["dt"])
49+
p2d_minus = hyperbolic2d(x, t, t0_minus, vrms, amp, wav)[1].T
4950

50-
Pop = -PhaseShift(vel_sep, 2 * zrec, parmod["nt"], freq, kx)
51+
kx = np.fft.ifftshift(np.fft.fftfreq(parmod["nx"], parmod["dx"]))
52+
freq = np.fft.rfftfreq(parmod["nt"], parmod["dt"])
5153

52-
# Decomposition operator
53-
Dupop = Identity(parmod["nt"] * parmod["nx"]) + Pop
54+
Pop = -PhaseShift(vel_sep, 2 * zrec, parmod["nt"], freq, kx)
5455

55-
p2d = Dupop * p2d_minus.ravel()
56-
p2d = p2d.reshape(parmod["nt"], parmod["nx"])
57-
return p2d, p2d_minus
56+
# Decomposition operator
57+
Dupop = Identity(parmod["nt"] * parmod["nx"]) + datakind * Pop
58+
59+
p2d = Dupop * p2d_minus.ravel()
60+
p2d = p2d.reshape(parmod["nt"], parmod["nx"])
61+
return p2d, p2d_minus
62+
63+
return core
5864

5965

6066
@pytest.mark.parametrize("par", [(par1), (par2)])
@@ -87,10 +93,10 @@ def test_PhaseShift_3dsignal(par):
8793
)
8894

8995

90-
@pytest.mark.parametrize("par", [(par1), (par2)])
96+
@pytest.mark.parametrize("par", [(par1), (par2), (par1v), (par2v)])
9197
def test_Deghosting_2dsignal(par, create_data2D):
9298
"""Deghosting of 2d data"""
93-
p2d, p2d_minus = create_data2D
99+
p2d, p2d_minus = create_data2D(1 if par["kind"] is "p" else -1)
94100

95101
p2d_minus_inv, p2d_plus_inv = Deghosting(
96102
p2d,
@@ -100,6 +106,7 @@ def test_Deghosting_2dsignal(par, create_data2D):
100106
parmod["dx"],
101107
vel_sep,
102108
zrec,
109+
kind=par["kind"],
103110
win=np.ones_like(p2d),
104111
npad=0,
105112
ntaper=0,

0 commit comments

Comments
 (0)