mne-tools / mne-tools/mne-python

ENH: Need tools for fixing mesh topology

Open
#8,825 14 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

BUG
Dominant language
Python
Stars
3.5k
Forks
1.6k
Avg merge
1d 6h
Merged PRs (30d)
100

Description

Describe the bug

Someone else's high-resolution head was used for the selected subject.

lh.seghead in FreeView looks like:
subject-346-freeview

But the high-resolution head rendered in mne coreg gui looks like:
(Notice the differences of the top-left corner of the goggle, the ears, and the nose bridge.)
I can confirm that it is from other subject's head-dense.fif (lh.seghead) via FreeView.
subject-346-coreg

The high-resolution head also did not align to the head. No rotations were made, the head looks like:
subject-346-coreg-head


FreeView showed that lh.seghead and outer_skin.surf were aligned.
From the above images, it looks like someone else's dense head was used. The specified subject is subject-346, the error messages indicated that subject-102 dense head was used instead?

subject-102 is the first subject in the subject dropdown dialog.
It seems to me that mne coreg gui renders the first subject and then update with the selected subject. Maybe the bug result from that process?

mne coreg -s subject-346
Exception occurred in traits notification handler for object: <mne.gui._file_traits.SurfaceSource object at 0x7f3db86bcb30>, trait: file, old value: subjects//subject-102/bem/subject-102-head-dense.fif, new value: subjects//subject-346/bem/subject-346-head-dense.fif
Traceback (most recent call last):
  File "/home/ntubabylab/anaconda3/envs/mne/lib/python3.8/site-packages/traits/trait_notifiers.py", line 522, in _dispatch_change_event
    self.dispatch(handler, *args)
  File "/home/ntubabylab/anaconda3/envs/mne/lib/python3.8/site-packages/traits/trait_notifiers.py", line 484, in dispatch
    handler(*args)
  File "/home/ntubabylab/anaconda3/envs/mne/lib/python3.8/site-packages/mne/gui/_file_traits.py", line 175, in read_file
    bem = read_bem_surfaces(self.file, verbose=False)[0]
  File "<decorator-gen-98>", line 22, in read_bem_surfaces
  File "/home/ntubabylab/anaconda3/envs/mne/lib/python3.8/site-packages/mne/bem.py", line 1270, in read_bem_surfaces
    _check_complete_surface(this)
  File "/home/ntubabylab/anaconda3/envs/mne/lib/python3.8/site-packages/mne/bem.py", line 270, in _check_complete_surface
    raise RuntimeError(msg)
RuntimeError: Surface outer skin  has topological defects: 13 / 383510 vertices have fewer than three neighboring triangles [44385, 44387, 44389, 45198, 46031, 46033, 46861, 46862, 47708, 48546, 49428, 50338, 53081]
Steps to reproduce

I can't provide a MWE because it only happened to this subject.

Expected results

subject-346's lh.seghead

Actual results

subject-102(?)'s lh.seghead

Additional information

The above images in this post will be removed in the future.

Platform:      Linux-5.8.0-40-generic-x86_64-with-glibc2.10
Python:        3.8.5 (default, Sep  4 2020, 07:30:14)  [GCC 7.3.0]
Executable:    /home/ntubabylab/anaconda3/envs/mne/bin/python
CPU:           x86_64: 12 cores
Memory:        62.8 GB

mne:           0.22.0
numpy:         1.19.2 {blas=mkl_rt, lapack=mkl_rt}
scipy:         1.5.2
matplotlib:    3.3.2 {backend=Qt5Agg}

sklearn:       0.23.2
numba:         0.51.2
nibabel:       3.2.0
nilearn:       Not found
dipy:          Not found
cupy:          8.1.0
pandas:        1.1.3
mayavi:        4.7.2
pyvista:       0.26.1 {pyvistaqt=0.2.0, OpenGL 4.5.0 NVIDIA 450.102.04 via GeForce GTX 1660/PCIe/SSE2}
vtk:           9.0.1
PyQt5:         5.15.1

The high-resolution head was created with mne make_scalp_surfaces.

#!/usr/bin/env python
import os
import subprocess

from mne.parallel import parallel_func

from config import (N_JOBS, subjects_to_run, exclude_subjects, mri_dir,
                    subjects_dir)


def run_command(command, log_file):
    with open(log_file, "wb") as f:
        proc = subprocess.Popen(command,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT)
        for line in proc.stdout:
            f.write(line)
    if proc.wait() != 0:
        raise RuntimeError("command failed")


def process_subject_head(subject):
    subject_mri_dir = os.path.join(mri_dir, subject)
    run_command([
        "mne", "make_scalp_surfaces", "-s", subject, "-d", subjects_dir,
        "--force", "--overwrite", "--verbose"
    ], os.path.join(subject_mri_dir, f"{subject}_make_scalp_surfaces.txt"))
    print(f"Created high-resolution head surfaces for {subject}")

process_subject_head('subject-346')
Logs in mne make_scalp_surfaces
1. Creating a dense scalp tessellation with mkheadsurf...
Running subprocess: mkheadsurf -subjid subject-346 -srcvol T1.mgz
INFO: log file is /mnt/sdb1/MEG_Prosody/subjects/subject-346/scripts/mkheadsurf.log

--------------------------------

Tue 02 Feb 2021 10:22:20 AM CST

/mnt/sdb1/MEG_Prosody

mri_seghead --invol /mnt/sdb1/MEG_Prosody/subjects/subject-346/mri/T1.mgz --outvol /mnt/sdb1/MEG_Prosody/subjects/subject-346/mri/seghead.mgz --fill 1 --thresh1 20 --thresh2 20 --nhitsmin 2

--------------------------------

input volume:  /mnt/sdb1/MEG_Prosody/subjects/subject-346/mri/T1.mgz

output volume: /mnt/sdb1/MEG_Prosody/subjects/subject-346/mri/seghead.mgz

threshold1:    20

threshold2:    20

nhitsmin:      2

fill value:    1

Loading input volume

Filling Columns

Filling Rows

Filling Slices

Merging and Inverting

Growing

Counting

N Head Voxels = 2763508

N Back Voxels = 14013708

Avg. Back Intensity = 1.099117

Max. Back Intensity = 235.000000

Writing output

Done

--------------------------------

Tue 02 Feb 2021 10:22:22 AM CST

/mnt/sdb1/MEG_Prosody

mri_tessellate /mnt/sdb1/MEG_Prosody/subjects/subject-346/mri/seghead.mgz 1 /mnt/sdb1/MEG_Prosody/subjects/subject-346/surf/lh.seghead

--------------------------------

7.1.1

  7.1.1

slice 40: 4930 vertices, 5067 faces

slice 50: 13321 vertices, 13533 faces

slice 60: 23339 vertices, 23642 faces

slice 70: 32759 vertices, 33068 faces

slice 80: 41073 vertices, 41395 faces

slice 90: 49432 vertices, 49789 faces

slice 100: 58965 vertices, 59458 faces

slice 110: 68826 vertices, 69328 faces

slice 120: 77977 vertices, 78498 faces

slice 130: 86895 vertices, 87425 faces

slice 140: 95446 vertices, 96008 faces

slice 150: 104054 vertices, 104633 faces

slice 160: 112518 vertices, 113104 faces

slice 170: 122539 vertices, 123275 faces

slice 180: 135046 vertices, 136220 faces

slice 190: 149553 vertices, 150907 faces

slice 200: 164959 vertices, 166490 faces

slice 210: 181548 vertices, 183291 faces

slice 220: 189480 vertices, 191117 faces

slice 230: 190186 vertices, 191755 faces

slice 240: 190186 vertices, 191755 faces

slice 250: 190186 vertices, 191755 faces

using the conformed surface RAS to save vertex points...

writing /mnt/sdb1/MEG_Prosody/subjects/subject-346/surf/lh.seghead

using vox2ras matrix:

-1.00000   0.00000   0.00000   128.00000;

 0.00000   0.00000   1.00000  -128.00000;

 0.00000  -1.00000   0.00000   128.00000;

 0.00000   0.00000   0.00000   1.00000;

--------------------------------

Tue 02 Feb 2021 10:22:24 AM CST

/mnt/sdb1/MEG_Prosody

mris_smooth -n 10 -b area.seghead -c curv.seghead /mnt/sdb1/MEG_Prosody/subjects/subject-346/surf/lh.seghead /mnt/sdb1/MEG_Prosody/subjects/subject-346/surf/lh.seghead

--------------------------------

smoothing for 10 iterations

smoothing surface tessellation for 10 iterations...

smoothing complete - recomputing first and second fundamental forms...

writing smoothed curvature to /mnt/sdb1/MEG_Prosody/subjects/subject-346/surf/lh.curv.seghead

writing smoothed area to /mnt/sdb1/MEG_Prosody/subjects/subject-346/surf/lh.area.seghead

--------------------------------

Tue 02 Feb 2021 10:22:27 AM CST

/mnt/sdb1/MEG_Prosody

mris_inflate -n 10 -sulc sulc.seghead /mnt/sdb1/MEG_Prosody/subjects/subject-346/surf/lh.seghead /mnt/sdb1/MEG_Prosody/subjects/subject-346/surf/lh.seghead.inflated

--------------------------------

niterations = 10

sulc name = sulc.seghead

Reading /mnt/sdb1/MEG_Prosody/subjects/subject-346/surf/lh.seghead

avg radius = 87.9 mm, total surface area = 117737 mm^2


