Skip to content

DictionaryMatcher: coarse-to-fine lattice search (coarse=, refine=) - #50

Merged
mcencini merged 1 commit into
mainfrom
claude/project-thread-dvys3p
Nov 1, 2026
Merged

mcencini merged 1 commit into
mainfrom
claude/project-thread-dvys3p

Conversation

@mcencini

@mcencini mcencini commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

Requested by Matteo · project thread

What changed

DictionaryMatcher(coarse=k) places the atoms on the lattice their parameters were simulated on. That is a product of one value list per parameter, and some combinations may be missing, such as T2 > T1. The search runs in two passes. First it scores every k-th value along each axis. Then it scores the 2k+1 values around the coarse winner along each axis. refine=False returns the coarse pass alone, and refine can be set between calls. The new matcher.lattice exposes the placement. coarse needs parameters and does not combine with groups.

Why

mri2qmap-bartorch carries this search as a private _Grid beside DictionaryMatcher. Inside the ADMM iterations it matches on the coarse lattice, and at the last iteration it does the full refine. Moving it into the matcher lets mri2qmap use the matcher's chunking, device replicas and least-squares scales instead of its own. On a 3 % log (T1, T2) grid of about 37 000 atoms, coarse=3 scores about 4 200 + 49 atoms per voxel.

Validation

  • New tests in tests/estimators/test_dictionary.py:
    • On a 2-D triangular lattice, coarse-to-fine finds the same indices, scales, scores and parameters as the exhaustive search, for 200 noisy complex-scaled signals with top_k 1 and 3.
    • refine=False returns coarse-lattice atoms only.
    • Setting refine=True afterwards restores exact self-matches.
    • Invalid combinations are refused.
    • The lattice follows .to().
  • I first tried an exponential-recovery test dictionary. Its neighbouring atoms correlate at 0.9998, so a coarse winner can sit far along a flat ridge. That's a property of the method, not a bug: the search assumes the likeness falls off with lattice distance. The test now uses a dictionary with that property, and the docstring states the assumption.
  • pytest tests/estimators tests/test_docstring_defaults.py: 263 passed, 28 skipped (CUDA). This ran against src/ with the 0.0.14 wheel's compiled kernels; the kernels are untouched.
  • ruff format / ruff check: clean.
  • Not run: the full suite, the docs build, and a GPU.

Documentation impact

The DictionaryMatcher docstring documents coarse, refine, lattice and the smoothness assumption. The CHANGELOG has an Unreleased/Added entry.

Checklist

  • The new tests cover the change. The estimator tests pass; the full suite was not run.
  • ruff format and check are clean.
  • numpydoc docstrings.
  • Comments describe the current code.
  • Kernels are not touched.
  • Docs build not run.

Generated by Claude Code

DictionaryMatcher(coarse=k) places the atoms on the lattice of their
parameter values (a product of one list per parameter, combinations possibly
left out), scores every k-th value along each axis, then the 2k + 1 values
around the winner along each. refine=False stops after the coarse pass, which
an iterative reconstruction can use until its last iteration.

From mri2qmap-bartorch, which carries the same search as a private _Grid.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MFB6QM5LeyLiZBruB754ux
@mcencini mcencini self-assigned this Nov 1, 2026
@mcencini
mcencini merged commit ef30833 into main Nov 1, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants