Skip to content

Use MEDiCINe's own recommended default for num_depth_bins#4686

Open
nwatters01 wants to merge 4 commits into
SpikeInterface:mainfrom
nwatters01:fix-medicine-default-num-depth-bins
Open

Use MEDiCINe's own recommended default for num_depth_bins#4686
nwatters01 wants to merge 4 commits into
SpikeInterface:mainfrom
nwatters01:fix-medicine-default-num-depth-bins

Conversation

@nwatters01

@nwatters01 nwatters01 commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Summary

  • The medicine motion estimation preset (MedicineRegistration.run in src/spikeinterface/sortingcomponents/motion/medicine.py) computed num_depth_bins by dividing the probe's depth span by win_scale_um, a generic windowing parameter tuned for other methods (dredge, decentralized, etc.), defaulting to 300 µm. For a typical probe this yields far more depth bins than MEDiCINe is designed for.
  • MEDiCINe's own package (medicine.run.run_medicine) defaults and documents num_depth_bins=2 as sufficient for all of its authors' recording sessions, independent of any window-scale concept.
  • All other MEDiCINe hyperparameter defaults in MedicineRegistration.run (motion_bound, time_kernel_width, activity_network_hidden_features, amplitude_threshold_quantile, batch_size, training_steps, initial_motion_noise, motion_noise_steps, learning_rate, epsilon) already match medicine's own defaults exactly — num_depth_bins was the one outlier.
  • This PR adds an explicit num_depth_bins=None parameter to MedicineRegistration.run. When unset, it now defaults to 1 if rigid else 2 (MEDiCINe's own recommendation) instead of being derived from win_scale_um/win_margin_um. Users who want a different value can still pass num_depth_bins explicitly through estimate_motion_kwargs.
  • Also filled in the previously empty params_doc docstring for this method, and removed a leftover debug print().
  • No other preset or the shared estimate_motion() signature/defaults were touched, so this is backwards compatible for all other motion estimation methods.

Dependencies

  • medicine-neuro was not previously referenced anywhere in pyproject.toml. Added it to the test-sortingcomponents dependency group (alongside torch, following the same pattern) so the new test below actually runs in CI rather than being skipped, and added an explanatory comment next to the existing torch comment in [project.optional-dependencies].sortingcomponents noting it's an optional heavy dep (itself pulling in torch) needed only for the medicine method — not bundled into that extra by default, same treatment as torch.

Test plan

  • Added src/spikeinterface/sortingcomponents/motion/tests/test_medicine.py (skipped if the optional medicine/torch packages aren't installed):
    • Parametrized check that num_depth_bins resolves to MEDiCINe's own default (2 non-rigid / 1 rigid), independent of win_scale_um.
    • Direct equivalence check: given identical peaks and RNG state (torch.manual_seed / np.random.seed), the spikeinterface medicine estimate_motion wrapper produces output numerically identical to calling medicine.run_medicine() directly, confirming the wrapper's resolved settings and outputs match the original package.
  • python -m pytest src/spikeinterface/sortingcomponents/motion/tests/ (full directory, 12 passed, no regressions)
  • python -m py_compile src/spikeinterface/sortingcomponents/motion/medicine.py

The medicine preset derived num_depth_bins from the generic win_scale_um
windowing parameter (tuned for other methods like dredge/decentralized),
which for a typical probe produces far more depth bins than MEDiCINe is
designed for. MEDiCINe's own default and documented recommendation is 2
non-rigid depth bins, so use that directly (1 when rigid) unless the user
explicitly passes num_depth_bins. All other MedicineRegistration defaults
already matched medicine.run_medicine()'s defaults exactly.
@nwatters01

Copy link
Copy Markdown
Contributor Author

Some context: I have received emails from users complaining about the fact that spikeinterface's default parameters for Medicine are not appropriate. This PR changes this to make the default parameters ones that Medicine works well for.

This change is completely backwards compatible, and no other motion estimation methods are affected.

@JoeZiminski

Copy link
Copy Markdown
Contributor

This makes sense to me thanks for this. Would it be possible to add a test which runs the SI wrapper and the original MEDiCINe package to ensure the outputs / settings match?

@zm711 zm711 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This makes sense to me. Just one question about positioning of the args.

## medicine specific kwargs propagated to the lib
output_dir=None,
plot_figures=False,
num_depth_bins=None,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

curious about the positioning of this arg? I'm just thinking for backwards compatibility. If we put this at the bottom it won't break positional arguments for people but has the same effect.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks, I've now moved it to the bottom!

Nicholas Watters added 2 commits July 13, 2026 22:47
…nal package

Verifies that:
- num_depth_bins resolves to MEDiCINe's own default (2 non-rigid / 1 rigid),
  independent of the generic win_scale_um window parameter used by other
  motion estimation methods.
- Given the same peaks and RNG state, spikeinterface's `medicine`
  estimate_motion method produces output identical to calling
  medicine.run_medicine() directly.
@nwatters01

Copy link
Copy Markdown
Contributor Author

Thank you for your suggestions.

I've moved the num_depth_bins argument to the bottom to ensure backwards compatibility, and added a test file to test that this wrapper gives the results as the medicine package with default parameters. I ran the test locally to make sure it passes.

@chrishalcrow

Copy link
Copy Markdown
Member

Thanks for this! The new tests aren't currently running on the ci: if you look at https://github.com/SpikeInterface/spikeinterface/actions/runs/29302001612/job/86987545183?pr=4686#step:30:378 and search "medicine" you'll see

SKIPPED [1] src\spikeinterface\sortingcomponents\motion\tests\test_medicine.py:5: could not import 'medicine': No module named 'medicine'

You should be able to add it to the sorting-components test suite by adding medicine to the pyproject.toml here:

test-sortingcomponents = [

@alejoe91 alejoe91 added the motion correction Questions related to motion correction label Jul 14, 2026
Needed so the new test_medicine.py test actually runs in CI instead of
being skipped, and documents medicine-neuro as an optional heavy dep
(like torch) for the "medicine" motion estimation method.
@nwatters01

Copy link
Copy Markdown
Contributor Author

Thanks for the comments, and Alessio for approval!

I've now fixed the test dependencies, so the tests run. I'll wait for the rest of the day to hear if there's anything else, and otherwise will merge first thing tomorrow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

motion correction Questions related to motion correction

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants