Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mne/_freesurfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -838,10 +838,10 @@ def _get_head_surface(surf, subject, subjects_dir, bem=None, verbose=None):
]
else:
try_fnames = [
op.join(subject_dir, "bem", f"{subject}-head.fif"),
op.join(subject_dir, "bem", "outer_skin.surf"),
op.join(subject_dir, "bem", "flash", "outer_skin.surf"),
op.join(subject_dir, "bem", f"{subject}-head-sparse.fif"),
op.join(subject_dir, "bem", f"{subject}-head.fif"),
]
for fname in try_fnames:
if op.exists(fname):
Expand Down
2 changes: 1 addition & 1 deletion mne/coreg.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@
fid_fname_general = os.path.join(bem_dirname, "{head}-fiducials.fif")
src_fname = os.path.join(bem_dirname, "{subject}-{spacing}-src.fif")
_head_fnames = (
head_bem_fname,
os.path.join(bem_dirname, "outer_skin.surf"),
head_sparse_fname,
head_bem_fname,
)
_high_res_head_fnames = (
os.path.join(bem_dirname, "{subject}-head-dense.fif"),
Expand Down
20 changes: 20 additions & 0 deletions mne/datasets/_fsaverage/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# License: BSD-3-Clause
# Copyright the MNE-Python contributors.

import shutil
from pathlib import Path

from ...utils import get_subjects_dir, set_config, verbose_static
Expand Down Expand Up @@ -50,6 +51,15 @@ def fetch_fsaverage(subjects_dir=None, *, verbose=None):
the zip file is downloaded and files are updated. No files will
be overwritten.

The head surface ``bem/fsaverage-head.fif`` is the smooth head surface
packaged with MNE-Python (the one :func:`mne.create_default_subject`
installs) rather than the watershed outer skin surface from the zip file.
To update an existing copy of fsaverage, delete the file and call this
function again.

.. versionchanged:: 1.13
The packaged head surface is used for ``bem/fsaverage-head.fif``.

.. versionadded:: 0.18
"""
# Code used to create the BEM (other files taken from MNE-sample-data):
Expand All @@ -74,6 +84,10 @@ def fetch_fsaverage(subjects_dir=None, *, verbose=None):
subjects_dir = subjects_dir.expanduser().absolute()
fs_dir = subjects_dir / "fsaverage"
fs_dir.mkdir(parents=True, exist_ok=True)
# Both zip files contain the watershed outer skin as bem/fsaverage-head.fif;
# replace it with the packaged head surface unless the file already existed
head_fname = fs_dir / "bem" / "fsaverage-head.fif"
replace_head = not head_fname.is_file()
_manifest_check_download(
manifest_path=FSAVERAGE_MANIFEST_PATH / "root.txt",
destination=subjects_dir,
Expand All @@ -86,6 +100,12 @@ def fetch_fsaverage(subjects_dir=None, *, verbose=None):
url="https://github.com/mne-tools/mne-data/releases/download/fsaverage-1.0/fsaverage-bem.zip",
hash_="b31509cdcf7908af6a83dc5ee8f49fb1",
)
if replace_head:
head_fname.parent.mkdir(exist_ok=True)
shutil.copyfile(
Path(__file__).parents[2] / "data" / "fsaverage" / "fsaverage-head.fif",
head_fname,
)
return fs_dir


Expand Down
18 changes: 15 additions & 3 deletions mne/datasets/tests/test_datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,24 @@ def test_datasets_basic(tmp_path, monkeypatch):
with pytest.raises(FileNotFoundError, match="as specified by MNE_DAT"):
testing.data_path(download=False)

def noop(*args, **kwargs):
return
def fake_download(manifest_path, destination, url, hash_):
for name in manifest_path.read_text().split():
if not (destination / name).is_file(): # like the real downloader
(destination / name).parent.mkdir(parents=True, exist_ok=True)
(destination / name).write_bytes(b"")

monkeypatch.setattr(mne.datasets._fsaverage.base, "_manifest_check_download", noop)
monkeypatch.setattr(
mne.datasets._fsaverage.base, "_manifest_check_download", fake_download
)
sd_2 = datasets.fetch_fsaverage()
assert sd / "fsaverage" == sd_2
# the packaged head surface is installed, but an existing one is left alone
head = sd_2 / "bem" / "fsaverage-head.fif"
packaged = Path(mne.__file__).parent / "data" / "fsaverage" / "fsaverage-head.fif"
assert head.read_bytes() == packaged.read_bytes()
head.write_bytes(b"")
datasets.fetch_fsaverage()
assert head.read_bytes() == b""


def test_erp_core_fetch_file(tmp_path, monkeypatch):
Expand Down
3 changes: 3 additions & 0 deletions mne/tests/test_coreg.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from mne.channels import DigMontage
from mne.coreg import (
Coregistration,
_find_head_bem,
_is_mri_subject,
coregister_fiducials,
create_default_subject,
Expand Down Expand Up @@ -443,6 +444,8 @@ def test_coregistration(scale_mode, ref_scale, grow_hair, fiducials, fid_match):
coreg = Coregistration(
info, subject=subject, subjects_dir=subjects_dir, fiducials=fiducials
)
# the subject's own head file is preferred over the watershed outer_skin.surf
assert _find_head_bem(subject, subjects_dir).endswith("sample-head.fif")
assert np.allclose(coreg._last_parameters, coreg._parameters)
assert len(coreg.fiducials.dig) == 3
for dig_point in coreg.fiducials.dig:
Expand Down
2 changes: 2 additions & 0 deletions mne/viz/tests/test_3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,8 @@ def test_plot_alignment_eeg(renderer, evoked):
assert "ecog: 1" in log
assert "seeg: 1" in log
assert "eeg: 10" in log
# the subject's own head file is preferred over the watershed outer_skin.surf
assert "Using sample-head.fif for head surface." in log
# check number of actors
# 4 surfs (both hemis, skin, skull), 1 ECoG, 1 sEEG,
# 5 orig EEG + 1 projected EEG
Expand Down
Loading