Skip to content

XFit-style dipole fitting GUI#13074

Draft
wmvanvliet wants to merge 194 commits intomne-tools:mainfrom
wmvanvliet:xfit
Draft

XFit-style dipole fitting GUI#13074
wmvanvliet wants to merge 194 commits intomne-tools:mainfrom
wmvanvliet:xfit

Conversation

@wmvanvliet
Copy link
Copy Markdown
Contributor

@wmvanvliet wmvanvliet commented Jan 21, 2025

This adds a GUI to perform guided dipole modeling in the spirit of MEGIN's XFit program. This PR contains the base functionality needed to make the GUI useful. Useful enough to include in the next release of MNE-Python. The plan is to keep adding features in future PRs as well as some sorely needed speed improvements.

See here for a list of currently supported features: #11977
This PR depends on: #12071

Screenshot 2025-01-21 183100

Minimal example:

import mne

data_path = mne.datasets.sample.data_path()
evoked = mne.read_evokeds(
    f"{data_path}/MEG/sample/sample_audvis-ave.fif", condition="Left Auditory"
)
evoked.apply_baseline((-0.2, 0))
trans = mne.read_trans(f"{data_path}/MEG/sample/sample_audvis_raw-trans.fif")
cov = mne.read_cov(f"{data_path}/MEG/sample/sample_audvis-cov.fif")
bem = mne.read_bem_solution(f"{data_path}/subjects/sample/bem/sample-5120-5120-5120-bem-sol.fif")
subject = "sample"
subjects_dir = data_path / "subjects"

evoked.pick("grad")

# Quick and dirty. No MRI whatsoever.
g = mne.gui.DipoleFitUI(evoked)

# Slow and proper. With proper BEM model.
# g = mne.gui.DipoleFitUI(evoked, trans=trans, cov=cov, bem=bem, subject=subject, subjects_dir=subjects_dir)

Todo:

  • Basic unit tests
  • In-depth unit tests
  • Proper documentation page
  • Towncrier

@larsoner
Copy link
Copy Markdown
Member

Didn't get to it this week, might have time Monday. If not, then it'll probably be another week because next week is full of meetings for me!

@wmvanvliet
Copy link
Copy Markdown
Contributor Author

There's no hurry :)

Copy link
Copy Markdown
Member

@larsoner larsoner left a comment

Choose a reason for hiding this comment

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

Looks pretty reasonable so far. Can you update + flesh out the top comment? For example I think towncrier is done and you have some unit tests, so not clear to me what is still missing.

I still need to actually do some manual testing to see how it works as well, which could be a next step (you can put it as a TODO in the top comment if you want 😄 )

)
parser.add_option(
"-b",
"--bem",
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.

Someday we should maybe allow --sphere... I think MNE-C had some way to do this. Can you add a TODO comment in case someone wants to try?

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.

If --bem is not speficied, a default auto-fitted sphere will be used. If the user wants to have control of the sphere, wouldn't it be easier if they just do this through mne.make_sphere_model than expose all the sphere parameters on the command line?

@larsoner
Copy link
Copy Markdown
Member

@wmvanvliet this is in draft mode, is this good to go from your end? If so feel free to mark as ready, ping me, and I'll try actually using it and see if there are any show-stopping issues.

CircleCI failure is real:

        ../tutorials/inverse/21_interactive_dipole_fit.py failed leaving traceback:
    
        Traceback (most recent call last):
          File "/home/circleci/project/tutorials/inverse/21_interactive_dipole_fit.py", line 41, in <module>
            mne.gui.dipolefit()
        TypeError: dipolefit() missing 1 required positional argument: 'evoked'

so is its style complaint

/home/circleci/project/doc/generated/commands.rst:457: WARNING: Option list ends without a blank line; unexpected unindent. [docutils]
/home/circleci/project/doc/generated/commands.rst:461: WARNING: Definition list ends without a blank line; unexpected unindent. [docutils]

in case you want to test locally, I can replicate the example error with

larsoner:~/python/mne-python/doc$ PATTERN=interactive_dipole make html-pattern

I'll look to see if I can see what docutils is angry about

Copy link
Copy Markdown
Member

@larsoner larsoner left a comment

Choose a reason for hiding this comment

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

Uggghh when I run locally I get a reference cycle. Working on fixing it and will push if I figure it out

@larsoner
Copy link
Copy Markdown
Member

Fixed ref cycle (need weakrefs to all callbacks) and improved scraping to use GUI-style scraping

@wmvanvliet
Copy link
Copy Markdown
Contributor Author

Only thing blocking this IMO is faster unit tests with better coverage.

@larsoner
Copy link
Copy Markdown
Member

@wmvanvliet looks like still draft mode, let me know when I should look and test it out (and hopefully merge!)

@wmvanvliet
Copy link
Copy Markdown
Contributor Author

You already helped a lot figuring out the ref cycles. We still need better test coverage before thinking about merging this.

@larsoner
Copy link
Copy Markdown
Member

Do you need help with tests? I might have time next week to get some in

@wmvanvliet
Copy link
Copy Markdown
Contributor Author

wmvanvliet commented Mar 20, 2026

Of course any help is appreciated and motivating! My main issue with writing these tests is speed. How can we test this GUI at any type of reasonable speed?

@larsoner
Copy link
Copy Markdown
Member

How can we test this GUI at any type of reasonable speed?

A couple ideas to get the ball rolling:

  1. Use as few GUI instances as possible: test as many things as feasible with each spun-up GUI.
  2. Monkey-patch slow functions that are tested properly elsewhere to do a really bad job really quickly instead of a correct job slowly: For one example, the field line mapping code that returns an ndarray of shape (n_sensors, n_head_vertices) can just return a rng.normal(...) instead of doing a meaninful computation (we check that correctness elsewhere!).

With these in place maybe it's already doable, but if not we should look to see what takes a lot of time and figure out how to make it faster (e.g., via caching, more monkey patching, etc.)

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants