mne-tools / mne-python

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

ENH: Add time x axis labels to epochs.plot #10367

Open larsoner opened 2 years ago

larsoner commented 2 years ago

... maybe just in mne-qt-browser if it can't look good in matplotlib. See https://mne.discourse.group/t/adding-y-and-x-axis-values-to-epochs-plot/4370

larsoner commented 2 years ago

cc @marsipu

marsipu commented 2 years ago

Ok I think we could set some custom ticks for this time-mode. How would you set the ticks? If tmin, tmax = (-0.5, 1.5), would you set one tick at 0 and one (shared) tick wth 1.5 for the previous and `-0.5´ for the next epoch? Spacing and n_ticks determined by n_epochs or duration?

larsoner commented 2 years ago

How would you set the ticks? If tmin, tmax = (-0.5, 1.5), would you set one tick at 0 and one (shared) tick wth 1.5 for the previous and `-0.5´ for the next epoch? Spacing and n_ticks determined by n_epochs or duration?

This is the tough part -- I think it will require some real-world testing, tweaking, and iteration. There are lots of epochs with lots of tmin/tmax and even time spans (e.g., ABR data can just be < 20 ms in duration; resting state can have 10-60 sec epochs), and this will interact also with the number of epochs shown in the window at once, etc. So I don't know of a good solution offhand

larsoner commented 2 years ago

... thinking about this more, I worry about it becoming very busy with limited benefit. I wonder if the way to go here is to have a single time scale bar (in the lower left) like we have for channels (in the upper left) that shows the largest of these bars that fits between zero (or tmin) to tmax : [1 ms, 5 ms, 10 ms, 50 ms, 100 ms, 1 s, 5 s, 10s, 20s, 30s, 60s]. I think this would cover 99% of use cases, and gives people a nice sense of relative scale. Then to get a precise time measurement, support for clicking/dragging a green indicator line into place (with a text overlay of the precise time) would work.

At the very least, this "time scale bar" should be easily doable in both backends. The time line is probably also doable.

What do you think @marsipu ?

marsipu commented 2 years ago

I think too that this would be a better solution than cluttering the x-axis more with ticks, nice idea with the "time scale bar".

Then to get a precise time measurement, support for clicking/dragging a green indicator line into place (with a text overlay of the precise time) would work.

Isn't this already working with the green vertical line? I adapted it for epochs too. Or do you mean something else? Maybe we can also raise more awareness for the crosshair activated with pressing "x"?

P.S. Unfortunately I won't be able to implement additional features like this soon because preparation for my big exam on April 5th goes into final stage now.

jadrew43 commented 2 years ago

Would this require the definition of variables analogous to mne.units and mne.units_scalings for the epoch domain? Also, what is the meaning behind mne.units_scalings for each channel type? Is mne.units_scaling mne.units the scale for the y-axis?

drammock commented 2 years ago

@jadrew43 take a look here:

https://github.com/mne-tools/mne-python/blob/a9bdf81d21626c22dc879154367648515bcea3cd/mne/viz/_mpl_figure.py#L1550-L1606

this is how the scalebars on the y axis are done in the matplotlib backend. There will be something analogous in the mne_qt_browser repo I think, for the qtgraph backend. So you'll need to adapt that to handle drawing a horizontal scalebar on the x axis (and figure out how long it should be based on the epoch duration).

Would this require the definition of variables analogous to mne.units and mne.units_scalings

I don't think so; time is always in seconds for us, where as signal amplitude might be Volts, Teslas/meter, etc.

jadrew43 commented 2 years ago

Yup, I'm looking at something similar in the mne-qt-browser repo. The position variable definitions don't seem to be as straightforward. Where does it call for x and y coordinates? _update_scalebar_*_positions() seem to be updating as you interact with the interface but not asking for coordinates like the matplotlib script does.

https://github.com/mne-tools/mne-qt-browser/blob/main/mne_qt_browser/_pg_figure.py#L3279-L3337

drammock commented 2 years ago

If I understand your question correctly: they're defined within those update methods:

https://github.com/mne-tools/mne-qt-browser/blob/6b67dd5af1ef0e39590ffacfbd4dffd8bd7d273d/mne_qt_browser/_pg_figure.py#L1429-L1434

e.g., here the x value is always self.mne.t_start.

jadrew43 commented 2 years ago

I wasn't able to figure this out for the qt backend but got something working for matplotlib! The only possible issue I see now is drawing the scalebar at y=19.5 instead of something like y=n_channels - offset where n_channels=20 is the default used in epochs.plot(). Would it be easier to make n_channels a global variable or to pass it along within **kwargs?

drammock commented 2 years ago

I wasn't able to figure this out for the qt backend but got something working for matplotlib!

Nice! I probably won't have time to review until Tuesday; maybe if @marsipu is available he could look?

marsipu commented 2 years ago

I wasn't able to figure this out for the qt backend but got something working for matplotlib!

Nice! I probably won't have time to review until Tuesday; maybe if @marsipu is available he could look?

I did 👍🏻 But we still need your approval to run CI's