[7f9fb8]: / mne / utils / spectrum.py

Download this file

105 lines (84 with data), 3.8 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
"""Utility functions for spectral and spectrotemporal analysis."""
# Authors: The MNE-Python contributors.
# License: BSD-3-Clause
# Copyright the MNE-Python contributors.
from inspect import currentframe, getargvalues, signature
from ..utils import warn
def _get_instance_type_string(inst):
"""Get string representation of the originating instance type."""
from numpy import ndarray
from ..epochs import BaseEpochs
from ..evoked import Evoked, EvokedArray
from ..io import BaseRaw
parent_classes = inst._inst_type.__bases__
if BaseRaw in parent_classes:
inst_type_str = "Raw"
elif BaseEpochs in parent_classes:
inst_type_str = "Epochs"
elif inst._inst_type in (Evoked, EvokedArray):
inst_type_str = "Evoked"
elif inst._inst_type == ndarray:
inst_type_str = "Array"
else:
raise RuntimeError(
f"Unknown instance type {inst._inst_type} in {type(inst).__name__}"
)
return inst_type_str
def _pop_with_fallback(mapping, key, fallback_fun):
"""Pop from a dict and fallback to a function parameter's default value."""
fallback = signature(fallback_fun).parameters[key].default
return mapping.pop(key, fallback)
def _update_old_psd_kwargs(kwargs):
"""Modify passed-in kwargs to match new API.
NOTE: using plot_raw_psd as fallback (even for epochs) is fine because
their kwargs are the same (and will stay the same: both are @legacy funcs).
"""
from ..viz import plot_raw_psd as fallback_fun
may_change = ("axes", "alpha", "ci_alpha", "amplitude", "ci")
for kwarg in may_change:
if kwarg in kwargs:
warn(
"The legacy plot_psd() method got an unexpected keyword argument "
f"'{kwarg}', which is a parameter of Spectrum.plot(). Try rewriting as "
f"object.compute_psd(...).plot(..., {kwarg}=<whatever>)."
)
kwargs.setdefault("axes", _pop_with_fallback(kwargs, "ax", fallback_fun))
kwargs.setdefault("alpha", _pop_with_fallback(kwargs, "line_alpha", fallback_fun))
kwargs.setdefault(
"ci_alpha", _pop_with_fallback(kwargs, "area_alpha", fallback_fun)
)
est = _pop_with_fallback(kwargs, "estimate", fallback_fun)
kwargs.setdefault("amplitude", est == "amplitude")
area_mode = _pop_with_fallback(kwargs, "area_mode", fallback_fun)
kwargs.setdefault("ci", "sd" if area_mode == "std" else area_mode)
def _split_psd_kwargs(*, plot_fun=None, kwargs=None):
from ..io import BaseRaw
from ..time_frequency import Spectrum
# if no kwargs supplied, get them from calling func
if kwargs is None:
frame = currentframe().f_back
arginfo = getargvalues(frame)
kwargs = {k: v for k, v in arginfo.locals.items() if k in arginfo.args}
if arginfo.keywords is not None: # add in **method_kw
kwargs.update(arginfo.locals[arginfo.keywords])
# for compatibility with `plot_raw_psd`, `plot_epochs_psd` and
# `plot_epochs_psd_topomap` functions (not just the instance methods/mixin)
if "raw" in kwargs:
kwargs["self"] = kwargs.pop("raw")
elif "epochs" in kwargs:
kwargs["self"] = kwargs.pop("epochs")
# `reject_by_annotation` not needed for Epochs or Evoked
if not isinstance(kwargs.pop("self", None), BaseRaw):
kwargs.pop("reject_by_annotation", None)
# handle API changes from .plot_psd(...) to .compute_psd(...).plot(...)
if plot_fun is Spectrum.plot:
_update_old_psd_kwargs(kwargs)
# split off the plotting kwargs
plot_kwargs = {
k: v
for k, v in kwargs.items()
if k in signature(plot_fun).parameters and k != "picks"
}
for k in plot_kwargs:
del kwargs[k]
return kwargs, plot_kwargs