def compute_cov_from_epochs(subject, session, tmin, tmax): bids_path = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space, extension='.fif', datatype=config.get_datatype(), root=config.deriv_root, check=False) processing = None if config.use_ica or config.use_ssp: processing = 'clean' epo_fname = bids_path.copy().update(processing=processing, suffix='epo') cov_fname = bids_path.copy().update(suffix='cov') msg = (f"Computing regularized covariance based on epochs' baseline " f"periods. Input: {epo_fname}, Output: {cov_fname}") logger.info( gen_log_message(message=msg, step=11, subject=subject, session=session)) epochs = mne.read_epochs(epo_fname, preload=True) cov = mne.compute_covariance(epochs, tmin=tmin, tmax=tmax, method='shrunk', rank='info') cov.save(cov_fname)
def run_forward(*, cfg, subject, session=None): bids_path = BIDSPath(subject=subject, session=session, task=cfg.task, acquisition=cfg.acq, run=None, recording=cfg.rec, space=cfg.space, extension='.fif', datatype=cfg.datatype, root=cfg.deriv_root, check=False) fname_info = bids_path.copy().update(**cfg.source_info_path_update) fname_trans = bids_path.copy().update(suffix='trans') fname_fwd = bids_path.copy().update(suffix='fwd') if cfg.use_template_mri: src, trans, bem_sol = _prepare_forward_fsaverage(cfg) else: src, trans, bem_sol = _prepare_forward(cfg, bids_path, fname_trans) # Finally, calculate and save the forward solution. msg = 'Calculating forward solution' logger.info( **gen_log_kwargs(message=msg, subject=subject, session=session)) info = mne.io.read_info(fname_info) fwd = mne.make_forward_solution(info, trans=trans, src=src, bem=bem_sol, mindist=cfg.mindist) mne.write_trans(fname_trans, fwd['mri_head_t'], overwrite=True) mne.write_forward_solution(fname_fwd, fwd, overwrite=True)
def run_evoked(subject, session=None): bids_path = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, extension='.fif', datatype=config.get_datatype(), root=config.deriv_root) processing = None if config.use_ica or config.use_ssp: processing = 'clean' fname_in = bids_path.copy().update(processing=processing, suffix='epo', check=False) fname_out = bids_path.copy().update(suffix='ave', check=False) msg = f'Input: {fname_in}, Output: {fname_out}' logger.info(gen_log_message(message=msg, step=6, subject=subject, session=session)) epochs = mne.read_epochs(fname_in, preload=True) msg = 'Creating evoked data based on experimental conditions …' logger.info(gen_log_message(message=msg, step=6, subject=subject, session=session)) all_evoked = dict() if isinstance(config.conditions, dict): for new_cond_name, orig_cond_name in config.conditions.items(): evoked = epochs[orig_cond_name].average() evoked.comment = evoked.comment.replace(orig_cond_name, new_cond_name) all_evoked[new_cond_name] = evoked else: for condition in config.conditions: evoked = epochs[condition].average() all_evoked[condition] = evoked if config.contrasts: msg = 'Contrasting evoked responses …' logger.info(gen_log_message(message=msg, step=6, subject=subject, session=session)) for contrast in config.contrasts: cond_1, cond_2 = contrast evoked_diff = mne.combine_evoked([all_evoked[cond_1], all_evoked[cond_2]], weights=[1, -1]) all_evoked[contrast] = evoked_diff evokeds = list(all_evoked.values()) mne.write_evokeds(fname_out, evokeds) if config.interactive: for evoked in evokeds: evoked.plot()
def compute_cov_from_empty_room(subject, session): bids_path = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, extension='.fif', datatype=config.get_datatype(), root=config.deriv_root, check=False) raw_er_fname = bids_path.copy().update(processing='filt', task='noise', suffix='raw') cov_fname = bids_path.copy().update(suffix='cov') extra_params = dict() if not config.use_maxwell_filter and config.allow_maxshield: extra_params['allow_maxshield'] = config.allow_maxshield msg = (f'Computing regularized covariance based on empty-room recording. ' f'Input: {raw_er_fname}, Output: {cov_fname}') logger.info( gen_log_message(message=msg, step=11, subject=subject, session=session)) raw_er = mne.io.read_raw_fif(raw_er_fname, preload=True, **extra_params) cov = mne.compute_raw_covariance(raw_er, method='shrunk', rank='info') cov.save(cov_fname)
def compute_cov_from_empty_room(cfg, subject, session): bids_path = BIDSPath(subject=subject, session=session, task=cfg.task, acquisition=cfg.acq, run=None, recording=cfg.rec, space=cfg.space, extension='.fif', datatype=cfg.datatype, root=cfg.deriv_root, check=False) raw_er_fname = bids_path.copy().update(processing='filt', task='noise', suffix='raw') cov_fname = bids_path.copy().update(suffix='cov') msg = (f'Computing regularized covariance based on empty-room recording. ' f'Input: {raw_er_fname}, Output: {cov_fname}') logger.info( **gen_log_kwargs(message=msg, subject=subject, session=session)) raw_er = mne.io.read_raw_fif(raw_er_fname, preload=True) cov = mne.compute_raw_covariance(raw_er, method='shrunk', rank='info') cov.save(cov_fname)
def compute_cov_from_epochs(cfg, subject, session, tmin, tmax): bids_path = BIDSPath(subject=subject, session=session, task=cfg.task, acquisition=cfg.acq, run=None, processing=cfg.proc, recording=cfg.rec, space=cfg.space, extension='.fif', datatype=cfg.datatype, root=cfg.deriv_root, check=False) processing = None if cfg.spatial_filter is not None: processing = 'clean' epo_fname = bids_path.copy().update(processing=processing, suffix='epo') cov_fname = bids_path.copy().update(suffix='cov') msg = (f"Computing regularized covariance based on epochs' baseline " f"periods. Input: {epo_fname}, Output: {cov_fname}") logger.info( **gen_log_kwargs(message=msg, subject=subject, session=session)) epochs = mne.read_epochs(epo_fname, preload=True) cov = mne.compute_covariance(epochs, tmin=tmin, tmax=tmax, method='shrunk', rank='info') cov.save(cov_fname, overwrite=True)
def test_copyfile_kit(tmpdir): """Test copying and renaming KIT files to a new location.""" output_path = str(tmpdir) data_path = op.join(base_path, 'kit', 'tests', 'data') raw_fname = op.join(data_path, 'test.sqd') hpi_fname = op.join(data_path, 'test_mrk.sqd') electrode_fname = op.join(data_path, 'test.elp') headshape_fname = op.join(data_path, 'test.hsp') subject_id = '01' session_id = '01' run = '01' acq = '01' task = 'testing' raw = mne.io.read_raw_kit( raw_fname, mrk=hpi_fname, elp=electrode_fname, hsp=headshape_fname) _, ext = _parse_ext(raw_fname, verbose=True) datatype = _handle_datatype(raw) bids_path = BIDSPath( subject=subject_id, session=session_id, run=run, acquisition=acq, task=task) kit_bids_path = bids_path.copy().update(acquisition=None, datatype=datatype, root=output_path) bids_fname = str(bids_path.copy().update(datatype=datatype, suffix=datatype, extension=ext, root=output_path)) copyfile_kit(raw_fname, bids_fname, subject_id, session_id, task, run, raw._init_kwargs) assert op.exists(bids_fname) _, ext = _parse_ext(hpi_fname, verbose=True) if ext == '.sqd': kit_bids_path.update(suffix='markers', extension='.sqd') assert op.exists(kit_bids_path) elif ext == '.mrk': kit_bids_path.update(suffix='markers', extension='.mrk') assert op.exists(kit_bids_path) if op.exists(electrode_fname): task, run, key = None, None, 'ELP' elp_ext = '.pos' elp_fname = BIDSPath( subject=subject_id, session=session_id, task=task, run=run, acquisition=key, suffix='headshape', extension=elp_ext, datatype='meg', root=output_path) assert op.exists(elp_fname) if op.exists(headshape_fname): task, run, key = None, None, 'HSP' hsp_ext = '.pos' hsp_fname = BIDSPath( subject=subject_id, session=session_id, task=task, run=run, acquisition=key, suffix='headshape', extension=hsp_ext, datatype='meg', root=output_path) assert op.exists(hsp_fname)
def run_ssp(subject, session=None): # compute SSP on first run of raw run = config.get_runs()[0] bids_path = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=run, recording=config.rec, space=config.space, extension='.fif', datatype=config.get_datatype(), root=config.deriv_root) # Prepare a name to save the data raw_fname_in = bids_path.copy().update(processing='filt', suffix='raw', check=False) # when saving proj, use run=None proj_fname_out = bids_path.copy().update(run=None, suffix='proj', check=False) msg = f'Input: {raw_fname_in}, Output: {proj_fname_out}' logger.info( gen_log_message(message=msg, step=4, subject=subject, session=session)) if raw_fname_in.copy().update(split='01').fpath.exists(): raw_fname_in.update(split='01') raw = mne.io.read_raw_fif(raw_fname_in) # XXX : n_xxx should be options in config msg = 'Computing SSPs for ECG' logger.debug( gen_log_message(message=msg, step=4, subject=subject, session=session)) ecg_projs, ecg_events = compute_proj_ecg(raw, n_grad=1, n_mag=1, n_eeg=0, average=True) msg = 'Computing SSPs for EOG' logger.debug( gen_log_message(message=msg, step=4, subject=subject, session=session)) if config.eog_channels: assert all( [ch_name in raw.ch_names for ch_name in config.eog_channels]) ch_name = ','.join(config.eog_channels) else: ch_name = None eog_projs, eog_events = compute_proj_eog(raw, ch_name=ch_name, n_grad=1, n_mag=1, n_eeg=1, average=True) mne.write_proj(proj_fname_out, eog_projs + ecg_projs)
def run_inverse(subject, session=None): bids_path = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, extension='.fif', datatype=config.get_datatype(), root=config.deriv_root, check=False) fname_ave = bids_path.copy().update(suffix='ave') fname_fwd = bids_path.copy().update(suffix='fwd') fname_cov = bids_path.copy().update(suffix='cov') fname_inv = bids_path.copy().update(suffix='inv') evokeds = mne.read_evokeds(fname_ave) cov = mne.read_cov(fname_cov) forward = mne.read_forward_solution(fname_fwd) info = evokeds[0].info inverse_operator = make_inverse_operator(info, forward, cov, loose=0.2, depth=0.8, rank='info') write_inverse_operator(fname_inv, inverse_operator) # Apply inverse snr = 3.0 lambda2 = 1.0 / snr**2 if isinstance(config.conditions, dict): conditions = list(config.conditions.keys()) else: conditions = config.conditions for condition, evoked in zip(conditions, evokeds): method = config.inverse_method pick_ori = None cond_str = config.sanitize_cond_name(condition) inverse_str = method hemi_str = 'hemi' # MNE will auto-append '-lh' and '-rh'. fname_stc = bids_path.copy().update( suffix=f'{cond_str}+{inverse_str}+{hemi_str}', extension=None) if "eeg" in config.ch_types: evoked.set_eeg_reference('average', projection=True) stc = apply_inverse(evoked=evoked, inverse_operator=inverse_operator, lambda2=lambda2, method=method, pick_ori=pick_ori) stc.save(fname_stc)
def run_forward(subject, session=None): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, prefix=deriv_path, check=False) fname_evoked = bids_basename.copy().update(kind='ave', extension='.fif') fname_trans = bids_basename.copy().update(kind='trans', extension='.fif') fname_fwd = bids_basename.copy().update(kind='fwd', extension='.fif') msg = f'Input: {fname_evoked}, Output: {fname_fwd}' logger.info( gen_log_message(message=msg, step=10, subject=subject, session=session)) # Find the raw data file trans = get_head_mri_trans(bids_basename=(bids_basename.copy().update( run=config.get_runs()[0], prefix=None)), bids_root=config.bids_root) mne.write_trans(fname_trans, trans) src = mne.setup_source_space(subject, spacing=config.spacing, subjects_dir=config.get_fs_subjects_dir(), add_dist=False) evoked = mne.read_evokeds(fname_evoked, condition=0) # Here we only use 3-layers BEM only if EEG is available. if 'eeg' in config.ch_types: model = mne.make_bem_model(subject, ico=4, conductivity=(0.3, 0.006, 0.3), subjects_dir=config.get_fs_subjects_dir()) else: model = mne.make_bem_model(subject, ico=4, conductivity=(0.3, ), subjects_dir=config.get_fs_subjects_dir()) bem = mne.make_bem_solution(model) fwd = mne.make_forward_solution(evoked.info, trans, src, bem, mindist=config.mindist) mne.write_forward_solution(fname_fwd, fwd, overwrite=True)
def run_evoked(subject, session=None): bids_path = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, extension='.fif', datatype=config.get_datatype(), root=config.deriv_root) processing = None if config.use_ica or config.use_ssp: processing = 'clean' fname_in = bids_path.copy().update(processing=processing, suffix='epo', check=False) fname_out = bids_path.copy().update(suffix='ave', check=False) msg = f'Input: {fname_in}, Output: {fname_out}' logger.info( gen_log_message(message=msg, step=6, subject=subject, session=session)) epochs = mne.read_epochs(fname_in, preload=True) msg = 'Creating evoked data based on experimental conditions …' logger.info( gen_log_message(message=msg, step=6, subject=subject, session=session)) evokeds = [] for condition in config.conditions: evoked = epochs[condition].average() evokeds.append(evoked) if config.contrasts: msg = 'Contrasting evoked responses …' logger.info( gen_log_message(message=msg, step=6, subject=subject, session=session)) for contrast in config.contrasts: cond_1, cond_2 = contrast evoked_1 = epochs[cond_1].average() evoked_2 = epochs[cond_2].average() evoked_diff = mne.combine_evoked([evoked_1, evoked_2], weights=[1, -1]) evokeds.append(evoked_diff) mne.write_evokeds(fname_out, evokeds) if config.interactive: for evoked in evokeds: evoked.plot()
def run_forward(subject, session=None): bids_path = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, extension='.fif', datatype=config.get_datatype(), root=config.deriv_root, check=False) fname_evoked = bids_path.copy().update(suffix='ave') fname_trans = bids_path.copy().update(suffix='trans') fname_fwd = bids_path.copy().update(suffix='fwd') msg = f'Input: {fname_evoked}, Output: {fname_fwd}' logger.info( gen_log_message(message=msg, step=10, subject=subject, session=session)) # Retrieve the head -> MRI transformation matrix from the MRI sidecar file # in the input data, and save it to an MNE "trans" file in the derivatives # folder. trans = get_head_mri_trans(bids_path.copy().update( run=config.get_runs()[0], root=config.bids_root)) mne.write_trans(fname_trans, trans) src = mne.setup_source_space(subject, spacing=config.spacing, subjects_dir=config.get_fs_subjects_dir(), add_dist=False) evoked = mne.read_evokeds(fname_evoked, condition=0) # Here we only use 3-layers BEM only if EEG is available. if 'eeg' in config.ch_types: model = mne.make_bem_model(subject, ico=4, conductivity=(0.3, 0.006, 0.3), subjects_dir=config.get_fs_subjects_dir()) else: model = mne.make_bem_model(subject, ico=4, conductivity=(0.3, ), subjects_dir=config.get_fs_subjects_dir()) bem = mne.make_bem_solution(model) fwd = mne.make_forward_solution(evoked.info, trans, src, bem, mindist=config.mindist) mne.write_forward_solution(fname_fwd, fwd, overwrite=True)
def run_inverse(subject, session=None): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, prefix=deriv_path, extension='.fif', check=False) fname_ave = bids_basename.copy().update(kind='ave') fname_fwd = bids_basename.copy().update(kind='fwd') fname_cov = bids_basename.copy().update(kind='cov') fname_inv = bids_basename.copy().update(kind='inv') evokeds = mne.read_evokeds(fname_ave) cov = mne.read_cov(fname_cov) forward = mne.read_forward_solution(fname_fwd) info = evokeds[0].info inverse_operator = make_inverse_operator(info, forward, cov, loose=0.2, depth=0.8, rank='info') write_inverse_operator(fname_inv, inverse_operator) # Apply inverse snr = 3.0 lambda2 = 1.0 / snr**2 for condition, evoked in zip(config.conditions, evokeds): method = config.inverse_method pick_ori = None cond_str = condition.replace(op.sep, '').replace('_', '') inverse_str = method hemi_str = 'hemi' # MNE will auto-append '-lh' and '-rh'. fname_stc = bids_basename.copy().update( kind=f'{cond_str}+{inverse_str}+{hemi_str}', extension=None) stc = apply_inverse(evoked=evoked, inverse_operator=inverse_operator, lambda2=lambda2, method=method, pick_ori=pick_ori) stc.save(fname_stc)
def run_time_frequency(*, cfg, subject, session=None): bids_path = BIDSPath(subject=subject, session=session, task=cfg.task, acquisition=cfg.acq, run=None, recording=cfg.rec, space=cfg.space, datatype=cfg.datatype, root=cfg.deriv_root, check=False) processing = None if cfg.spatial_filter is not None: processing = 'clean' fname_in = bids_path.copy().update(suffix='epo', processing=processing, extension='.fif') msg = f'Input: {fname_in}' logger.info( **gen_log_kwargs(message=msg, subject=subject, session=session)) epochs = mne.read_epochs(fname_in) if cfg.analyze_channels: # We special-case the average reference here. # See 02-sliding_estimator.py for more info. if 'eeg' in cfg.ch_types and cfg.eeg_reference == 'average': epochs.set_eeg_reference('average') else: epochs.apply_proj() epochs.pick(cfg.analyze_channels) freqs = np.arange(cfg.time_frequency_freq_min, cfg.time_frequency_freq_max) n_cycles = freqs / 3. for condition in cfg.time_frequency_conditions: this_epochs = epochs[condition] power, itc = mne.time_frequency.tfr_morlet(this_epochs, freqs=freqs, return_itc=True, n_cycles=n_cycles) condition_str = sanitize_cond_name(condition) power_fname_out = bids_path.copy().update( suffix=f'power+{condition_str}+tfr', extension='.h5') itc_fname_out = bids_path.copy().update( suffix=f'itc+{condition_str}+tfr', extension='.h5') power.save(power_fname_out, overwrite=True) itc.save(itc_fname_out, overwrite=True)
def main(): """Run group average in source space""" msg = 'Running Step 13: Grand-average source estimates' logger.info(gen_log_message(step=13, message=msg)) if not config.run_source_estimation: msg = ' … skipping: run_source_estimation is set to False.' logger.info(gen_log_message(step=13, message=msg)) return mne.datasets.fetch_fsaverage(subjects_dir=config.get_fs_subjects_dir()) parallel, run_func, _ = parallel_func(morph_stc, n_jobs=config.N_JOBS) all_morphed_stcs = parallel(run_func(subject, session) for subject, session in itertools.product(config.get_subjects(), config.get_sessions())) all_morphed_stcs = [morphed_stcs for morphed_stcs, subject in zip(all_morphed_stcs, config.get_subjects())] mean_morphed_stcs = map(sum, zip(*all_morphed_stcs)) subject = 'average' # XXX to fix if config.get_sessions(): session = config.get_sessions()[0] else: session = None bids_path = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space, datatype=config.get_datatype(), root=config.deriv_root, check=False) if isinstance(config.conditions, dict): conditions = list(config.conditions.keys()) else: conditions = config.conditions for condition, this_stc in zip(conditions, mean_morphed_stcs): this_stc /= len(all_morphed_stcs) method = config.inverse_method cond_str = config.sanitize_cond_name(condition) inverse_str = method hemi_str = 'hemi' # MNE will auto-append '-lh' and '-rh'. morph_str = 'morph2fsaverage' fname_stc_avg = bids_path.copy().update( suffix=f'{cond_str}+{inverse_str}+{morph_str}+{hemi_str}') this_stc.save(fname_stc_avg) msg = 'Completed Step 13: Grand-average source estimates' logger.info(gen_log_message(step=13, message=msg))
def test_handle_chpi_reading(tmp_path): """Test reading of cHPI information.""" raw = _read_raw_fif(raw_fname_chpi, allow_maxshield=True) root = tmp_path / 'chpi' root.mkdir() bids_path = BIDSPath(subject='01', session='01', task='audiovisual', run='01', root=root, datatype='meg') bids_path = write_raw_bids(raw, bids_path) raw_read = read_raw_bids(bids_path) assert raw_read.info['hpi_subsystem'] is not None # cause conflicts between cHPI info in sidecar and raw data meg_json_path = bids_path.copy().update(suffix='meg', extension='.json') with open(meg_json_path, 'r', encoding='utf-8') as f: meg_json_data = json.load(f) # cHPI frequency mismatch meg_json_data_freq_mismatch = meg_json_data.copy() meg_json_data_freq_mismatch['HeadCoilFrequency'][0] = 123 _write_json(meg_json_path, meg_json_data_freq_mismatch, overwrite=True) with pytest.warns(RuntimeWarning, match='Defaulting to .* mne.Raw object'): raw_read = read_raw_bids(bids_path) # cHPI "off" according to sidecar, but present in the data meg_json_data_chpi_mismatch = meg_json_data.copy() meg_json_data_chpi_mismatch['ContinuousHeadLocalization'] = False _write_json(meg_json_path, meg_json_data_chpi_mismatch, overwrite=True) raw_read = read_raw_bids(bids_path) assert raw_read.info['hpi_subsystem'] is None assert raw_read.info['hpi_meas'] == []
def run_report( *, cfg: SimpleNamespace, subject: str, session: Optional[str] = None, ): report = _gen_empty_report(cfg=cfg, subject=subject, session=session) kwargs = dict(cfg=cfg, subject=subject, session=session, report=report) report = run_report_preprocessing(**kwargs) report = run_report_sensor(**kwargs) report = run_report_source(**kwargs) bids_path = BIDSPath(subject=subject, session=session, task=cfg.task, acquisition=cfg.acq, run=None, recording=cfg.rec, space=cfg.space, extension='.fif', datatype=cfg.datatype, root=cfg.deriv_root, check=False) fname_report = bids_path.copy().update(suffix='report', extension='.html') report.save(fname=fname_report, open_browser=cfg.interactive, overwrite=True)
class FrozenBIDSPath: def __init__(self, *pargs, check=False, **kwargs): self._bp = BIDSPath(*pargs, check=check, **kwargs) def update(self, *, check=None, **kwargs): copy = self.__class__(subject="dummy", check=False) copy._bp = self._bp.copy().update(**kwargs) return copy def copy(self): return self def __getattr__(self, attr): return getattr(self._bp, attr) def __repr__(self): return repr(self._bp).replace( type(self._bp).__name__, type(self).__name__) def __str__(self): return str(self._bp).replace( type(self._bp).__name__, type(self).__name__) def __dir__(self): own_dir = dir(type(self)) + list(self.__dict__.keys()) return own_dir + [ d for d in dir(self._bp) if not d.startswith("_") and d not in own_dir ]
def plot_events(subject, session): raws_filt = [] bids_path = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, recording=config.rec, space=config.space, processing='filt', suffix='raw', extension='.fif', datatype=config.get_datatype(), root=config.deriv_root, check=False) for run in config.get_runs(): fname = bids_path.copy().update(run=run) raw_filt = mne.io.read_raw_fif(fname) raws_filt.append(raw_filt) del fname # Concatenate the filtered raws and extract the events. raw_filt_concat = mne.concatenate_raws(raws_filt) events, event_id = mne.events_from_annotations(raw=raw_filt_concat) fig = mne.viz.plot_events(events=events, event_id=event_id, first_samp=raw_filt_concat.first_samp, sfreq=raw_filt_concat.info['sfreq'], show=False) return fig
def plot_events(cfg, subject, session): raws_filt = [] raw_fname = BIDSPath(subject=subject, session=session, task=cfg.task, acquisition=cfg.acq, recording=cfg.rec, space=cfg.space, processing='filt', suffix='raw', extension='.fif', datatype=cfg.datatype, root=cfg.deriv_root, check=False) for run in cfg.runs: this_raw_fname = raw_fname.copy().update(run=run) if this_raw_fname.copy().update(split='01').fpath.exists(): this_raw_fname.update(split='01') raw_filt = mne.io.read_raw_fif(this_raw_fname) raws_filt.append(raw_filt) del this_raw_fname # Concatenate the filtered raws and extract the events. raw_filt_concat = mne.concatenate_raws(raws_filt, on_mismatch='warn') events, event_id = mne.events_from_annotations(raw=raw_filt_concat) fig = mne.viz.plot_events(events=events, event_id=event_id, first_samp=raw_filt_concat.first_samp, sfreq=raw_filt_concat.info['sfreq'], show=False) return fig
def plot_er_psd(subject, session): raw_fname = BIDSPath(subject=subject, session=session, acquisition=config.acq, run=None, recording=config.rec, space=config.space, task='noise', processing='filt', suffix='raw', extension='.fif', datatype=config.get_datatype(), root=config.deriv_root, check=False) extra_params = dict() if not config.use_maxwell_filter and config.allow_maxshield: extra_params['allow_maxshield'] = config.allow_maxshield if raw_fname.copy().update(split='01').fpath.exists(): raw_fname.update(split='01') raw_er_filtered = mne.io.read_raw_fif(raw_fname, preload=True, **extra_params) fmax = 1.5 * config.h_freq if config.h_freq is not None else np.inf fig = raw_er_filtered.plot_psd(fmax=fmax, show=False) return fig
def run_average(cfg, session, mean_morphed_stcs): subject = 'average' bids_path = BIDSPath(subject=subject, session=session, task=cfg.task, acquisition=cfg.acq, run=None, processing=cfg.proc, recording=cfg.rec, space=cfg.space, datatype=cfg.datatype, root=cfg.deriv_root, check=False) if isinstance(cfg.conditions, dict): conditions = list(cfg.conditions.keys()) else: conditions = cfg.conditions for condition, stc in zip(conditions, mean_morphed_stcs): method = cfg.inverse_method cond_str = sanitize_cond_name(condition) inverse_str = method hemi_str = 'hemi' # MNE will auto-append '-lh' and '-rh'. morph_str = 'morph2fsaverage' fname_stc_avg = bids_path.copy().update( suffix=f'{cond_str}+{inverse_str}+{morph_str}+{hemi_str}') stc.save(fname_stc_avg)
def morph_stc(cfg, subject, fs_subject, session=None): bids_path = BIDSPath(subject=subject, session=session, task=cfg.task, acquisition=cfg.acq, run=None, recording=cfg.rec, space=cfg.space, datatype=cfg.datatype, root=cfg.deriv_root, check=False) morphed_stcs = [] if cfg.task == 'rest': conditions = ['rest'] else: if isinstance(cfg.conditions, dict): conditions = list(cfg.conditions.keys()) else: conditions = cfg.conditions for condition in conditions: method = cfg.inverse_method cond_str = sanitize_cond_name(condition) inverse_str = method hemi_str = 'hemi' # MNE will auto-append '-lh' and '-rh'. morph_str = 'morph2fsaverage' fname_stc = bids_path.copy().update( suffix=f'{cond_str}+{inverse_str}+{hemi_str}') fname_stc_fsaverage = bids_path.copy().update( suffix=f'{cond_str}+{inverse_str}+{morph_str}+{hemi_str}') stc = mne.read_source_estimate(fname_stc) morph = mne.compute_source_morph(stc, subject_from=fs_subject, subject_to='fsaverage', subjects_dir=cfg.fs_subjects_dir) stc_fsaverage = morph.apply(stc) stc_fsaverage.save(fname_stc_fsaverage) morphed_stcs.append(stc_fsaverage) del fname_stc, fname_stc_fsaverage return morphed_stcs
def apply_ssp(subject, session=None): # load epochs to reject ICA components # compute SSP on first run of raw deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, prefix=deriv_path) fname_in = bids_basename.copy().update(kind='epo', extension='.fif', check=False) fname_out = bids_basename.copy().update(kind='epo', processing='clean', extension='.fif', check=False) epochs = mne.read_epochs(fname_in, preload=True) msg = f'Input: {fname_in}, Output: {fname_out}' logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) proj_fname_in = bids_basename.copy().update(kind='proj', extension='.fif', check=False) msg = f'Reading SSP projections from : {proj_fname_in}' logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) projs = mne.read_proj(proj_fname_in) epochs.add_proj(projs).apply_proj() msg = 'Saving epochs' logger.info( gen_log_message(message=msg, step=5, subject=subject, session=session)) epochs.save(fname_out, overwrite=True)
def run_ssp(subject, session=None): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) # compute SSP on first run of raw run = config.get_runs()[0] bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=run, recording=config.rec, space=config.space, prefix=deriv_path) # Prepare a name to save the data raw_fname_in = bids_basename.copy().update(processing='filt', kind=config.get_kind(), extension='.fif') # when saving proj, use run=None proj_fname_out = bids_basename.copy().update(run=None, kind='proj', extension='.fif', check=False) msg = f'Input: {raw_fname_in}, Output: {proj_fname_out}' logger.info( gen_log_message(message=msg, step=4, subject=subject, session=session)) raw = mne.io.read_raw_fif(raw_fname_in) # XXX : n_xxx should be options in config msg = 'Computing SSPs for ECG' logger.debug( gen_log_message(message=msg, step=4, subject=subject, session=session)) ecg_projs, ecg_events = \ compute_proj_ecg(raw, n_grad=1, n_mag=1, n_eeg=0, average=True) msg = 'Computing SSPs for EOG' logger.debug( gen_log_message(message=msg, step=4, subject=subject, session=session)) eog_projs, eog_events = \ compute_proj_eog(raw, n_grad=1, n_mag=1, n_eeg=1, average=True) mne.write_proj(proj_fname_out, eog_projs + ecg_projs)
def run_time_frequency(subject, session=None): deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, prefix=deriv_path, check=False) processing = None if config.use_ica or config.use_ssp: processing = 'clean' fname_in = bids_basename.copy().update(kind='epo', processing=processing, extension='.fif') msg = f'Input: {fname_in}' logger.info( gen_log_message(message=msg, step=9, subject=subject, session=session)) epochs = mne.read_epochs(fname_in) for condition in config.time_frequency_conditions: this_epochs = epochs[condition] power, itc = mne.time_frequency.tfr_morlet(this_epochs, freqs=freqs, return_itc=True, n_cycles=n_cycles) condition_str = condition.replace(op.sep, '').replace('_', '') power_fname_out = bids_basename.copy().update( kind=f'power+{condition_str}+tfr', extension='.h5') itc_fname_out = bids_basename.copy().update( kind=f'itc+{condition_str}+tfr', extension='.h5') power.save(power_fname_out, overwrite=True) itc.save(itc_fname_out, overwrite=True)
def test_keep_essential_annotations(tmpdir): """Test that essential Annotations are not omitted during I/O roundtrip.""" raw = _read_raw_fif(raw_fname) annotations = mne.Annotations(onset=[raw.times[0]], duration=[1], description=['BAD_ACQ_SKIP']) raw.set_annotations(annotations) # Write data, remove events.tsv, then try to read again bids_path = BIDSPath(subject='01', task='task', datatype='meg', root=tmpdir) with pytest.warns(RuntimeWarning, match='Acquisition skips detected'): write_raw_bids(raw, bids_path, overwrite=True) bids_path.copy().update(suffix='events', extension='.tsv').fpath.unlink() raw_read = read_raw_bids(bids_path) assert len(raw_read.annotations) == len(raw.annotations) == 1 assert (raw_read.annotations[0]['description'] == raw.annotations[0]['description'])
def run_time_decoding(subject, condition1, condition2, session=None): msg = f'Contrasting conditions: {condition1} – {condition2}' logger.info( gen_log_message(message=msg, step=7, subject=subject, session=session)) fname_epochs = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, recording=config.rec, space=config.space, suffix='epo', extension='.fif', datatype=config.get_datatype(), root=config.deriv_root, check=False) epochs = mne.read_epochs(fname_epochs) # We define the epochs and the labels epochs = mne.concatenate_epochs([epochs[condition1], epochs[condition2]]) X = epochs.get_data() n_cond1 = len(epochs[condition1]) n_cond2 = len(epochs[condition2]) y = np.r_[np.ones(n_cond1), np.zeros(n_cond2)] clf = make_pipeline( StandardScaler(), LogisticRegression(solver='liblinear', random_state=config.random_state)) se = SlidingEstimator(clf, scoring=config.decoding_metric, n_jobs=config.N_JOBS) scores = cross_val_multiscore(se, X=X, y=y, cv=config.decoding_n_splits) # let's save the scores now a_vs_b = f'{condition1}-{condition2}'.replace(op.sep, '') processing = f'{a_vs_b}+{config.decoding_metric}' processing = processing.replace('_', '-').replace('-', '') fname_mat = fname_epochs.copy().update(suffix='decoding', processing=processing, extension='.mat') savemat(fname_mat, {'scores': scores, 'times': epochs.times}) fname_tsv = fname_mat.copy().update(extension='.tsv') tabular_data = pd.DataFrame( dict(cond_1=[condition1] * len(epochs.times), cond_2=[condition2] * len(epochs.times), time=epochs.times, mean_crossval_score=scores.mean(axis=0), metric=[config.decoding_metric] * len(epochs.times))) tabular_data.to_csv(fname_tsv, sep='\t', index=False)
def main(): """Run grp ave.""" msg = 'Running Step 13: Grand-average source estimates' logger.info(gen_log_message(step=13, message=msg)) mne.datasets.fetch_fsaverage(subjects_dir=config.get_fs_subjects_dir()) parallel, run_func, _ = parallel_func(morph_stc, n_jobs=config.N_JOBS) all_morphed_stcs = parallel(run_func(subject, session) for subject, session in itertools.product(config.get_subjects(), config.get_sessions())) all_morphed_stcs = [morphed_stcs for morphed_stcs, subject in zip(all_morphed_stcs, config.get_subjects())] mean_morphed_stcs = map(sum, zip(*all_morphed_stcs)) subject = 'average' # XXX to fix if config.get_sessions(): session = config.get_sessions()[0] else: session = None deriv_path = config.get_subject_deriv_path(subject=subject, session=session, kind=config.get_kind()) bids_basename = BIDSPath(subject=subject, session=session, task=config.get_task(), acquisition=config.acq, run=None, processing=config.proc, recording=config.rec, space=config.space, prefix=deriv_path, check=False) for condition, this_stc in zip(config.conditions, mean_morphed_stcs): this_stc /= len(all_morphed_stcs) method = config.inverse_method cond_str = condition.replace(op.sep, '').replace('_', '') inverse_str = method hemi_str = 'hemi' # MNE will auto-append '-lh' and '-rh'. morph_str = 'morph2fsaverage' fname_stc_avg = bids_basename.copy().update( kind=f'{cond_str}+{inverse_str}+{morph_str}+{hemi_str}') this_stc.save(fname_stc_avg) msg = 'Completed Step 13: Grand-average source estimates' logger.info(gen_log_message(step=13, message=msg))
def test_handle_info_reading(): """Test reading information from a BIDS sidecar.json file.""" bids_root = _TempDir() # read in USA dataset, so it should find 50 Hz raw = _read_raw_fif(raw_fname) # write copy of raw with line freq of 60 # bids basename and fname bids_path = BIDSPath(subject='01', session='01', task='audiovisual', run='01', root=bids_root) suffix = "meg" bids_fname = bids_path.copy().update(suffix=suffix, extension='.fif') write_raw_bids(raw, bids_path, overwrite=True) # find sidecar JSON fname bids_fname.update(datatype=suffix) sidecar_fname = _find_matching_sidecar(bids_fname, suffix=suffix, extension='.json') # assert that we get the same line frequency set raw = read_raw_bids(bids_path=bids_path) assert raw.info['line_freq'] == 60 # 2. if line frequency is not set in raw file, then ValueError raw.info['line_freq'] = None with pytest.raises(ValueError, match="PowerLineFrequency .* required"): write_raw_bids(raw, bids_path, overwrite=True) # make a copy of the sidecar in "derivatives/" # to check that we make sure we always get the right sidecar # in addition, it should not break the sidecar reading # in `read_raw_bids` deriv_dir = op.join(bids_root, "derivatives") sidecar_copy = op.join(deriv_dir, op.basename(sidecar_fname)) os.mkdir(deriv_dir) with open(sidecar_fname, "r", encoding='utf-8') as fin: sidecar_json = json.load(fin) sidecar_json["PowerLineFrequency"] = 45 _write_json(sidecar_copy, sidecar_json) raw = read_raw_bids(bids_path=bids_path) assert raw.info['line_freq'] == 60 # 3. assert that we get an error when sidecar json doesn't match _update_sidecar(sidecar_fname, "PowerLineFrequency", 55) with pytest.raises(ValueError, match="Line frequency in sidecar json"): raw = read_raw_bids(bids_path=bids_path) assert raw.info['line_freq'] == 55