step 000: RMS=0.148 (target=0.015)   
step 005: RMS=0.114 (target=0.015)   
step 010: RMS=0.103 (target=0.015)   
step 015: RMS=0.097 (target=0.015)   
step 020: RMS=0.092 (target=0.015)   
step 025: RMS=0.088 (target=0.015)   
step 030: RMS=0.085 (target=0.015)   
step 035: RMS=0.082 (target=0.015)   
step 040: RMS=0.081 (target=0.015)   
step 045: RMS=0.080 (target=0.015)   
step 050: RMS=0.079 (target=0.015)   
step 055: RMS=0.080 (target=0.015)   
step 060: RMS=0.080 (target=0.015)   writing inflated surface to /mnt/sdb1/MEG_Prosody/subjects/subject-346/surf/lh.seghead.inflated

writing sulcal depths to /mnt/sdb1/MEG_Prosody/subjects/subject-346/surf/lh.sulc.seghead



inflation complete.

inflation took 0.3 minutes

mris_inflate utimesec    16.246170

mris_inflate stimesec    0.531678

mris_inflate ru_maxrss   299472

mris_inflate ru_ixrss    0

mris_inflate ru_idrss    0

mris_inflate ru_isrss    0

mris_inflate ru_minflt   743476

mris_inflate ru_majflt   0

mris_inflate ru_nswap    0

mris_inflate ru_inblock  0

mris_inflate ru_oublock  10448

mris_inflate ru_msgsnd   0

mris_inflate ru_msgrcv   0

mris_inflate ru_nsignals 0

mris_inflate ru_nvcsw    0

mris_inflate ru_nivcsw   1765

Started at: Tue 02 Feb 2021 10:22:20 AM CST

Ended   at: Tue 02 Feb 2021 10:22:43 AM CST

mkheadsurf done

2. Creating /mnt/sdb1/MEG_Prosody/subjects/subject-346/bem/subject-346-head-dense.fif ...
outer skin  CM is  10.24   5.95 -47.79 mm
Surfaces passed the basic topology checks.
3. Creating medium tessellation...
3.1 Decimating the dense tessellation...
3.2 Creating /mnt/sdb1/MEG_Prosody/subjects/subject-346/bem/subject-346-head-medium.fif
outer skin  CM is  18.27  27.64 -63.59 mm
Surfaces passed the basic topology checks.
4. Creating sparse tessellation...
4.1 Decimating the dense tessellation...
4.2 Creating /mnt/sdb1/MEG_Prosody/subjects/subject-346/bem/subject-346-head-sparse.fif
outer skin  CM is  17.12  24.57 -62.60 mm
Surfaces passed the basic topology checks.
/home/ntubabylab/anaconda3/envs/mne/bin/mne:8: RuntimeWarning: Surface outer skin  has topological defects: 13 / 383510 vertices have fewer than three neighboring triangles [44385, 44387, 44389, 45198, 46031, 46033, 46861, 46862, 47708, 48546, 49428, 50338, 53081]

Consider using --force as an additional input parameter.
  sys.exit(main())
/home/ntubabylab/anaconda3/envs/mne/bin/mne:8: RuntimeWarning: Surface outer skin  is not complete (sum of solid angles yielded 0.999793, should be 1.)
  sys.exit(main())
/home/ntubabylab/anaconda3/envs/mne/bin/mne:8: RuntimeWarning: Surface outer skin  has topological defects: 53 / 30000 vertices have fewer than three neighboring triangles [1659, 1663, 1690, 1732, 1734, 1767, 1812, 1813, 1815, 1849, 1850, 1887, 2012, 2127, 2212, 2272, 2507, 3476, 5047, 5435, 6169, 6296, 6297, 6532, 6540, 6587, 6976, 7295, 7855, 8106, 8199, 8528, 8533, 8538, 8727, 8795, 8953, 9039, 10498, 10546, 11537, 11560, 11755, 12293, 12587, 13594, 13779, 14204, 14207, 14300, 14313, 14463, 14532]

Consider using --force as an additional input parameter.
  sys.exit(main())
/home/ntubabylab/anaconda3/envs/mne/bin/mne:8: RuntimeWarning: Surface outer skin  is not complete (sum of solid angles yielded 0.999567, should be 1.)
  sys.exit(main())
/home/ntubabylab/anaconda3/envs/mne/bin/mne:8: RuntimeWarning: Surface outer skin  has topological defects: 17 / 2500 vertices have fewer than three neighboring triangles [176, 180, 184, 189, 271, 272, 677, 775, 991, 1060, 1061, 1107, 1128, 1160, 1161, 1162, 1190]

Consider using --force as an additional input parameter.
  sys.exit(main())
/home/ntubabylab/anaconda3/envs/mne/bin/mne:8: RuntimeWarning: Surface outer skin  is not complete (sum of solid angles yielded 1.00046, should be 1.)
  sys.exit(main())

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by examining the mne coreg subject-selection path and the traceback locations mne/gui/_file_traits.py and mne/bem.py, then review how mne make_scalp_surfaces creates and validates dense surfaces. Reproduce with subject-346 if the data are available, since the report has no MWE. Done means the selected subject's surface is rendered and topology defects are handled or reported appropriately.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
computer-graphics
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.