def run_report_sensor(*, cfg: SimpleNamespace, subject: str, session: Optional[str] = None, report: mne.Report) -> mne.Report: import matplotlib.pyplot as plt msg = 'Generating sensor-space analysis report …' logger.info( **gen_log_kwargs(message=msg, subject=subject, session=session)) if report is None: report = _gen_empty_report(cfg=cfg, subject=subject, session=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) fname_epo_clean = bids_path.copy().update(processing='clean', suffix='epo') fname_ave = bids_path.copy().update(suffix='ave') fname_decoding = bids_path.copy().update(processing=None, suffix='decoding', extension='.mat') fname_tfr_pow = bids_path.copy().update(suffix='power+condition+tfr', extension='.h5') ########################################################################### # # Visualize evoked responses. # if cfg.conditions is None: conditions = [] elif isinstance(cfg.conditions, dict): conditions = list(cfg.conditions.keys()) else: conditions = cfg.conditions.copy() conditions.extend(cfg.contrasts) if conditions: evokeds = mne.read_evokeds(fname_ave) else: evokeds = [] if evokeds: msg = (f'Adding {len(conditions)} evoked signals and contrasts to the ' f'report.') else: msg = 'No evoked conditions or contrasts found.' logger.info( **gen_log_kwargs(message=msg, subject=subject, session=session)) for condition, evoked in zip(conditions, evokeds): if cfg.analyze_channels: evoked.pick(cfg.analyze_channels) if condition in cfg.conditions: title = f'Condition: {condition}' tags = ('evoked', condition.lower().replace(' ', '-')) else: # It's a contrast of two conditions. title = f'Contrast: {condition[0]} – {condition[1]}' tags = ('evoked', 'contrast', f"{condition[0].lower().replace(' ', '-')}-" f"{condition[1].lower().replace(' ', '-')}") report.add_evokeds(evokeds=evoked, titles=title, tags=tags) ########################################################################### # # Visualize decoding results. # if cfg.decode: msg = 'Adding time-by-time decoding results to the report.' logger.info( **gen_log_kwargs(message=msg, subject=subject, session=session)) epochs = mne.read_epochs(fname_epo_clean) for contrast in cfg.contrasts: cond_1, cond_2 = contrast a_vs_b = f'{cond_1}+{cond_2}'.replace(op.sep, '') processing = f'{a_vs_b}+{cfg.decoding_metric}' processing = processing.replace('_', '-').replace('-', '') fname_decoding_ = (fname_decoding.copy().update( processing=processing)) decoding_data = loadmat(fname_decoding_) del fname_decoding_, processing, a_vs_b fig = plot_decoding_scores( times=epochs.times, cross_val_scores=decoding_data['scores'], metric=cfg.decoding_metric) title = f'Time-by-time Decoding: {cond_1} ./. {cond_2}' caption = (f'{len(epochs[cond_1])} × {cond_1} ./. ' f'{len(epochs[cond_2])} × {cond_2}') tags = ('epochs', 'contrast', f"{contrast[0].lower().replace(' ', '-')}-" f"{contrast[1].lower().replace(' ', '-')}") report.add_figure(fig=fig, title=title, caption=caption, tags=tags) plt.close(fig) del decoding_data, cond_1, cond_2, title, caption del epochs ########################################################################### # # Visualize TFR as topography. # if cfg.time_frequency_conditions is None: conditions = [] elif isinstance(cfg.time_frequency_conditions, dict): conditions = list(cfg.time_frequency_conditions.keys()) else: conditions = cfg.time_frequency_conditions.copy() if conditions: msg = 'Adding TFR analysis results to the report.' logger.info( **gen_log_kwargs(message=msg, subject=subject, session=session)) for condition in conditions: cond = config.sanitize_cond_name(condition) fname_tfr_pow_cond = str(fname_tfr_pow.copy()).replace( "+condition+", f"+{cond}+") power = mne.time_frequency.read_tfrs(fname_tfr_pow_cond) fig = power[0].plot_topo(show=False, fig_facecolor='w', font_color='k', border='k') report.add_figure(fig=fig, title=f'TFR: {condition}', caption=f'TFR Power: {condition}', tags=('time-frequency', condition.lower().replace(' ', '-'))) plt.close(fig) return report