|
5 | 5 | # Andrew Dykstra <andrew.r.dykstra@gmail.com>
|
6 | 6 | # Teon Brooks <teon.brooks@gmail.com>
|
7 | 7 | # Daniel McCloy <dan.mccloy@gmail.com>
|
| 8 | +# Ana Radanovic <radanovica@protonmail.com> |
| 9 | +# Erica Peterson <nordme@uw.edu> |
8 | 10 | #
|
9 | 11 | # License: BSD-3-Clause
|
10 | 12 |
|
@@ -206,6 +208,83 @@ def equalize_channels(instances, copy=True, verbose=None):
|
206 | 208 | return equalized_instances
|
207 | 209 |
|
208 | 210 |
|
| 211 | +def unify_bad_channels(insts): |
| 212 | + """Unify bad channels across a list of instances. |
| 213 | +
|
| 214 | + All instances must be of the same type and have matching channel names and channel |
| 215 | + order. The ``.info["bads"]`` of each instance will be set to the union of |
| 216 | + ``.info["bads"]`` across all instances. |
| 217 | +
|
| 218 | + Parameters |
| 219 | + ---------- |
| 220 | + insts : list |
| 221 | + List of instances (:class:`~mne.io.Raw`, :class:`~mne.Epochs`, |
| 222 | + :class:`~mne.Evoked`, :class:`~mne.time_frequency.Spectrum`, |
| 223 | + :class:`~mne.time_frequency.EpochsSpectrum`) across which to unify bad channels. |
| 224 | +
|
| 225 | + Returns |
| 226 | + ------- |
| 227 | + insts : list |
| 228 | + List of instances with bad channels unified across instances. |
| 229 | +
|
| 230 | + See Also |
| 231 | + -------- |
| 232 | + mne.channels.equalize_channels |
| 233 | + mne.channels.rename_channels |
| 234 | + mne.channels.combine_channels |
| 235 | +
|
| 236 | + Notes |
| 237 | + ----- |
| 238 | + This function modifies the instances in-place. |
| 239 | +
|
| 240 | + .. versionadded:: 1.6 |
| 241 | + """ |
| 242 | + from ..io import BaseRaw |
| 243 | + from ..epochs import Epochs |
| 244 | + from ..evoked import Evoked |
| 245 | + from ..time_frequency.spectrum import BaseSpectrum |
| 246 | + |
| 247 | + # ensure input is list-like |
| 248 | + _validate_type(insts, (list, tuple), "insts") |
| 249 | + # ensure non-empty |
| 250 | + if len(insts) == 0: |
| 251 | + raise ValueError("insts must not be empty") |
| 252 | + # ensure all insts are MNE objects, and all the same type |
| 253 | + inst_type = type(insts[0]) |
| 254 | + valid_types = (BaseRaw, Epochs, Evoked, BaseSpectrum) |
| 255 | + for inst in insts: |
| 256 | + _validate_type(inst, valid_types, "each object in insts") |
| 257 | + if type(inst) != inst_type: |
| 258 | + raise ValueError("All insts must be the same type") |
| 259 | + |
| 260 | + # ensure all insts have the same channels and channel order |
| 261 | + ch_names = insts[0].ch_names |
| 262 | + for inst in insts[1:]: |
| 263 | + dif = set(inst.ch_names) ^ set(ch_names) |
| 264 | + if len(dif): |
| 265 | + raise ValueError( |
| 266 | + "Channels do not match across the objects in insts. Consider calling " |
| 267 | + "equalize_channels before calling this function." |
| 268 | + ) |
| 269 | + elif inst.ch_names != ch_names: |
| 270 | + raise ValueError( |
| 271 | + "Channel names are sorted differently across instances. Please use " |
| 272 | + "mne.channels.equalize_channels." |
| 273 | + ) |
| 274 | + |
| 275 | + # collect bads as dict keys so that insertion order is preserved, then cast to list |
| 276 | + all_bads = dict() |
| 277 | + for inst in insts: |
| 278 | + all_bads.update(dict.fromkeys(inst.info["bads"])) |
| 279 | + all_bads = list(all_bads) |
| 280 | + |
| 281 | + # update bads on all instances |
| 282 | + for inst in insts: |
| 283 | + inst.info["bads"] = all_bads |
| 284 | + |
| 285 | + return insts |
| 286 | + |
| 287 | + |
209 | 288 | class ReferenceMixin(MontageMixin):
|
210 | 289 | """Mixin class for Raw, Evoked, Epochs."""
|
211 | 290 |
|
|
0 commit comments