Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
5608889
fix: avoid upcasting to fp64 in Bilinear
mrava87 Apr 26, 2026
4531ec8
test: started to add checks on type in test_basicoperators
mrava87 Apr 26, 2026
7f4e91a
test: finalized to add checks on type in test_basicoperators
mrava87 Apr 26, 2026
ed3111f
fix: fix casting of dtype for AVOLinearModelling
mrava87 Apr 26, 2026
e8382f1
test: improved tests for poststack (including dtype check)
mrava87 Apr 27, 2026
4d6d4c2
fix: use rcond for cupy tests
mrava87 Apr 27, 2026
8c12393
minor: relax tolerance for cupy tests to pass
mrava87 Apr 27, 2026
6b6127b
test: added more dtype checks to tests
mrava87 Apr 27, 2026
f8d5929
fix: change Laplacian creation to avoid unwanted upcasting (plus tests)
mrava87 Apr 28, 2026
3392138
minor: relax tol for fp32 dottest in derivatives
mrava87 Apr 29, 2026
5f2b5eb
minor: relax tol for fp32 dottest in dct
mrava87 Apr 29, 2026
5e47847
minor: relax tol more for fp32 dottest in dct
mrava87 Apr 29, 2026
c802882
minor: bring back less conservative tol for fp32 dottest in dct
mrava87 Apr 29, 2026
00fd217
relax tol for fp32 dottest in causalintegration
mrava87 Apr 29, 2026
f10729f
test: added dtype checks to test_diagonal
mrava87 May 1, 2026
ad7f0ec
test: added dtype checks to test_dwts
mrava87 May 1, 2026
ce92891
test: added dtype checks to test_interp and fix dtype for linear and …
mrava87 May 1, 2026
6de47c7
test: added dtype checks to more tests
mrava87 May 4, 2026
7b44a1b
minor: fix rtol in dottest of test_kroneker
mrava87 May 4, 2026
e815e4d
test: added dtype checks for marchenko and fix operator
mrava87 May 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion pylops/avo/avo.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,9 @@ def __init__(
dimsd += self.spatdims
super().__init__(dtype=np.dtype(dtype), dims=dims, dimsd=dimsd, name=name)

self.G = self.ncp.concatenate([gs.T[:, self.ncp.newaxis] for gs in Gs], axis=1)
self.G = self.ncp.concatenate(
[gs.astype(dtype).T[:, self.ncp.newaxis] for gs in Gs], axis=1
)
# add dimensions to G to account for horizonal axes
for _ in range(len(self.spatdims)):
self.G = self.G[..., np.newaxis]
Expand Down
7 changes: 6 additions & 1 deletion pylops/basicoperators/laplacian.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
__all__ = ["Laplacian"]

import numpy as np

from pylops import LinearOperator
from pylops.basicoperators import SecondDerivative
Expand Down Expand Up @@ -124,13 +125,17 @@ def _calc_l2op(
kind: Tderivkind,
dtype: DTypeLike,
):
weights = np.array(weights, dtype=dtype)
sampling = np.array(sampling, dtype=dtype)
l2op = SecondDerivative(
dims, axis=axes[0], sampling=sampling[0], edge=edge, kind=kind, dtype=dtype
)
dims = l2op.dims
l2op *= weights[0]
for ax, samp, weight in zip(axes[1:], sampling[1:], weights[1:], strict=True):
l2op += weight * SecondDerivative(
tmpop = SecondDerivative(
dims, axis=ax, sampling=samp, edge=edge, kind=kind, dtype=dtype
)
tmpop *= weight
l2op += tmpop
return l2op
5 changes: 3 additions & 2 deletions pylops/signalprocessing/bilinear.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ def __init__(
)

ncp = get_array_module(iava)

# check non-unique pairs (works only with numpy arrays)
_ensure_iava_is_unique(
iava=to_numpy(iava),
Expand All @@ -141,10 +142,10 @@ def __init__(
# find indices and weights
self.iava_t = ncp.floor(iava[0]).astype(int)
self.iava_b = self.iava_t + 1
self.weights_tb = iava[0] - self.iava_t
self.weights_tb = (iava[0] - self.iava_t).astype(self.dtype)
self.iava_l = ncp.floor(iava[1]).astype(int)
self.iava_r = self.iava_l + 1
self.weights_lr = iava[1] - self.iava_l
self.weights_lr = (iava[1] - self.iava_l).astype(self.dtype)

# expand dims to weights for nd-arrays
if ndims > 2:
Expand Down
4 changes: 2 additions & 2 deletions pylops/signalprocessing/interp.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def _linearinterp(
# find indices and weights
iva_l = ncp.floor(iava).astype(int)
iva_r = iva_l + 1
weights = iava - iva_l
weights = (iava - iva_l).astype(dtype)

# create operators
Op = Diagonal(1 - weights, dims=dimsd, axis=axis, dtype=dtype) * Restriction(
Expand All @@ -81,7 +81,7 @@ def _sincinterp(
nreg = dims[axis]
ireg = ncp.arange(nreg)
sinc = ncp.tile(iava[:, np.newaxis], (1, nreg)) - ncp.tile(ireg, (len(iava), 1))
sinc = ncp.sinc(sinc)
sinc = ncp.sinc(sinc).astype(dtype)

# identify additional dimensions and create MatrixMult operator
otherdims = np.array(dims)
Expand Down
54 changes: 30 additions & 24 deletions pylops/waveeqprocessing/marchenko.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,13 +301,14 @@ def __init__(

# Add negative time to reflection data and convert to frequency
if not np.iscomplexobj(R):
dtypec = (np.empty(0, dtype=dtype) + 1j * np.empty(0, dtype=dtype)).dtype
Rtwosided = np.concatenate(
(self.ncp.zeros((self.ns, self.nr, self.nt - 1), dtype=R.dtype), R),
axis=-1,
)
Rtwosided_fft = np.fft.rfft(Rtwosided, self.nt2, axis=-1) / np.sqrt(
self.nt2
)
).astype(dtypec)
self.Rtwosided_fft = Rtwosided_fft[..., :nfmax]
else:
self.Rtwosided_fft = R
Expand Down Expand Up @@ -427,13 +428,12 @@ def apply_onepoint(
shift=-1,
dtype=self.dtype,
)
Wop = Diagonal(w.T.ravel())
Iop = Identity(self.nr * self.nt2)
Wop = Diagonal(w.T.ravel(), dtype=self.dtype)
Iop = Identity(self.nr * self.nt2, dtype=self.dtype)
Mop = Block(
[[Iop, -1 * Wop * Rop], [-1 * Wop * Rollop * R1op, Iop]]
) * BlockDiag([Wop, Wop])
Gop = Block([[Iop, -1 * Rop], [-1 * Rollop * R1op, Iop]])

[[Iop, -1 * Wop * Rop], [-1 * Wop * Rollop * R1op, Iop]], dtype=self.dtype
) * BlockDiag([Wop, Wop], dtype=self.dtype)
Gop = Block([[Iop, -1 * Rop], [-1 * Rollop * R1op, Iop]], dtype=self.dtype)
if dottest:
Dottest(
Gop,
Expand All @@ -443,7 +443,6 @@ def apply_onepoint(
verb=True,
backend=get_module_name(self.ncp),
)
if dottest:
Dottest(
Mop,
2 * self.ns * self.nt2,
Expand All @@ -457,10 +456,14 @@ def apply_onepoint(
if G0 is None:
if self.wav is not None and nfft is not None:
G0 = (
directwave(
self.wav, trav, self.nt, self.dt, nfft=nfft, derivative=True
(
directwave(
self.wav, trav, self.nt, self.dt, nfft=nfft, derivative=True
)
)
).T
.astype(self.dtype)
.T
)
G0 = to_cupy_conditional(self.Rtwosided_fft, G0)
else:
msg = "wav and/or nfft are not provided. Provide either G0 or wav and nfft..."
Expand Down Expand Up @@ -634,12 +637,12 @@ def apply_multiplepoints(
shift=-1,
dtype=self.dtype,
)
Wop = Diagonal(w.transpose(2, 0, 1).ravel())
Wop = Diagonal(w.transpose(2, 0, 1).ravel(), dtype=self.dtype)
Iop = Identity(self.nr * nvs * self.nt2)
Mop = Block(
[[Iop, -1 * Wop * Rop], [-1 * Wop * Rollop * R1op, Iop]]
) * BlockDiag([Wop, Wop])
Gop = Block([[Iop, -1 * Rop], [-1 * Rollop * R1op, Iop]])
[[Iop, -1 * Wop * Rop], [-1 * Wop * Rollop * R1op, Iop]], dtype=self.dtype
) * BlockDiag([Wop, Wop], dtype=self.dtype)
Gop = Block([[Iop, -1 * Rop], [-1 * Rollop * R1op, Iop]], dtype=self.dtype)

if dottest:
Dottest(
Expand All @@ -650,7 +653,6 @@ def apply_multiplepoints(
verb=True,
backend=get_module_name(self.ncp),
)
if dottest:
Dottest(
Mop,
2 * self.ns * nvs * self.nt2,
Expand All @@ -666,15 +668,19 @@ def apply_multiplepoints(
G0 = np.zeros((self.nr, nvs, self.nt), dtype=self.dtype)
for ivs in range(nvs):
G0[:, ivs] = (
directwave(
self.wav,
trav[:, ivs],
self.nt,
self.dt,
nfft=nfft,
derivative=True,
(
directwave(
self.wav,
trav[:, ivs],
self.nt,
self.dt,
nfft=nfft,
derivative=True,
)
)
).T
.astype(self.dtype)
.T
)
G0 = to_cupy_conditional(self.Rtwosided_fft, G0)
else:
msg = "wav and/or nfft are not provided. Provide either G0 or wav and nfft..."
Expand Down
27 changes: 21 additions & 6 deletions pytests/test_avo.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,24 +141,39 @@ def test_zoeppritz_and_approx_multipleangles():


@pytest.mark.parametrize("par", [(par1), (par2), (par3), (par4)])
def test_AVOLinearModelling(par):
@pytest.mark.parametrize("dtype", [np.float32, np.float64])
def test_AVOLinearModelling(par, dtype):
"""Dot-test and inversion for AVOLinearModelling"""
AVOop = AVOLinearModelling(
np.asarray(theta),
vsvp=par["vsvp"] if isinstance(par["vsvp"], float) else np.asarray(par["vsvp"]),
np.asarray(theta).astype(dtype),
vsvp=par["vsvp"]
if isinstance(par["vsvp"], float)
else np.asarray(par["vsvp"]).astype(dtype),
nt0=nt0,
linearization=par["linearization"],
dtype=dtype,
)
assert dottest(
AVOop,
ntheta * nt0,
3 * nt0,
rtol=1e-4 if dtype == np.float32 else 1e-6,
backend=backend,
)
assert dottest(AVOop, ntheta * nt0, 3 * nt0, backend=backend)

d = AVOop * np.asarray(m).astype(dtype)
madj = AVOop.H * d
minv = lsqr(
AVOop,
AVOop * np.asarray(m),
x0=np.zeros_like(m),
d,
x0=np.zeros_like(m).astype(dtype),
damp=1e-20,
niter=1000,
atol=1e-8,
btol=1e-8,
show=0,
)[0]

assert d.dtype == dtype
assert madj.dtype == dtype
assert_array_almost_equal(m, minv, decimal=3)
Loading
Loading