Skip to content

Commit b79dab2

Browse files
committed
test: added dtype checks for sliding (and fix issues with tap dtype and internal ops
1 parent 4d14737 commit b79dab2

4 files changed

Lines changed: 119 additions & 54 deletions

File tree

pylops/signalprocessing/sliding1d.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ def __init__(
199199
self.tapertype = tapertype
200200
self.savetaper = savetaper
201201
if self.tapertype is not None:
202-
tap = taper(nwin, nover, tapertype=self.tapertype)
202+
tap = taper(nwin, nover, tapertype=self.tapertype).astype(Op.dtype)
203203
tapin = tap.copy()
204204
tapin[:nover] = 1
205205
tapend = tap.copy()
@@ -247,7 +247,7 @@ def _matvec_savetaper(self, x: NDArray) -> NDArray:
247247
self.taps = to_cupy_conditional(x, self.taps)
248248
y = ncp.zeros(self.dimsd, dtype=self.dtype)
249249
if self.simOp:
250-
x = self.Op @ x
250+
x = self.Op.matvec(x.ravel()).reshape(self.Op.dimsd)
251251
if self.tapertype is not None:
252252
x = self.taps * x
253253
for iwin0 in range(self.dims[0]):
@@ -270,7 +270,7 @@ def _rmatvec_savetaper(self, x: NDArray) -> NDArray:
270270
if self.tapertype is not None:
271271
ywins = ywins * self.taps
272272
if self.simOp:
273-
y = self.Op.H @ ywins
273+
y = self.Op.rmatvec(ywins.ravel())
274274
else:
275275
y = ncp.zeros(self.dims, dtype=self.dtype)
276276
for iwin0 in range(self.dims[0]):
@@ -284,7 +284,7 @@ def _matvec_nosavetaper(self, x: NDArray) -> NDArray:
284284
self.taps = to_cupy_conditional(x, self.taps)
285285
y = ncp.zeros(self.dimsd, dtype=self.dtype)
286286
if self.simOp:
287-
x = self.Op @ x
287+
x = self.Op.matvec(x.ravel()).reshape(self.Op.dimsd)
288288
for iwin0 in range(self.dims[0]):
289289
if self.simOp:
290290
xxwin = x[iwin0]
@@ -311,7 +311,7 @@ def _rmatvec_nosavetaper(self, x: NDArray) -> NDArray:
311311
if self.tapertype is not None:
312312
for iwin0 in range(self.dims[0]):
313313
ywins = self._apply_taper(ywins, iwin0)
314-
y = self.Op.H @ ywins
314+
y = self.Op.rmatvec(ywins.ravel())
315315
else:
316316
y = ncp.zeros(self.dims, dtype=self.dtype)
317317
for iwin0 in range(self.dims[0]):

pylops/signalprocessing/sliding2d.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,9 @@ def __init__(
236236
self.tapertype = tapertype
237237
self.savetaper = savetaper
238238
if self.tapertype is not None:
239-
tap = taper2d(dimsd[1], nwin, nover, tapertype=self.tapertype)
239+
tap = taper2d(dimsd[1], nwin, nover, tapertype=self.tapertype).astype(
240+
Op.dtype
241+
)
240242
tapin = tap.copy()
241243
tapin[:nover] = 1
242244
tapend = tap.copy()
@@ -286,7 +288,7 @@ def _matvec_savetaper(self, x: NDArray) -> NDArray:
286288
self.taps = to_cupy_conditional(x, self.taps)
287289
y = ncp.zeros(self.dimsd, dtype=self.dtype)
288290
if self.simOp:
289-
x = self.Op @ x
291+
x = self.Op.matvec(x.ravel()).reshape(self.Op.dimsd)
290292
for iwin0 in range(self.dims[0]):
291293
if self.simOp:
292294
xx = x[iwin0].reshape(self.nwin, self.dimsd[-1])
@@ -311,7 +313,7 @@ def _rmatvec_savetaper(self, x: NDArray) -> NDArray:
311313
if self.tapertype is not None:
312314
ywins = ywins * self.taps
313315
if self.simOp:
314-
y = self.Op.H @ ywins
316+
y = self.Op.rmatvec(ywins.ravel()).reshape(self.dims)
315317
else:
316318
y = ncp.zeros(self.dims, dtype=self.dtype)
317319
for iwin0 in range(self.dims[0]):
@@ -327,7 +329,7 @@ def _matvec_nosavetaper(self, x: NDArray) -> NDArray:
327329
self.taps = to_cupy_conditional(x, self.taps)
328330
y = ncp.zeros(self.dimsd, dtype=self.dtype)
329331
if self.simOp:
330-
x = self.Op @ x
332+
x = self.Op.matvec(x.ravel()).reshape(self.Op.dimsd)
331333
for iwin0 in range(self.dims[0]):
332334
if self.simOp:
333335
xxwin = x[iwin0].reshape(self.nwin, self.dimsd[-1])
@@ -360,7 +362,7 @@ def _rmatvec_nosavetaper(self, x: NDArray) -> NDArray:
360362
if self.tapertype is not None:
361363
for iwin0 in range(self.dims[0]):
362364
ywins = self._apply_taper(ywins, iwin0)
363-
y = self.Op.H @ ywins
365+
y = self.Op.rmatvec(ywins.ravel()).reshape(self.dims)
364366
else:
365367
y = ncp.zeros(self.dims, dtype=self.dtype)
366368
for iwin0 in range(self.dims[0]):

pylops/signalprocessing/sliding3d.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ def _matvec_savetaper(self, x: NDArray) -> NDArray:
349349
self.taps = to_cupy_conditional(x, self.taps)
350350
y = ncp.zeros(self.dimsd, dtype=self.dtype)
351351
if self.simOp:
352-
x = self.Op @ x
352+
x = self.Op.matvec(x.ravel()).reshape(self.Op.dimsd)
353353
for iwin0 in range(self.dims[0]):
354354
for iwin1 in range(self.dims[1]):
355355
if self.simOp:
@@ -382,7 +382,7 @@ def _rmatvec_savetaper(self, x: NDArray) -> NDArray:
382382
if self.tapertype is not None:
383383
ywins = ywins * self.taps
384384
if self.simOp:
385-
y = self.Op.H @ ywins
385+
y = self.Op.rmatvec(ywins.ravel()).reshape(self.dims)
386386
else:
387387
y = ncp.zeros(self.dims, dtype=self.dtype)
388388
for iwin0 in range(self.dims[0]):
@@ -399,7 +399,7 @@ def _matvec_nosavetaper(self, x: NDArray) -> NDArray:
399399
self.taps = to_cupy_conditional(x, self.taps)
400400
y = ncp.zeros(self.dimsd, dtype=self.dtype)
401401
if self.simOp:
402-
x = self.Op @ x
402+
x = self.Op.matvec(x.ravel()).reshape(self.Op.dimsd)
403403
for iwin0 in range(self.dims[0]):
404404
for iwin1 in range(self.dims[1]):
405405
if self.simOp:
@@ -453,7 +453,7 @@ def _rmatvec_nosavetaper(self, x: NDArray) -> NDArray:
453453
for iwin0 in range(self.dims[0]):
454454
for iwin1 in range(self.dims[1]):
455455
ywins = self._apply_taper(ywins, iwin0, iwin1)
456-
y = self.Op.H @ ywins
456+
y = self.Op.rmatvec(ywins.ravel()).reshape(self.dims)
457457
else:
458458
y = ncp.zeros(self.dims, dtype=self.dtype)
459459
for iwin0 in range(self.dims[0]):

pytests/test_sliding.py

Lines changed: 103 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import pytest
1414

1515
from pylops.basicoperators import Identity, MatrixMult
16+
from pylops.optimization.basic import cgls
1617
from pylops.signalprocessing import Sliding1D, Sliding2D, Sliding3D
1718
from pylops.signalprocessing.sliding1d import sliding1d_design
1819
from pylops.signalprocessing.sliding2d import sliding2d_design
@@ -112,9 +113,10 @@
112113

113114

114115
@pytest.mark.parametrize("par", [(par1), (par2), (par3), (par4), (par5), (par6)])
115-
def test_Sliding1D(par):
116-
"""Dot-test and inverse for Sliding1D operator"""
117-
Op = MatrixMult(np.ones((par["nwiny"], par["ny"])))
116+
@pytest.mark.parametrize("dtype", [np.float32, np.float64])
117+
def test_Sliding1D(par, dtype):
118+
"""Dot-test and forward/adjoint/inverse for Sliding1D operator"""
119+
Op = MatrixMult(np.ones((par["nwiny"], par["ny"]), dtype=dtype), dtype=dtype)
118120

119121
nwins, dim = sliding1d_design(par["npy"], par["nwiny"], par["novery"], par["ny"])[
120122
:2
@@ -129,27 +131,38 @@ def test_Sliding1D(par):
129131
tapertype=par["tapertype"],
130132
savetaper=par["savetaper"],
131133
)
132-
assert dottest(Slid, par["npy"], par["ny"] * nwins, backend=backend)
133-
x = np.ones(par["ny"] * nwins)
134+
assert dottest(
135+
Slid,
136+
par["npy"],
137+
par["ny"] * nwins,
138+
rtol=1e-3 if dtype == np.float32 else 1e-6,
139+
backend=backend,
140+
)
141+
142+
x = np.ones((nwins, par["ny"]), dtype=dtype)
134143
y = Slid * x.ravel()
144+
xadj = Slid.H * y
145+
xinv = cgls(Slid, y, niter=50)[0]
135146

136-
xinv = Slid / y
137-
assert_array_almost_equal(x.ravel(), xinv)
147+
assert y.dtype == dtype
148+
assert xadj.dtype == dtype
149+
assert_array_almost_equal(x, xinv, decimal=3 if dtype == np.float32 else 8)
138150

139151

140152
@pytest.mark.skipif(
141153
int(os.environ.get("TEST_CUPY_PYLOPS", 0)) == 1, reason="Not CuPy enabled"
142154
)
143155
@pytest.mark.parametrize("par", [(par1), (par2), (par3), (par4)])
144-
def test_Sliding1D_simOp(par):
145-
"""Dot-test and inverse for Sliding1D operator with
156+
@pytest.mark.parametrize("dtype", [np.float32, np.float64])
157+
def test_Sliding1D_simOp(par, dtype):
158+
"""Dot-test and forward/adjoint/inverse for Sliding1D operator with
146159
Op applied to all windows simultaneously
147160
"""
148161
nwins, dim = sliding1d_design(
149162
par["npy"], par["nwiny"], par["novery"], par["nwiny"]
150163
)[:2]
151164

152-
Op = Identity((nwins, par["nwiny"]))
165+
Op = Identity((nwins, par["nwiny"]), dtype=dtype)
153166

154167
Slid = Sliding1D(
155168
Op,
@@ -160,18 +173,30 @@ def test_Sliding1D_simOp(par):
160173
tapertype=par["tapertype"],
161174
savetaper=par["savetaper"],
162175
)
163-
assert dottest(Slid, par["npy"], par["nwiny"] * nwins)
164-
x = np.ones(par["nwiny"] * nwins)
176+
assert dottest(
177+
Slid,
178+
par["npy"],
179+
par["nwiny"] * nwins,
180+
rtol=1e-3 if dtype == np.float32 else 1e-6,
181+
)
182+
x = np.ones((nwins, par["nwiny"]), dtype=dtype)
165183
y = Slid * x.ravel()
184+
xadj = Slid.H * y
185+
xinv = cgls(Slid, y, niter=50)[0]
166186

167-
xinv = Slid / y
168-
assert_array_almost_equal(x.ravel(), xinv)
187+
assert y.dtype == dtype
188+
assert xadj.dtype == dtype
189+
assert_array_almost_equal(x, xinv, decimal=3 if dtype == np.float32 else 8)
169190

170191

171192
@pytest.mark.parametrize("par", [(par1), (par2), (par3), (par4), (par5), (par6)])
172-
def test_Sliding2D(par):
173-
"""Dot-test and inverse for Sliding2D operator"""
174-
Op = MatrixMult(np.ones((par["nwiny"] * par["nt"], par["ny"] * par["nt"])))
193+
@pytest.mark.parametrize("dtype", [np.float32, np.float64])
194+
def test_Sliding2D(par, dtype):
195+
"""Dot-test and forward/adjoint/inverse for Sliding2D operator"""
196+
Op = MatrixMult(
197+
np.ones((par["nwiny"] * par["nt"], par["ny"] * par["nt"]), dtype=dtype),
198+
dtype=dtype,
199+
)
175200

176201
nwins, dims = sliding2d_design(
177202
(par["npy"], par["nt"]), par["nwiny"], par["novery"], (par["ny"], par["nt"])
@@ -186,28 +211,36 @@ def test_Sliding2D(par):
186211
savetaper=par["savetaper"],
187212
)
188213
assert dottest(
189-
Slid, par["npy"] * par["nt"], par["ny"] * par["nt"] * nwins, backend=backend
214+
Slid,
215+
par["npy"] * par["nt"],
216+
par["ny"] * par["nt"] * nwins,
217+
rtol=1e-3 if dtype == np.float32 else 1e-6,
218+
backend=backend,
190219
)
191-
x = np.ones((par["ny"] * nwins, par["nt"]))
220+
x = np.ones((nwins, par["ny"], par["nt"]), dtype=dtype)
192221
y = Slid * x.ravel()
222+
xadj = Slid.H * y
223+
xinv = cgls(Slid, y, niter=50)[0]
193224

194-
xinv = Slid / y
195-
assert_array_almost_equal(x.ravel(), xinv)
225+
assert y.dtype == dtype
226+
assert xadj.dtype == dtype
227+
assert_array_almost_equal(x, xinv, decimal=3 if dtype == np.float32 else 8)
196228

197229

198230
@pytest.mark.skipif(
199231
int(os.environ.get("TEST_CUPY_PYLOPS", 0)) == 1, reason="Not CuPy enabled"
200232
)
201233
@pytest.mark.parametrize("par", [(par1), (par2), (par3), (par4)])
202-
def test_Sliding2D_simOp(par):
203-
"""Dot-test and inverse for Sliding2D operator with
234+
@pytest.mark.parametrize("dtype", [np.float32, np.float64])
235+
def test_Sliding2D_simOp(par, dtype):
236+
"""Dot-test and forward/adjoint/inverse for Sliding2D operator with
204237
Op applied to all windows simultaneously
205238
"""
206239
nwins, dims = sliding2d_design(
207240
(par["npy"], par["nt"]), par["nwiny"], par["novery"], (par["nwiny"], par["nt"])
208241
)[:2]
209242

210-
Op = Identity((nwins, par["nwiny"], par["nt"]))
243+
Op = Identity((nwins, par["nwiny"], par["nt"]), dtype=dtype)
211244

212245
Slid = Sliding2D(
213246
Op,
@@ -218,20 +251,37 @@ def test_Sliding2D_simOp(par):
218251
tapertype=par["tapertype"],
219252
savetaper=par["savetaper"],
220253
)
221-
x = np.ones((nwins, par["nwiny"], par["nt"]))
254+
assert dottest(
255+
Slid,
256+
par["npy"] * par["nt"],
257+
par["nwiny"] * par["nt"] * nwins,
258+
rtol=1e-3 if dtype == np.float32 else 1e-6,
259+
backend=backend,
260+
)
261+
262+
x = np.ones((nwins, par["nwiny"], par["nt"]), dtype=dtype)
222263
y = Slid * x.ravel()
264+
xadj = Slid.H * y
265+
xinv = cgls(Slid, y, niter=50)[0]
223266

224-
xinv = Slid / y
225-
assert_array_almost_equal(x.ravel(), xinv)
267+
assert y.dtype == dtype
268+
assert xadj.dtype == dtype
269+
assert_array_almost_equal(x, xinv, decimal=3 if dtype == np.float32 else 8)
226270

227271

228272
@pytest.mark.parametrize("par", [(par1), (par2), (par3), (par4), (par5), (par6)])
229-
def test_Sliding3D(par):
230-
"""Dot-test and inverse for Sliding3D operator"""
273+
@pytest.mark.parametrize("dtype", [np.float32, np.float64])
274+
def test_Sliding3D(par, dtype):
275+
"""Dot-test and forward/adjoint/inverse for Sliding3D operator"""
231276
Op = MatrixMult(
232277
np.ones(
233-
(par["nwiny"] * par["nwinx"] * par["nt"], par["ny"] * par["nx"] * par["nt"])
234-
)
278+
(
279+
par["nwiny"] * par["nwinx"] * par["nt"],
280+
par["ny"] * par["nx"] * par["nt"],
281+
),
282+
dtype=dtype,
283+
),
284+
dtype=dtype,
235285
)
236286

237287
nwins, dims = sliding3d_design(
@@ -255,21 +305,27 @@ def test_Sliding3D(par):
255305
Slid,
256306
par["npy"] * par["npx"] * par["nt"],
257307
par["ny"] * par["nx"] * par["nt"] * nwins[0] * nwins[1],
308+
rtol=1e-3 if dtype == np.float32 else 1e-6,
258309
backend=backend,
259310
)
260-
x = np.ones((par["ny"] * par["nx"] * nwins[0] * nwins[1], par["nt"]))
311+
312+
x = np.ones((nwins[0], nwins[1], par["ny"], par["nx"], par["nt"]), dtype=dtype)
261313
y = Slid * x.ravel()
314+
xadj = Slid.H * y
315+
xinv = cgls(Slid, y, niter=50)[0]
262316

263-
xinv = Slid / y
264-
assert_array_almost_equal(x.ravel(), xinv)
317+
assert y.dtype == dtype
318+
assert xadj.dtype == dtype
319+
assert_array_almost_equal(x, xinv, decimal=3 if dtype == np.float32 else 8)
265320

266321

267322
@pytest.mark.skipif(
268323
int(os.environ.get("TEST_CUPY_PYLOPS", 0)) == 1, reason="Not CuPy enabled"
269324
)
270325
@pytest.mark.parametrize("par", [(par1), (par2), (par3), (par4)])
271-
def test_Sliding3D_simOp(par):
272-
"""Dot-test and inverse for Sliding3D operator with
326+
@pytest.mark.parametrize("dtype", [np.float32, np.float64])
327+
def test_Sliding3D_simOp(par, dtype):
328+
"""Dot-test and forward/adjoint/inverse for Sliding3D operator with
273329
Op applied to all windows simultaneously
274330
"""
275331
nwins, dims = sliding3d_design(
@@ -279,7 +335,7 @@ def test_Sliding3D_simOp(par):
279335
(par["nwiny"], par["nwinx"], par["nt"]),
280336
)[:2]
281337

282-
Op = Identity((*nwins, par["nwiny"], par["nwinx"], par["nt"]))
338+
Op = Identity((*nwins, par["nwiny"], par["nwinx"], par["nt"]), dtype=dtype)
283339

284340
Slid = Sliding3D(
285341
Op,
@@ -295,9 +351,16 @@ def test_Sliding3D_simOp(par):
295351
Slid,
296352
par["npy"] * par["npx"] * par["nt"],
297353
par["nwiny"] * par["nwinx"] * par["nt"] * nwins[0] * nwins[1],
354+
rtol=1e-3 if dtype == np.float32 else 1e-6,
355+
)
356+
357+
x = np.ones(
358+
(nwins[0], nwins[1], par["nwiny"], par["nwinx"], par["nt"]), dtype=dtype
298359
)
299-
x = np.ones((par["nwiny"] * par["nwinx"] * nwins[0] * nwins[1], par["nt"]))
300360
y = Slid * x.ravel()
361+
xadj = Slid.H * y
362+
xinv = cgls(Slid, y, niter=50)[0]
301363

302-
xinv = Slid / y
303-
assert_array_almost_equal(x.ravel(), xinv)
364+
assert y.dtype == dtype
365+
assert xadj.dtype == dtype
366+
assert_array_almost_equal(x, xinv, decimal=3 if dtype == np.float32 else 8)

0 commit comments

Comments
 (0)