Skip to content

Support complex filters in Convolve1D adjoints - #817

Merged
mrava87 merged 4 commits into
PyLops:devfrom
antonsoo:fix/complex-convolution-adjoint
Oct 17, 2026
Merged

mrava87 merged 4 commits into
PyLops:devfrom
antonsoo:fix/complex-convolution-adjoint

Conversation

@antonsoo

@antonsoo antonsoo commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Convolve1D reverses the filter for its adjoint but does not conjugate it. This extends the operator to complex filters: the forward result is already correct, and the added conjugation supplies the corresponding Hermitian adjoint for short and long filters. Complex-filter use was previously unsupported.

Conjugate the reversed filter before the existing contiguous copy, preserving the CuPy stride handling from #797. Extend the existing dot-test, dtype and inversion cases to complex64/complex128 with h + 1j*h, add the conjugation to the adjoint equations, and repeat the plotted example with a complex filter.

For example, this adjoint error is about 42.85 on dev and near machine precision with the fix:

import numpy as np
from scipy.linalg import convolution_matrix
from pylops.signalprocessing import Convolve1D

h = np.array([1 + .5j, -.2 + .3j, .1 - .1j])
y = np.arange(12) + 1j * np.arange(12)[::-1]
op = Convolve1D(12, h=h, offset=1, dtype="complex128")
matrix = convolution_matrix(h, 12, "same")
print(np.linalg.norm(op.H @ y - matrix.conj().T @ y))

Validation:

  • All 24 added complex cases in the existing one-dimensional test fail before and pass after, covering both precisions, compact/extended filters, offsets and direct/FFT methods. Independent matrix checks also cover overlap-add, multidimensional filters and broadcasting. The complete convolution suite passes on CPU and CuPy: 382 cases each.
  • Recorded speech and guitar deconvolution/calibration agree with independent dense damped least squares in all 48 complex-filter cases per backend. Maximum relative inverse error drops from 6.62 to 9.60e-7 on CPU and 1.80e-6 on an RTX 5070. All forward outputs and 48 real-filter controls per backend remain byte-identical.
  • Project lint/hooks, wheel build, documentation build and the convolution example pass. Mypy diagnostics are unchanged from dev. A broader integration run encountered a randomized float32 ChirpRadon dot-test tolerance failure; a 500-seed comparison gives identical results on unmodified dev and the patched tree, including two failing seeds.

The recorded-audio workload is a constructed numerical validation. It does not establish an existing production PyLops use case or demand for complex filters.

AI disclosure: Codex was used to investigate the failure, implement the change, write and run the independent checks, and prepare the documentation and PR text.

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 0 complexity · 0 duplication

Metric Results
Complexity 0
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@mrava87

mrava87 commented Oct 14, 2026

Copy link
Copy Markdown
Collaborator

Thanks @antonsoo for this. I would say this is more of an enhancement than a bug per se, as we never really support complex valued filters (no tests or examples with it) mostly because I am not aware of any real application that would benefit from it - although, of course we also don't have any guardrail in place to check for the dtype and raise an error otherwise.

Looks like the fix is very minor though, so I am going to have a closer look soon and let you know if I have any comment before merging 😄

@mrava87
mrava87 self-requested a review October 14, 2026 19:22
@mrava87 mrava87 added the enhancement New feature or request label Oct 14, 2026
@antonsoo antonsoo changed the title Conjugate complex filters in Convolve1D adjoints Support complex filters in Convolve1D adjoints Oct 14, 2026
@antonsoo

Copy link
Copy Markdown
Contributor Author

Classifying this as a small support enhancement makes sense. The speech/guitar inverse was a constructed numerical validation; I don't have an existing production PyLops use case for complex filters to point to. I've updated the title and description to make that scope clear. The implementation and real-filter controls are unchanged.

@mrava87 mrava87 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@antonsoo thanks for the contribution. I think adding support for complex-valued filters in Convolved1D is a good enhancement, however quite a few things don't follow the standards in the rest of the library... left comments for you to adjust before I can merge 😄

Comment thread examples/plot_convolve.py
Comment thread pylops/signalprocessing/convolve1d.py Outdated
Comment thread pylops/signalprocessing/convolve1d.py
Comment thread pytests/test_convolve.py Outdated
Comment thread CHANGELOG.md Outdated
@antonsoo
antonsoo force-pushed the fix/complex-convolution-adjoint branch from 1c5c666 to cbd256d Compare October 17, 2026 17:51
@antonsoo

Copy link
Copy Markdown
Contributor Author

Updated the tests to extend test_Convolve1D_1d with h + 1j*h, both complex precisions, and the existing dot/dtype/inversion checks. The example now repeats the plotted inverse with / and real/imaginary panels; it contains no assertions. I also removed the changelog entry.

For the time-domain equation I kept t+tau using the equivalent correlation form h(tau)^* y(t+tau); this preserves the conjugate adjoint of the forward convolution.

Rebased on current dev. CPU checks, lint, the example and documentation build pass. The recorded CPU/GPU inverses still agree with independent dense references, with all real-filter controls unchanged.

@mrava87
mrava87 merged commit 0fed249 into PyLops:dev Oct 17, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants