question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ENH: Need tools for fixing mesh topology

See original GitHub issue

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())

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:14 (13 by maintainers)

github_iconTop GitHub Comments

2reactions
tillhabersetzercommented, Mar 1, 2022

Thank you very much for providing the code. I had the same problem and it worked for me too! I would really appreciate to see this function mne.surface.fix_topology(rr, tris) implemented in mne python

1reaction
larsonercommented, Feb 3, 2021

@yh-luo I’ll reopen until we get a variant of this code in MNE-Python. I’ve also needed to use it so that’s at least three people, and these topology questions come up a lot so I think it’s worth pursuing proper inclusion as a function.

@christian-oreilly since you did all the heavy lifting on this, would you be up for opening a EDIT: rough PR to add a mne.surface.fix_topology(rr, tris) function? Then I’m happy to hack away at the code to add tests, etc. to get it working, but the first commit will already get you code credit for the changes when we squash+merge, which I think is helpful since you did the heavy lifting!

I think in the end we probably also want a write_head_bem function since the code to do this currently requires poking around in private attributes. Then the fix could have maybe just been for you @yh-luo :

surf = mne.read_bem_surfaces(fname_head)[0]
surf['rr'], surf['tris'] = mne.surface.fix_topology(surf['rr'], surf['tris'])
mne.write_head_bem(fname_head, surf)
Read more comments on GitHub >

github_iconTop Results From Across the Web

Network Topology: An A-Z Guide & Top 5 ... - Tek-Tools
Here's a comprehensive guide on network topology and its types. We additionally cover the top 5 network topology software.
Read more >
MeshLab
It provides a set of tools for editing, cleaning, healing, inspecting, rendering, texturing and converting meshes. It offers features for processing raw data ......
Read more >
How to resolve Mesh Topological Errors - CAD Forum
I now have an error in the tree with the error "The mesh has ... All mesh you get straight from a scan...
Read more >
Chapter 10: Assigning the Mesh | CFD
Autodesk Simulation CFD provides tools to help you modify the default mesh to match your design and optimize performance and reliability.
Read more >
Mesh generation for CFD Simulations
Note that the mesh topology used to specify simulation parameters may be ... All pre-processing tools have to deal with geometrical issues ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found