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 browserfig UI events #12819

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from

Conversation

nmarkowitz
Copy link
Contributor

@nmarkowitz nmarkowitz commented Aug 28, 2024

What does this implement/fix?

Creates hook to use UI-events in the Qt browser. Also implements the TimeChange event for the matplotlib-based browser.

Additional information

mne/viz/ui_events.py Show resolved Hide resolved
@wmvanvliet
Copy link
Contributor

This needs a unit test.

@wmvanvliet
Copy link
Contributor

Now the following works:

import mne

path = mne.datasets.sample.data_path()
raw = mne.io.read_raw_fif(path / "MEG/sample/sample_audvis_raw.fif", preload=True)

mne.viz.set_browser_backend("matplotlib")
fig1 = raw.copy().pick("eeg").plot()
fig2 = raw.copy().pick("meg").plot()

mne.viz.ui_events.link(fig1, fig2)

And scrolling through time will update both figures.

@nmarkowitz
Copy link
Contributor Author

@wmvanvliet I added the ChannelBrowse and TimeBrowse ui events. Just need to make unit tests for them

@nmarkowitz
Copy link
Contributor Author

This needs a unit test.

Where/how would I put a unit test? I also saw there's no unit test for Brain and EvokedField objects. Do those need unit tests as well?

mne/viz/ui_events.py Outdated Show resolved Hide resolved
mne/viz/ui_events.py Outdated Show resolved Hide resolved
mne/viz/ui_events.py Outdated Show resolved Hide resolved
mne/viz/ui_events.py Outdated Show resolved Hide resolved
@nmarkowitz
Copy link
Contributor Author

@wmvanvliet the matplotlib and qt browsers (on this branch mne-tools/mne-qt-browser#286 ) are synced in time and channels. It's also working for epochs.

wmvanvliet and others added 4 commits September 10, 2024 12:10
Mouse and keypresses no longer directly update the plot, but instead
generate the appropriate UI events. Figures always listen and respond to
their own UI events, which is where the updating of the figure happens.
This way, there is a single place in the code where checking of corner
cases, etc. happens.

In addition, the matplotlib xdata timeline is different from actual
times in the Raw object. UI events should always be meaningful outside
of the figure. Hence, TimeChange and TimeBrowse should give the selected
times in terms of the original Raw object. Various translations
therefore need to happen.
@wmvanvliet
Copy link
Contributor

I've overhauled the event code in the matplotlib figure a bit. The biggest improvement is that now the TimeBrowse event generates meaningful time_start and time_end values. So if you open a raw browser and an epochs browser side-by-side, you can link the event streams and have their scrolling behavior synced. Try this out:

import mne
path = mne.datasets.sample.data_path()
raw = mne.io.read_raw_fif(path / "MEG" / "sample" / "sample_audvis_raw.fif")
events = mne.find_events(raw)
epochs = mne.Epochs(raw, events, preload=True)
mne.viz.set_browser_backend('matplotlib')

fig1 = raw.plot(events=events)
fig2 = epochs.plot()

def on_time_browse_event(event):
    print(event)

def on_channel_browse_event(event):
    print(event)

def on_time_change_event(event):
    print(event)

mne.viz.ui_events.subscribe(fig2, 'time_browse', on_time_browse_event)
mne.viz.ui_events.subscribe(fig2, 'channel_browse', on_channel_browse_event)
mne.viz.ui_events.subscribe(fig2, 'time_change', on_time_change_event)
mne.viz.ui_events.link(fig2, fig1, include_events=['time_browse', 'channel_browse'])

@wmvanvliet
Copy link
Contributor

another improvement is that the figure is no longer updated twice on every keypress. Before, the keypress first updated the figure and then generated the UI event, which caused the event handler to update the figure again. Now, the keypress just generates the UI event and lets the event handler take care of updating the figure.

@nmarkowitz
Copy link
Contributor Author

Should we do the same for the vertical bar? Currently when the vertical bar appears in epoch mode all epochs at that timepoint are marked with a vertical bar. So raw time doesn't matter here.

@wmvanvliet
Copy link
Contributor

I've updated the TimeChange event (the vertical bar) to properly indicate the time in the epoch (from tmin to tmax instead of from 0 to epoch duration)

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