mne-tools / mne-python

MNE: Magnetoencephalography (MEG) and Electroencephalography (EEG) in Python
https://mne.tools
BSD 3-Clause "New" or "Revised" License
2.68k stars 1.31k forks source link

Obtaining annotations with plot window still open with fig.mne #9011

Open fishbacp opened 3 years ago

fishbacp commented 3 years ago

The following will allow me, within a separate script, to use fig.mne to recover the bad channels with the plot window open and drop them from raw:

fig=raw.plot() bads=fig.mne.info[‘bads’] raw.drop_channels(bads)

Can we do the same for annotations? In other words, suppose I wish to access annotations within a script without closing the plot window? Does fig.mne.inst.annotations have this capability, or could it modified to do so?

Was asked to post this request here and tag @drammock

agramfort commented 3 years ago

the figure should update the instance automatically on close. For both the bads and the annotations.

have you noticed this? or is it broken?

fishbacp commented 3 years ago

Hi,

Yes, the update of raw works fine when I close the plot window. But for purposes of my application (made with Tkinter), I'd like to have the GUI open adjacent to the plot window. When the user presses a button, raw will be updated, to remove bads and annotations, so that subsequent calculations done by my script can be performed with the plot window still open. After performing calculations, the user could annotate further without having to re-plot.

For bads, I can do this using

fig=raw.plot() bads=fig.mne.info[‘bads’] raw.drop_channels(bads)

Am I correct that

annotations = fig.mne.inst.annotations

retrieves the annotations with the plot window still open? If so, is there a way to remove these annotations from raw without closing the plot window, similar to how I removed the bads above?

Thanks

Paul

On Tue, Mar 9, 2021 at 7:18 AM Alexandre Gramfort notifications@github.com wrote:

the figure should update the instance automatically on close. For both the bads and the annotations.

have you noticed this? or is it broken?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/mne-tools/mne-python/issues/9011#issuecomment-793803325, or unsubscribe https://github.com/notifications/unsubscribe-auth/AJWRNJNGB5NP6S4IG7Q6GX3TCYGX7ANCNFSM4YZUG3MQ .

-- Professor of Mathematics, Grand Valley State University Past-President, Pi Mu Epsilon National Honorary Mathematics Society, Inc.

Department of Mathematics (MAK C-2-408) Grand Valley State University 1 Campus Dr. Allendale, MI 49401 fishbacp@mail.gvsu.edu 616.331.2040 616.331.3120 (fax)

drammock commented 3 years ago

As mentioned in the discourse answer, it is currently possible to access the annotations in that way. But the properties in MNEBrowseFigure.mne.* are undocumented and if your want to make use of them in this way, we should talk about making them documented and stable. Can you describe your app in a little more detail (overall purpose, what things you want to be able to update while the plot is open, etc) so that we can decide how to proceed?

fishbacp commented 3 years ago

The script will eventually be used in a clinical setting. Within the tikinter GUI, the user opens a file and plots it in a separate window using raw.plot. Once bad channels and annotations are removed from the raw data, other buttons in the GUI allow for analysis of the updated data (raw bads and annotations now removed). One such analysis consists of detecting high-frequency oscillation (HFO) detection, the results of which can be presented in different ways.

The goal of leaving the raw plot open is that the user might want to go back in and add/remove channels and/or add/delete annotations before repeating the calculation at a press of a button. Being able to do this with the plot open is more convenient (and efficient) than having the user close the plot window and then plot raw again. I gather from what you and your colleagues have said, I can currently retrieve the bads with the plot window open and remove them from raw using

fig=raw.plot() bads=fig.mne.info[‘bads’] raw.drop_channels(bads)

Also, I can recover the annotation starts and durations with the plot window open using

raw.annotations.onset raw.annotations.duration

So, is there a way to "drop the annotations" from the raw, analogous to dropping the bad channels using raw.drop_channels?

I realize I may just be overlooking a single command that already exists, and I apologize in advance if my explanation is unclear.

Thanks

Paul

On Tue, Mar 9, 2021 at 12:11 PM Daniel McCloy notifications@github.com wrote:

As mentioned in the discourse answer, it is currently possible to access the annotations in that way. But the properties in MNEBrowseFigure.mne.* are undocumented and if your want to make use of them in this way, we should talk about making them documented and stable. Can you describe your app in a little more detail (overall purpose, what things you want to be able to update while the plot is open, etc) so that we can decide how to proceed?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/mne-tools/mne-python/issues/9011#issuecomment-794177656, or unsubscribe https://github.com/notifications/unsubscribe-auth/AJWRNJJNG7OSGMBTEOIY2V3TCZCCRANCNFSM4YZUG3MQ .

-- Professor of Mathematics, Grand Valley State University Past-President, Pi Mu Epsilon National Honorary Mathematics Society, Inc.

Department of Mathematics (MAK C-2-408) Grand Valley State University 1 Campus Dr. Allendale, MI 49401 fishbacp@mail.gvsu.edu 616.331.2040 616.331.3120 (fax)

drammock commented 3 years ago

Dropping the annotations from the raw object already happens automatically / instantly. Try this:

import os
import mne
import matplotlib.pyplot as plt
plt.ion()
dp = mne.datasets.multimodal.data_path()
raw = mne.io.read_raw(os.path.join(dp, 'multimodal_raw.fif'))
fig = raw.plot()

Now in the plot window you can add an annotation (press a to start annotation mode, then click-drag to create an annotation), and then type raw.annotations to see that there is 1 segment. Now go back to the plot and right-click the annotation span to remove it, and type raw.annotations in the terminal again to see that there are now zero segments.

I want to repeat, however, the message that the fig.mne.* namespace is undocumented and, until it is documented, is not guaranteed to be stable. So you can build your app now in a way that makes use of, say, fig.mne.info['bads'], but it's possible that we end up changing the namespace in a way that makes your app stop working.

To give some context: Only in the last 6 months did we switch from using vanilla matplotlib Figure objects to using our own MNEBrowseFigure object. In making that transition, the fig.mne.* namespace was created as a way of keeping track of all the things we need to, to make the figure interactive. It did occur to me that users may eventually want to access those figure properties and maybe even modify them while the figure was open, but the first priority was getting the regular mouse-and-keyboard-based interactivity working properly. Then came a period of finding and fixing all the things that I broke when converting to the custom subclass approach, and now (sooner than I expected) we're at the point where users want to modify an open figure via python commands. This means sorting out which parts of that namespace are actually safe to modify directly, and maybe making some of them private and/or providing some new user-facing methods on the figure (e.g., fig.drop_channels() or similar). What we really want to avoid is the original Raw and the copy of Raw that is being modified by the figure getting out of sync, such that changes to one overwrite changes to the other when the figure is closed, in a way that is unexpected or not obvious.

cbrnr commented 3 years ago

To summarize, raw.annotations are updated immediately, but raw.info["bads"] aren't. Is there a reason why this isn't implemented for bad channels? It should be relatively unproblematic if these channels don't get dropped while the figure is open.

agramfort commented 3 years ago

it should be the case too for bads I agree.