Created
April 15, 2025 10:10
-
-
Save wmvanvliet/bdc0e7679bbc0519ee9b367c37541065 to your computer and use it in GitHub Desktop.
Virtually move head position inside the MEG helmet using MNE-Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Virtually move around head position.""" | |
import os | |
from copy import deepcopy | |
from subprocess import run | |
import mne | |
import numpy as np | |
from move_head import move_head | |
path = mne.datasets.sample.data_path() | |
ev_orig = mne.read_evokeds( | |
path / "MEG/sample/sample_audvis-ave.fif", condition="Left Auditory" | |
) | |
ev_orig.apply_baseline() | |
ev_orig.comment = "original" | |
# Make an Info with the head in the default position. This is only relevant to the | |
# example. Presumably you already have some other data with the desired head position | |
# you want to use. | |
info_dest = deepcopy(ev_orig.info) | |
info_dest["dev_head_t"]["trans"] = np.array( | |
[ | |
[1, 0, 0, 0], | |
[0, 1, 0, 0], | |
[0, 0, 1, 0.04], | |
[0, 0, 0, 1], | |
] | |
) | |
# Move head position using MNE-Python | |
ev_moved = ev_orig.copy() | |
move_head(ev_moved, info_dest) | |
ev_moved.comment = "moved" | |
# Move head position using the maxfilter program | |
if os.path.exists("/tmp/maxfilter_ave.fif"): | |
os.unlink("/tmp/maxfilter_ave.fif") | |
run( | |
[ | |
"maxfilter", | |
"-f", | |
str(path / "MEG/sample/sample_audvis-ave.fif"), | |
"-trans", | |
"default", | |
"-o", | |
"/tmp/maxfilter_ave.fif", | |
"-force", | |
"-v", | |
] | |
) | |
ev_maxfilter = mne.read_evokeds("/tmp/maxfilter_ave.fif", condition="Left Auditory") | |
ev_maxfilter.apply_baseline() | |
ev_maxfilter.comment = "maxfilter" | |
# Plot comparison | |
mne.viz.plot_evoked_topo([ev_orig, ev_moved, ev_maxfilter]) | |
fig_orig = mne.viz.plot_alignment( | |
ev_orig.info, | |
trans=path / "MEG/sample/sample_audvis_raw-trans.fif", | |
subject="sample", | |
subjects_dir=path / "subjects", | |
) | |
fig_orig.plotter.add_text("original") | |
fig_moved = mne.viz.plot_alignment( | |
ev_moved.info, | |
trans=path / "MEG/sample/sample_audvis_raw-trans.fif", | |
subject="sample", | |
subjects_dir=path / "subjects", | |
) | |
fig_moved.plotter.add_text("moved") | |
fig_maxfilter = mne.viz.plot_alignment( | |
ev_maxfilter.info, | |
trans=path / "MEG/sample/sample_audvis_raw-trans.fif", | |
subject="sample", | |
subjects_dir=path / "subjects", | |
) | |
fig_maxfilter.plotter.add_text("maxfilter") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from mne._fiff.meas_info import Info | |
from mne._fiff.pick import pick_types, pick_info | |
from mne.channels.interpolation import _do_interp_dots | |
from mne.epochs import BaseEpochs | |
from mne.evoked import Evoked | |
from mne.forward import _map_meg_or_eeg_channels | |
from mne.io import BaseRaw | |
from mne.utils.check import _validate_type | |
def move_head(inst, dest): | |
"""Virtually move head position to a new destination. | |
After this operation, the data will have the sensor layout and head position of the | |
destination data. | |
Parameters | |
---------- | |
inst : Raw | Epochs | Evoked | |
The data to virtually moved. Will be modified in-place. | |
dest : Raw | Epochs | Evoked | Info | |
Some data with the desired head position. | |
Notes | |
----- | |
As a side effect, all bad channels will be interpolated. | |
""" | |
_validate_type(dest, (BaseRaw, BaseEpochs, Evoked, Info), "dest") | |
if isinstance(dest, Info): | |
info_to = dest | |
else: | |
info_to = dest.info | |
if "dev_head_t" not in info_to: | |
raise ValueError( | |
"Could find an MEG->head transformation in the supplied `dest`." | |
) | |
picks_to = pick_types(info_to, meg=True, exclude=[]) | |
info_to = pick_info(info_to, picks_to) | |
_validate_type(inst, (BaseRaw, BaseEpochs, Evoked), "inst") | |
info_from = inst.info | |
if "dev_head_t" not in info_from: | |
raise ValueError( | |
"Could find an MEG->head transformation in the supplied `inst`." | |
) | |
picks_from = pick_types(info_from, exclude="bads", meg=True) | |
info_from = pick_info(info_from, picks_from) | |
mapping = _map_meg_or_eeg_channels( | |
info_from, info_to, mode="accurate", origin="auto" | |
) | |
_do_interp_dots(inst, mapping, picks_from, picks_to) | |
inst.info["dev_head_t"] = info_to["dev_head_t"] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment