Skip to content

Instantly share code, notes, and snippets.

@larsoner
Last active June 1, 2026 16:09
Show Gist options
  • Select an option

  • Save larsoner/5af20934521278927c8a3056df2bcb69 to your computer and use it in GitHub Desktop.

Select an option

Save larsoner/5af20934521278927c8a3056df2bcb69 to your computer and use it in GitHub Desktop.
fsaverage_1005 code
% Create fsaverage_1020
headshape = ft_read_headshape('~/mne_data/MNE-sample-data/subjects/fsaverage/bem/outer_skin.surf');
% [pos, tri, magic] = read_surf('~/mne_data/MNE-sample-data/subjects/fsaverage/surf/lh.seghead');
% headshape = [];
% headshape.pos = pos;
% headshape.tri = tri;
% ft_plot_mesh(headshape,'facecolor','skin');camlight;
assert(headshape.unit == "mm");
cfg = [];
cfg.method = '1020';
cfg.coordsys = 'rpa';
cfg.fiducial = [];
cfg.fiducial.lpa = [-80.61611938476562, -29.08875274658203, -41.310768127441406];
cfg.fiducial.nas = [1.467630386352539, 85.06715393066406, -34.83611297607422];
cfg.fiducial.rpa = [84.36284637451172, -28.502763748168945, -41.277435302734375];
cfg.fiducial.ini = [2.2790975635871296, -142.6586769521236, -47.75208979845047];
elec = ft_electrodeplacement(cfg, headshape);
assert(elec.unit == "mm");
out_path = '~/python/mne-python/mne/channels/data/montages/fsaverage_1005.tsv';
C = [elec.label, num2cell(elec.elecpos * 1e-3)];
C = [{"label", "x", "y", "z"}; C];
writecell(C, out_path, 'filetype', 'text', 'delimiter', '\t');
from pathlib import Path
import numpy as np
import pandas as pd
import mne
from mne.io.constants import FIFF
fids_fif = mne.coreg.get_mni_fiducials("fsaverage")
fids = dict(
lpa=fids_fif[0],
nasion=fids_fif[1],
rpa=fids_fif[2],
)
for key, val in fids.items():
assert val["ident"] == getattr(FIFF, f"FIFFV_POINT_{key.upper()}")
fids = {key: val["r"] for key, val in fids.items()}
mri_head_t = mne.transforms._get_trans(trans="fsaverage", fro="mri", to="head")[0]
fids_head = {key: mne.transforms.apply_trans(mri_head_t, fids[key]) for key in fids}
np.testing.assert_allclose(fids_head["lpa"][2:], 0, atol=1e-6)
assert -0.1 < fids_head["lpa"][0] < -0.01 # to the left
np.testing.assert_allclose(fids_head["nasion"][[0, 2]], 0, atol=1e-6)
assert 0.2 > fids_head["nasion"][1] > 0.01 # forward
np.testing.assert_allclose(fids_head["rpa"][2:], 0, atol=1e-6)
assert 0.1 > fids_head["rpa"][0] > 0.01 # to the right
ini_head = -fids_head["nasion"]
fids["ini"] = mne.transforms.apply_trans(
mne.transforms.invert_transform(mri_head_t), ini_head
)
with np.printoptions(suppress=True, floatmode="fixed"):
for key, val in fids.items():
print(f"cfg.fiducial.{key[:3]} = {list(map(float, 1000 * val))};")
# Run afterward: create 1020 variant
path = Path(mne.channels.__file__).parent / "data" / "montages" / "fsaverage_1005.tsv"
if path.is_file():
data = pd.read_csv(path, sep="\t")
# Get rid of "INI" and "Nz"
data = data[(data["label"] != "INI") & (data["label"] != "Nz")]
want_ch_names = mne.channels.make_standard_montage("colin27_1005").ch_names
# in our colin27 but not in spherical or fsaverage montages
bad_names = {'A1', 'T6', 'M2', 'T4', 'T3', 'M1', 'A2', 'T5'}
want_ch_names = [ch_name for ch_name in want_ch_names if ch_name not in bad_names]
spherical_ch_names = mne.channels.make_standard_montage("spherical_1005").ch_names
missing_from_spherical = {"NFp2", "NFp1", "NFp2h", "NFpz", "N2h", "NFp1h", "N2", "N1h", "N1"}
spherical_ch_names = [ch_name for ch_name in spherical_ch_names if ch_name not in missing_from_spherical]
assert set(spherical_ch_names) == set(want_ch_names)
want_fids = ["NAS", "LPA", "RPA"]
assert data["label"].isin(want_ch_names + list(want_fids)).all()
assert len(data) == len(want_ch_names) + len(want_fids)
for extra, count in (("1020", 24),):
new_names = mne.channels.make_standard_montage(f"spherical_{extra}").ch_names
mask = data["label"].isin(new_names + want_fids)
this_data = data[mask]
assert mask.sum() == count, mask.sum()
spherical_ch_names = mne.channels.make_standard_montage(f"spherical_{extra}").ch_names
assert set(spherical_ch_names) == set(new_names)
this_data.to_csv(
path.with_name(f"fsaverage_{extra}.tsv"), sep="\t", index=False
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment