Skip to content

Commit

Permalink
Merge branch 'main' into et
Browse files Browse the repository at this point in the history
  • Loading branch information
larsoner authored Oct 27, 2023
2 parents 1e3c06d + cdad29d commit da1747f
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 9 deletions.
2 changes: 2 additions & 0 deletions doc/changes/devel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Enhancements
- Refactored internals of :func:`mne.read_annotations` (:gh:`11964` by `Paul Roujansky`_)
- Add support for drawing MEG sensors in :ref:`mne coreg` (:gh:`12098` by `Eric Larson`_)
- Add ``check_version=True`` to :ref:`mne sys_info` to check for a new release on GitHub (:gh:`12146` by `Eric Larson`_)
- Bad channels are now colored gray in addition to being dashed when spatial colors are used in :func:`mne.viz.plot_evoked` and related functions (:gh:`12142` by `Eric Larson`_)
- By default MNE-Python creates matplotlib figures with ``layout='constrained'`` rather than the default ``layout='tight'`` (:gh:`12050`, :gh:`12103` by `Mathieu Scheltienne`_ and `Eric Larson`_)
- Enhance :func:`~mne.viz.plot_evoked_field` with a GUI that has controls for time, colormap, and contour lines (:gh:`11942` by `Marijn van Vliet`_)
- Add :class:`mne.viz.ui_events.UIEvent` linking for interactive colorbars, allowing users to link figures and change the colormap and limits interactively. This supports :func:`~mne.viz.plot_evoked_topomap`, :func:`~mne.viz.plot_ica_components`, :func:`~mne.viz.plot_tfr_topomap`, :func:`~mne.viz.plot_projs_topomap`, :meth:`~mne.Evoked.plot_image`, and :meth:`~mne.Epochs.plot_image` (:gh:`12057` by `Santeri Ruuskanen`_)
Expand Down Expand Up @@ -72,6 +73,7 @@ Bugs
- Fix :func:`~mne.viz.plot_volume_source_estimates` with :class:`~mne.VolSourceEstimate` which include a list of vertices (:gh:`12025` by `Mathieu Scheltienne`_)
- Add support for non-ASCII characters in Annotations, Evoked comments, etc when saving to FIFF format (:gh:`12080` by `Daniel McCloy`_)
- Correctly handle passing ``"eyegaze"`` or ``"pupil"`` to :meth:`mne.io.Raw.pick` (:gh:`12019` by `Scott Huberty`_)
- Fix bug with :func:`mne.time_frequency.Spectrum.plot` and related functions where bad channels were not marked (:gh:`12142` by `Eric Larson`_)
- Fix bug with :func:`~mne.viz.plot_raw` where changing ``MNE_BROWSER_BACKEND`` via :func:`~mne.set_config` would have no effect within a Python session (:gh:`12078` by `Santeri Ruuskanen`_)
- Improve handling of ``method`` argument in the channel interpolation function to support :class:`str` and raise helpful error messages (:gh:`12113` by `Mathieu Scheltienne`_)
- Fix combination of ``DIN`` event channels into a single synthetic trigger channel ``STI 014`` by the MFF reader of :func:`mne.io.read_raw_egi` (:gh:`12122` by `Mathieu Scheltienne`_)
Expand Down
14 changes: 11 additions & 3 deletions mne/time_frequency/tests/test_spectrum.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from contextlib import nullcontext
from functools import partial

import matplotlib.pyplot as plt
import numpy as np
import pytest
from matplotlib.colors import same_color
from numpy.testing import assert_allclose, assert_array_equal

from mne import Annotations, create_info, make_fixed_length_epochs
Expand Down Expand Up @@ -449,8 +449,16 @@ def test_plot_spectrum(kind, array, request):
data, freqs = spectrum.get_data(return_freqs=True)
Klass = SpectrumArray if kind == "raw" else EpochsSpectrumArray
spectrum = Klass(data=data, info=spectrum.info, freqs=freqs)
spectrum.info["bads"] = spectrum.ch_names[:1] # one grad channel
spectrum.plot(average=True, amplitude=True, spatial_colors=True)
spectrum.plot(average=False, amplitude=False, spatial_colors=False)
spectrum.plot(average=True, amplitude=False, spatial_colors=False)
n_grad = sum(ch_type == "grad" for ch_type in spectrum.get_channel_types())
for amp, sc in ((True, True), (False, False)):
fig = spectrum.plot(average=False, amplitude=amp, spatial_colors=sc, exclude=())
lines = fig.axes[0].lines[2:] # grads, ignore two vlines
assert len(lines) == n_grad
bad_color = "0.5" if sc else "r"
n_bad = sum(same_color(line.get_color(), bad_color) for line in lines)
assert n_bad == 1
spectrum.plot_topo()
spectrum.plot_topomap()
plt.close("all")
8 changes: 5 additions & 3 deletions mne/viz/evoked.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,15 +679,17 @@ def _plot_lines(
_handle_spatial_colors(
colors, info, idx, this_type, psd, ax, sphere
)
bad_color = (0.5, 0.5, 0.5)
else:
if isinstance(_spat_col, (tuple, str)):
col = [_spat_col]
else:
col = ["k"]
bad_color = "r"
colors = col * len(idx)
for i in bad_ch_idx:
if i in idx:
colors[idx.index(i)] = "r"
for i in bad_ch_idx:
if i in idx:
colors[idx.index(i)] = bad_color

if zorder == "std":
# find the channels with the least activity
Expand Down
7 changes: 7 additions & 0 deletions mne/viz/tests/test_evoked.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import pytest
from matplotlib import gridspec
from matplotlib.collections import PolyCollection
from matplotlib.colors import same_color
from mpl_toolkits.axes_grid1.parasite_axes import HostAxes # spatial_colors
from numpy.testing import assert_allclose

Expand Down Expand Up @@ -134,6 +135,12 @@ def test_plot_evoked():
amplitudes = _get_amplitudes(fig)
assert len(amplitudes) == len(default_picks)
assert evoked.proj is False
assert evoked.info["bads"] == ["MEG 2641", "EEG 004"]
eeg_lines = fig.axes[2].lines
n_eeg = sum(ch_type == "eeg" for ch_type in evoked.get_channel_types())
assert len(eeg_lines) == n_eeg == 4
n_bad = sum(same_color(line.get_color(), "0.5") for line in eeg_lines)
assert n_bad == 1
# Test a click
ax = fig.get_axes()[0]
line = ax.lines[0]
Expand Down
3 changes: 2 additions & 1 deletion mne/viz/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2506,6 +2506,7 @@ def _plot_psd(
if not average:
picks = np.concatenate(picks_list)
info = pick_info(inst.info, sel=picks, copy=True)
bad_ch_idx = [info["ch_names"].index(ch) for ch in info["bads"]]
types = np.array(info.get_channel_types())
ch_types_used = list()
for this_type in _VALID_CHANNEL_TYPES:
Expand Down Expand Up @@ -2538,7 +2539,7 @@ def _plot_psd(
xlim=(freqs[0], freqs[-1]),
ylim=None,
times=freqs,
bad_ch_idx=[],
bad_ch_idx=bad_ch_idx,
titles=titles,
ch_types_used=ch_types_used,
selectable=True,
Expand Down
3 changes: 1 addition & 2 deletions tutorials/intro/70_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
HTML pages it generates are self-contained and do not require a running Python
environment. However, it is less flexible as you can't change code and re-run
something directly within the browser. This tutorial covers the basics of
building a report. As usual, we will start by importing the modules and data we
need:
building a report. As usual, we will start by importing the modules and data we need:
"""

# %%
Expand Down

0 comments on commit da1747f

Please sign in to comment.