Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: new coreg gui features #10015

Merged
merged 38 commits into from
Dec 6, 2021
Merged

Conversation

GuillaumeFavelier
Copy link
Contributor

@GuillaumeFavelier GuillaumeFavelier commented Nov 17, 2021

This PR adds support for the parameters scale_by_distance, project_eeg, mark_inside of CoregistrationUI.

It's part of #8833

ToDo

  • integrate head_transparency, scale_by_distance, mark_inside and orient_to_surface within the UX
  • show/hide HPI/HSP/EEG based on the weight they are assigned for ICP
  • fix bug with head_resolution widget not being sync'ed with fid_accurate
  • add a status bar to display infos about fitting operations
  • improve 3d labels content
  • fix bug with mark_inside on maOS pyvista<0.32

@GuillaumeFavelier GuillaumeFavelier self-assigned this Nov 17, 2021
@GuillaumeFavelier GuillaumeFavelier changed the title WIP,ENH: new coreg features WIP,ENH: new coreg gui features Nov 17, 2021
@agramfort
Copy link
Member

tell us when it's ready for review @GuillaumeFavelier

@GuillaumeFavelier GuillaumeFavelier changed the title WIP,ENH: new coreg gui features ENH: new coreg gui features Nov 18, 2021
@GuillaumeFavelier
Copy link
Contributor Author

I double-checked some examples and fixed a visual bug introduced in here. This PR is now ready for reviews @agramfort, @larsoner

@larsoner
Copy link
Member

I ran:

mne coreg -s sample -d subjects --fif MEG/sample/sample_audvis_raw.fif

clicked "lock" (to get out of fiducials mode), then hit "fit fiducials", then turned on transparent mode, then recorded this, which is just a few clusters of rapid Z translation clicks:

Peek.2021-11-18.11-02.mp4
  1. After I stop clicking the Z-translate button, the points jump downward (probably correct?) but then "slide upward" incrementally (probably incorrect?). Note that this does not happen to HPI coils but it does to EEG and dig points, if that helps track down the bug.
  2. The HPI-coil-size is seems wrong for the coil on the far side of the head. By the end of the video, it's basically on the head surface, but it has a huge radius

mne/gui/_coreg.py Outdated Show resolved Hide resolved
@GuillaumeFavelier GuillaumeFavelier changed the title ENH: new coreg gui features WIP,ENH: new coreg gui features Nov 22, 2021
@GuillaumeFavelier
Copy link
Contributor Author

just a few clusters of rapid Z translation clicks

I added a lock on _set_parameter() which should prevent those "out-of-sync" scenarii caused by spamming.

Copy link
Contributor Author

@GuillaumeFavelier GuillaumeFavelier left a comment

Choose a reason for hiding this comment

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

https://github.com/GuillaumeFavelier/mne-python/blob/cc281f88fff60bc7bdd522e9c369421a413fc81c/mne/gui/_coreg.py#L221

Is this really necessary? Because it is not compatible with the parameter head_resolution (for example when the user sets --low-res-head).

@GuillaumeFavelier
Copy link
Contributor Author

In an attempt to simplify interface and user interactions, what do you think of:

  • merging orient_glyphs and scale_by_distance into one checkbox
  • keeping mark_inside=True and removing its checkbox
  • setting head_transparency depending on "lock fiducials" and removing its checkbox

Also is it necessary to have all "Show HPI", "Show EEG" and "Show HSP", maybe only one "Show sensors" could work?
If those widgets are not really needed, we can remove them all too.

@larsoner
Copy link
Member

merging orient_glyphs and scale_by_distance into one checkbox

From talking to @agramfort a bit, I'm tempted to just always scale by distance and orient the glyphs, and not make these optional.

keeping mark_inside=True and removing its checkbox

Agreed

setting head_transparency depending on "lock fiducials" and removing its checkbox

Sometimes it's nice to be able to make it transparent, and even to varying degrees. But I guess we could add support for this later, and stick with what you propose for now

Also is it necessary to have all "Show HPI", "Show EEG" and "Show HSP", maybe only one "Show sensors" could work?

Being able to toggle these separately can be nice. What if we show/hide based on the weight they are assigned for ICP? Zero weight = hide, non-zero weight = show?

@larsoner
Copy link
Member

larsoner commented Nov 22, 2021

Is this really necessary? Because it is not compatible with the parameter head_resolution (for example when the user sets --low-res-head).

You need to use the high resolution head when picking fiducials, otherwise your clicks get locked to vertex locations that are some mm away from where you actually clicked. Also it's much harder to make out the correct fid locations when using the low resolution head.

In other words, I think if you are in "set fiducials" mode, you should always be shown an opaque, high-res head with no sensors. Once you leave that mode, you should switch to a semi-transparent, high- or low- (depending on the option / config value they have set) res head with whatever sensors they've chosen to show

@larsoner
Copy link
Member

larsoner commented Dec 3, 2021

Sure, I can look today or early next week

@larsoner
Copy link
Member

larsoner commented Dec 3, 2021

  1. Fixed the drawing (I think)
  2. Last update always gets drawn by the timer. You can verify interactively, but also by watching e.g.:
    MNE_LOGGING_LEVEL=debug mne coreg -s sample -d subjects/ --fif MEG/sample/sample_audvis_raw.fif
    
  3. Fixed "jerkiness" by removing a _process_events call in _add_mesh. We really shouldn't need it there. If we do, we should fix it elsewhere. I think this should speed things up globally, because now we can truly manually control when updates are made. @GuillaumeFavelier if you remember where this came from, we should double check that removing it doesn't break anything!
  4. Fixed CTRL-C behavior (now properly closes rather than aborting) both for mne coreg and for PyQtGraph-based browsing
  5. Fixed iterative ICP updates so they show up on the fly now. I can't upload a video at the moment, but feel free to try locally!

Comment on lines +155 to +167
# https://stackoverflow.com/questions/5160577/ctrl-c-doesnt-work-with-pyqt
def _qt_app_exec(app):
# adapted from matplotlib
old_signal = signal.getsignal(signal.SIGINT)
is_python_signal_handler = old_signal is not None
if is_python_signal_handler:
signal.signal(signal.SIGINT, signal.SIG_DFL)
try:
app.exec_()
finally:
# reset the SIGINT exception handler
if is_python_signal_handler:
signal.signal(signal.SIGINT, old_signal)
Copy link
Member

Choose a reason for hiding this comment

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

cc @marsipu you'll probably be interested in this -- it makes ctrl-C actually interrupt blocking mode. For me it actually kills the Python session, but matplotlib does the same. So I think it's okay (?)

if show:
fig.show()
# If block=False, a Qt-Event-Loop has to be started
# somewhere else in the calling code.
if block:
QApplication.instance().exec()
_qt_app_exec(QApplication.instance())
Copy link
Member

Choose a reason for hiding this comment

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

... and here is where I used that private function it so that it would affect pyqtgraph-based browsing

@larsoner
Copy link
Member

larsoner commented Dec 3, 2021

