Skip to content

RFC, MAINT: changes to 2D plotting #7751

@drammock

Description

@drammock

This issue is for planning changes to our 2D plotting capabilities (roadmap link). As a starting point, here are (I think?) all the functions/methods that make 2D plots, grouped roughly by the kind of plot they generate. Also included is a section for 3D plots that always use matplotlib rather than mayavi/pyvista. Each section is followed by some comments / proposals about what might be done. Some of the proposed changes are big, others are quite minor. When folks have weighed in, I'll convert it to a consolidated checklist for keeping track of which ones are done.

Browse-type windows (scrollable data)

  • raw.plot
  • epochs.plot
  • ica.plot_sources(raw)

possible changes

  1. Anything we can do to speed up the responsiveness of scrolling / scaling of browse-type windows would be desirable.
  2. One possible approach to unifying the underlying code would be a new class MNEBrowseFigure that inherits from matplotlib.figure.Figure and automatically does a bunch of stuff in its __init__ like generating the scrollbars and buttons, setting margins, etc. This would also allow the (somewhat unwieldy) params dictionaries that are passed back and forth to be instead stored as attributes of the Figure object (nested under an mne attribute so they can be accessed as fig.mne.property_name, thereby segregating the MNE-specific attributes from the matplotlib ones). done in MRG, VIZ, MAINT: figure class proof-of-concept #7955
  3. Streamline all browse-type windows (e.g. same color for bad channels/components, same behavior for right/left-clicking on traces/labels, etc.) see Marking bad channels and bad ICs is inconsistent #6531. done in MRG, VIZ, MAINT: Use new figure class for epochs.plot and ICA.plot_sources #8381
  4. unify API:
  5. make annotation text at top toggleable (Toggle Annotations visibility in plot_raw() #8578) addressed in VIZ, ENH: allow show/hide annotations by label #8624

Interactive lineplots (click-drag to pop up scalp topographies, click to show channel names)

  • raw.plot_psd
  • epochs.plot_psd
  • evoked.plot
  • evoked.plot_white
  • evoked.plot_joint

possible changes

  1. evoked.plot_joint currently generates separate figures for each channel type; all the others generate a single figure with subplots for each channel type. It's worth considering whether there's a way for plot_joint to be single-figure like the others.
  2. all of these have options for spatial_colors; the head circle in the inset axes gets stretched to an ellipse when the window is resized. Should fix the aspect ratio of the inset axes if possible. done in MRG, VIZ: equal aspect ratio for inset sensor maps #8545

scalp field maps (possibly w/ trellis)

  • {raw/epochs/evoked/mne.viz}.plot_projs_topomap
  • epochs.plot_psd_topomap
  • evoked.plot_topomap
  • ica.plot_components
  • mne.preprocessing.corrmap
  • mne.viz.plot_arrowmap
  • mne.viz.plot_tfr_topomap

possible changes

  1. make sure all of these have vlim='joint' option
  2. when vlim='joint', there should only be 1 colorbar on far right edge (currently still get 1 per axes)
  3. all of these should have the same trellis-style capability (nrows, ncols)
  4. consistent colorbar labelling (some have units, some don't)
  5. fix TOPOs appear circular for MEG  #8563 done in MRG, FIX, VIZ: correctly triage extrapolation mask for topos based on channel type #8589
  6. fix Consistency in plot_topomap APIs #4122

image plots

  • epochs.plot_image (separate fig per ch_type, has ERP/ERF w/ confint in subplot)
  • evoked.plot_image (one fig for all ch_types)
  • mne.viz.plot_source_spectrogram
  • mne.viz.plot_cov (two figs: cov matrices; SVD spectra)
  • mne.viz.plot_csd

possible changes

  1. does plot_cov need to return 2 figures? Why not one 2x3 fig instead of two 1x3 figs?
  2. is there value in plot_cov having a vlim='joint' option?
  3. can epochs.plot_image be made to work as a single fig?
  4. for some reason plot_csd defaults to viridis colormap. Consistency would dictate that it use Reds like we do for one-sided data everywhere else.

many axes in a topo-style layout

  • raw.plot_psd_topo
  • epochs.plot_topo_image (w/ colorbar)
  • evoked.plot_topo
  • mne.viz.plot_compare_evokeds(axes='topo')

possible changes

  1. raw.plot_psd_topo defaults to black background and "click to magnify" pops up a white-on-black PSD trace for that channel. In contrast, epochs.plot_topo_image does a white-on-black overview but pops up normally-colored magnifications, while evoked.plot_topo does a white-background overview and normally-colored magnifications. These should be consistent (default to white BG always).
  2. plot_compare_evokeds(axes='topo') will generate separate figures for each channel type. Since this approach to topo plotting can be extremely slow, it's worth considering to throw an error if this is requested with multiple ch_types.

layouts / montages

  • {raw/epochs/evoked/mne.viz}.plot_sensors(kind='topomap')
  • mne.viz.plot_montage(kind='topomap')
  • mne.viz.plot_layout

possible changes

  1. similar to the discussion about being too MEG-centric in Set all types to False in pick_types #7710, why should raw.plot_sensors() default to 'mag'?
  2. raw.plot_sensors(ch_groups='position') doesn't actually color-code the 8 different regions?

barplots

  • epochs.plot_drop_log
  • ica.plot_scores

possible changes

  1. plot_drop_log blocks execution, but is not interactive in any way. It should not block.
  2. epochs.plot_drop_log default title is "unknown", should be "unknown subject" to be consistent with the corresponding mne.viz function

static time series (possibly multi-panel)

  • ica.plot_overlay
  • ica.plot_sources(evoked)
  • mne.viz.plot_compare_evokeds
  • mne.viz.plot_dipole_amplitudes
  • mne.viz.plot_filter
  • mne.viz.plot_ideal_filter
  • mne.viz.plot_head_positions
  • mne.viz.plot_snr_estimate

possible changes

  1. plot_compare_evokeds is only interactive if axes='topo', and should not otherwise block execution
  2. TODO: many in this category are ones I rarely use, should revisit after more extensive testing
  3. plot_compare_evokeds does not have a scalings parameter (Scaling parameter for mne.viz.plot_compare_evokeds #8556)

misc

  • ica.plot_properties (4 heterogeneous subplots)
  • mne.viz.plot_bem (images + overlaid curves, in a trellis)
  • mne.viz.plot_connectivity_circle (highly custom)
  • mne.viz.plot_events
  • various help windows for the interactive plots
  • settings windows for turning proj on and off

possible changes

  1. Similar to the browse-style proposal, some lightweight custom figure classes might help here to streamline the code (i.e., for the help windows and proj settings windows)
  2. I'm kind of surprised that matplotlib doesn't have built-in chord diagram support. We should consider spinning off our plot_connectivity_circle into a more general function and get it into matplotlib, so others can use it (and to lower our maintenance burden). See also this implementation. (Surprisingly, both Bokeh and Plotly used to have chord diagrams and apparently no longer do? Seems like circos and D3 (and an R wrapper of D3) are the only maintained implementations nowadays)
  3. examine the usage of _prepare_trellis for plot_bem; it's rather unlike all the other uses of trellis in the codebase. Probably nothing wrong with it, but worth looking at / keeping in mind if changes to _prepare_trellis happen for other reasons.

matplotlib 3D

  • mne.viz.plot_dipole_locations(mode='orthoview')
  • mne.viz.plot_montage(kind='3d')
  • mne.viz.plot_sensors(kind='3d')

possible changes

  1. defaults seem to be a little different in plot_montage vs plot_sensors. Make them consistent / deduplicate where possible.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions