Repository navigation
Subspace: project with conj(basis), expand with basis.T, so complex signals round-trip - #51
Merged
Merged
Conversation
project is signals @ basis.conj() and expand is coefficients @ basis.mT, so a complex signal of the span comes back unchanged; modes is basis.mH, the layout mri-nufft's MRISubspace expands with its conjugate. A complex dictionary whose atoms do not share one phase was projected onto the conjugate of its span. Real dictionaries are unaffected. The subspace-route tests now also run an off-resonant, complex basis. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MFB6QM5LeyLiZBruB754ux
…-dvys3p-subspace # Conflicts: # CHANGELOG.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Matteo · project thread
What changed
Subspace.fitkeeps the left singular vectorsBof the signals laid out as columns. The two maps now match that:project(s)=s @ B.conj(), the inner products ⟨b_k, s⟩expand(c)=c @ B.mT, soexpand(project(s)) == sfor any signal in the span, complex includedmodes=B.mH(resolve_conj'd), which is mri-nufft'sMRISubspacelayout.MRISubspaceexpands withconj(modes)and projects withmodes, which are exactlyexpandandproject.pics -Band bartorch'sbasis=contract without the conjugate, so they takebasis.mT. The docstring anddocs/explanations/model-based-reconstruction.mdsay so.Why
Before this change,
projectwass @ Bandexpandwasc @ B.mH. Those two are adjoints of each other, so they agreed with mri-nufft. But they project onto the conjugate of the signals' span. On random complex signals that lie in a rank-3 span, the round trip had 96 % error. Real dictionaries, and dictionaries whose atoms share one global phase, hid this. A dictionary whose phase changes along the train does not, for example one with off-resonance or RF phase cycling. Found while moving mri2qmap's real-coefficient basis rotation upstream (mri2qmap-bartorch).Validation
tests/estimators/test_subspace.py::test_complex_signals_of_the_span_round_tripfails before the change and passes after it. It also checks themodes/ mri-nufft relations.tests/operator/test_subspace_route.pynow runs both a real basis and an off-resonant complex one against mri-nufft'sMRISubspace(op and adj_op). All 5+2 pass. Locally I had to stubmrinufft.check_backend, because the installed mri-nufft lacks it, and install finufft.pytest tests/estimators tests/operator tests/test_docstring_defaults.py: 285 passed, 32 skipped (CUDA).ruff format/ruff check: clean.Documentation impact
Subspace.project,expandandmodesdocstrings, the model-based reconstruction explanation, and a CHANGELOG Unreleased/Fixed entry. For callers with complex, phase-varying dictionaries, coefficients change by a conjugation of the basis. That is the fix.Checklist
Generated by Claude Code