Pushed another couple of commits to:

  1. Temporarily use my PyVista version branch until they change their policy (FIX: Bump version pyvista/pyvista#1911)
  2. Make hpi the same size as dig and EEG
  3. Default to "matched" fid mode

@GuillaumeFavelier can you look and see if my changes and the code behavior make sense? Basically every _update_plots call just updates the set of things to draw, and every tick of the time (1/60th of a sec max) _redraw is called, which pops things from the list of things to draw. This ensures that whatever our last state is, eventually all items from it get drawn. In practice it seems that they're always drawn at once, which is nice. (Before they were drawn at the same time, but the _process_events in _add_mesh caused the draw to update, so if you updated say 5 items it would evoke 5 redraws rather than a single one at the end.)

@GuillaumeFavelier
Copy link
Contributor Author

Thank you for the great help @larsoner!

can you look and see if my changes and the code behavior make sense?

I took the time to review your commits carefully and I tested locally with _qt and _notebook. I'm glad that 2 mutexes and a set did the trick 👌

Fixed CTRL-C behavior

This is awesome!

Fixed iterative ICP updates so they show up on the fly now

I was not aware of this issue, for me, the plot was updated after each iteration 😮

Fixed "jerkiness" by removing a _process_events call in _add_mesh.

Same for the jerkiness but it was maybe more difficult for me to notice.

Before they were drawn at the same time, but the _process_events in _add_mesh caused the draw to update, so if you updated say 5 items it would evoke 5 redraws rather than a single one at the end.

Anyway, thank you for the explanation, I'll keep this in mind.

We really shouldn't need it there.

I have been digging to find where the call comes from and I tracked it down to #7791 (comment). Apparently, it was necessary during the migration to pyvistaqt on MacOS with vtk < 8.2.

To be honest, we probably do not need it anymore.

@GuillaumeFavelier GuillaumeFavelier changed the title WIP,ENH: new coreg gui features ENH: new coreg gui features Dec 6, 2021
@agramfort
Copy link
Member

trying to unselect "show high resolution head" on my mac produces a segfault. Can someelse replicate? Just untick the box just after starting the GUI.

❯ mne coreg -s sample -d ~/mne_data/MNE-sample-data/subjects --interaction=trackball -f ~/mne_data/MNE-sample-data/MEG/sample/sample_audvis_raw.fif
python3.8(72101,0x10aa1cdc0) malloc: Incorrect checksum for freed object 0x7fef1ba26a00: probably modified after being freed.
Corrupt value: 0x101010101010101
python3.8(72101,0x10aa1cdc0) malloc: *** set a breakpoint in malloc_error_break to debug
Fatal Python error: Aborted

Current thread 0x000000010aa1cdc0 (most recent call first):
File "/Users/alex/miniconda3/lib/python3.8/site-packages/vtkmodules/qt/QVTKRenderWindowInteractor.py", line 381 in paintEvent
File "/Users/alex/work/src/mne-python/mne/viz/backends/_utils.py", line 163 in _qt_app_exec
File "/Users/alex/work/src/mne-python/mne/gui/_coreg.py", line 249 in init
File "", line 24 in init
File "/Users/alex/work/src/mne-python/mne/gui/init.py", line 192 in coregistration
File "", line 24 in coregistration
File "/Users/alex/work/src/mne-python/mne/commands/mne_coreg.py", line 89 in run
File "/Users/alex/work/src/mne-python/mne/commands/utils.py", line 107 in main
File "/Users/alex/miniconda3/bin/mne", line 33 in
[1] 72101 abort mne coreg -s sample -d ~/mne_data/MNE-sample-data/subjects -f

@GuillaumeFavelier
Copy link
Contributor Author

trying to unselect "show high resolution head" on my mac produces a segfault.

I have the same behaviour

@agramfort
Copy link
Member

agramfort commented Dec 6, 2021 via email

@GuillaumeFavelier
Copy link
Contributor Author

yes, trying to see what is going on suddenly with this head :)

@GuillaumeFavelier
Copy link
Contributor Author

The crash seems related to the _grow_hair_changed() call in _hair_resolution_changed() so I pushed a few commits to rework grow_hair and obtain something compatible with the new redraw system. What do you think @larsoner, @agramfort ?

@larsoner
Copy link
Member

larsoner commented Dec 6, 2021

I pushed a few commits to rework grow_hair and obtain something compatible with the new redraw system. What do you think @larsoner, @agramfort ?

When I saw your comment about it being related to the hair growth stuff, my thought was "we should separate the update of the head geometry variable from the update of the PyVista plot", and it looks like indeed that's what you did, so I'll go ahead and fix the conflict and merge hopefully. I also noticed in @hoechenberger's PR some pyvista version comparisons we no longer need I think.

* upstream/main:
  Use fixes._compare_version for version checks everywhere (mne-tools#10091)
  Fast annotation from mask (mne-tools#10089)
  fix trace offsets in butterfly mode (mne-tools#10087)
  fix plot_compare_evokeds topo legend axes placement (mne-tools#9927)
  doc: clarify ica.apply include and exclude params (mne-tools#10086)
  MRG: Make y a required parameter in CSP.fit_transform() (mne-tools#10084)
  Add scrollbar to report tag dropdown menu (mne-tools#10082)
@larsoner larsoner merged commit 0ad069b into mne-tools:main Dec 6, 2021
@larsoner
Copy link
Member

larsoner commented Dec 6, 2021

Thanks @GuillaumeFavelier !

@GuillaumeFavelier GuillaumeFavelier deleted the enh/coreg_feats branch December 6, 2021 18:54
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.

3 participants