def _save_bads(*, bads, bids_path, verbose): """Update the set of channels marked as bad.""" channels_tsv_fname = bids_path.copy().update(suffix='channels', extension='.tsv') channels_tsv_data = _from_tsv(channels_tsv_fname) descriptions = [] for ch_name in bads: idx = channels_tsv_data['name'].index(ch_name) if channels_tsv_data['status'][idx] == 'bad': # Channel was already marked as bad, retain existing description. description = channels_tsv_data['status_description'][idx] else: # Channel has been manually marked as bad during inspection, assign # default description. description = 'Manual inspection via MNE-BIDS' descriptions.append(description) # We pass overwrite=True, causing all channels not passed as bad here to # be marked as good. mark_bad_channels(ch_names=bads, descriptions=descriptions, bids_path=bids_path, overwrite=True, verbose=verbose)
def _save_bads(*, bads, descriptions, bids_path, verbose): """Update the set of channels marked as bad. Parameters ---------- bads : list The complete list of bad channels. descriptions : list The values to be written to the `status_description` column. """ # We pass overwrite=True, causing all channels not passed as bad here to # be marked as good. mark_bad_channels(ch_names=bads, descriptions=descriptions, bids_path=bids_path, overwrite=True, verbose=verbose)
# Read the (now BIDS-formatted) data and print a list of channels currently # marked as bad. raw = read_raw_bids(bids_path=bids_path, verbose=False) print(f'The following channels are currently marked as bad:\n' f' {", ".join(raw.info["bads"])}\n') ############################################################################### # So currently, two channels are maked as bad: ``EEG 053`` and ``MEG 2443``. # Let's assume that through visual data inspection, we found that two more # MEG channels are problematic, and we would like to mark them as bad as well. # To do that, we simply add them to a list, which we then pass to # :func:`mne_bids.mark_bad_channels`: bads = ['MEG 0112', 'MEG 0131'] mark_bad_channels(ch_names=bads, bids_path=bids_path, verbose=False) ############################################################################### # That's it! Let's verify the result. raw = read_raw_bids(bids_path=bids_path, verbose=False) print(f'After marking MEG 0112 and MEG 0131 as bad, the following channels ' f'are now marked as bad:\n {", ".join(raw.info["bads"])}\n') ############################################################################### # As you can see, now a total of **four** channels is marked as bad: the ones # that were already bad when we started – ``EEG 053`` and ``MEG 2443`` – and # the two channels we passed to :func:`mne_bids.mark_bad_channels` – # ``MEG 0112`` and ``MEG 0131``. This shows that marking bad channels via # :func:`mne_bids.mark_bad_channels`, by default, is an **additive** procedure, # which allows you to mark additional channels as bad while retaining the
def run(): """Run the mark_bad_channels command.""" from mne.commands.utils import get_optparser parser = get_optparser(__file__, usage="usage: %prog options args", prog_prefix='mne_bids', version=mne_bids.__version__) parser.add_option('--ch_name', dest='ch_names', action='append', default=[], help='The names of the bad channels. If multiple ' 'channels are bad, pass the --ch_name parameter ' 'multiple times.') parser.add_option('--description', dest='descriptions', action='append', default=[], help='Descriptions as to why the channels are bad. ' 'Must match the number of bad channels provided. ' 'Pass multiple times to supply more than one ' 'value in that case.') parser.add_option('--bids_root', dest='bids_root', help='The path of the folder containing the BIDS ' 'dataset') parser.add_option('--subject_id', dest='subject', help=('Subject name')) parser.add_option('--session_id', dest='session', help='Session name') parser.add_option('--task', dest='task', help='Task name') parser.add_option('--acq', dest='acquisition', help='Acquisition parameter') parser.add_option('--run', dest='run', help='Run number') parser.add_option('--proc', dest='processing', help='Processing label.') parser.add_option('--rec', dest='recording', help='Recording name') parser.add_option('--type', dest='datatype', help='Recording data type, e.g. meg, ieeg or eeg') parser.add_option('--suffix', dest='suffix', help='The filename suffix, i.e. the last part before ' 'the extension') parser.add_option('--ext', dest='extension', help='The filename extension, including the leading ' 'period, e.g. .fif') parser.add_option('--overwrite', dest='overwrite', action='store_true', help='Replace existing channel status entries') parser.add_option('--verbose', dest='verbose', action='store_true', help='Whether do generate additional diagnostic output') opt, args = parser.parse_args() if args: parser.print_help() parser.error(f'Please do not specify arguments without flags. ' f'Got: {args}.\n') if opt.bids_root is None: parser.print_help() parser.error('You must specify bids_root') if opt.ch_names is None: parser.print_help() parser.error('You must specify some --ch_name parameters.') ch_names = [] if opt.ch_names == [''] else opt.ch_names bids_path = BIDSPath(subject=opt.subject, session=opt.session, task=opt.task, acquisition=opt.acquisition, run=opt.run, processing=opt.processing, recording=opt.recording, datatype=opt.datatype, suffix=opt.suffix, extension=opt.extension, root=opt.bids_root) bids_paths = bids_path.match() # Only keep data we can actually read & write. allowed_extensions = list(reader.keys()) bids_paths = [p for p in bids_paths if p.extension in allowed_extensions] if not bids_paths: logger.info('No matching files found. Please consider using a less ' 'restrictive set of entities to broaden the search.') return # XXX should be return with an error code? logger.info(f'Marking channels {", ".join(ch_names)} as bad in ' f'{len(bids_paths)} recording(s) …') for bids_path in bids_paths: logger.info(f'Processing: {bids_path.basename}') mark_bad_channels(ch_names=ch_names, descriptions=opt.descriptions, bids_path=bids_path, overwrite=opt.overwrite, verbose=opt.verbose)