Skip to content

Commit e3d3e4d

Browse files
committed
[brain2mesh] enable decoupling in pass 2 if pass 1 fails
1 parent 371110d commit e3d3e4d

File tree

3 files changed

+55
-15
lines changed

3 files changed

+55
-15
lines changed

iso2mesh/brain2mesh.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ def normalizer(x):
354354
continue
355355
if (loop == 1) and ("label_elem" not in locals()):
356356
if "bone_n" in locals() and "skin_n" in locals():
357+
print("decoupling bone and skin surfaces")
357358
bone_n, bone_f = surfboolean(
358359
bone_n[:, :3],
359360
bone_f[:, :3],
@@ -362,14 +363,17 @@ def normalizer(x):
362363
skin_f[:, :3],
363364
)
364365
if "bone_n" in locals() and "csf_n" in locals():
366+
print("decoupling csf and bone surfaces")
365367
csf_n, csf_f = surfboolean(
366368
csf_n[:, :3], csf_f[:, :3], "decouple", bone_n[:, :3], bone_f[:, :3]
367369
)
368370
if "pial_n" in locals() and "csf_n" in locals():
371+
print("decoupling pial and csf surfaces")
369372
pial_n, pial_f = surfboolean(
370373
pial_n[:, :3], pial_f[:, :3], "decouple", csf_n[:, :3], csf_f[:, :3]
371374
)
372375
if "pial_n" in locals() and "wm_n" in locals():
376+
print("decoupling wm and pial surfaces")
373377
wm_n, wm_f = surfboolean(
374378
wm_n[:, :3], wm_f[:, :3], "decouple", pial_n[:, :3], pial_f[:, :3]
375379
)
@@ -452,18 +456,27 @@ def normalizer(x):
452456
return brain_n, brain_el, brain_f
453457

454458
# Generates a coarse tetrahedral mesh of the combined tissues
459+
final_surf_n, final_surf_f = meshcheckrepair(final_surf_n, final_surf_f, "dup")
455460
try:
456461
final_n, final_e, _ = s2m(
457-
final_surf_n, final_surf_f, 1.0, maxvol, "tetgen1.5", None, None, "-A"
462+
final_surf_n,
463+
final_surf_f,
464+
1.0,
465+
maxvol,
466+
"tetgen1.5",
467+
None,
468+
None,
469+
"-YY -A",
458470
)
459-
except:
471+
except RuntimeError as e:
460472
print(
461-
"volumetric mesh generation failed, returning the intermediate surface model only"
473+
f"volumetric mesh generation failed with error: {e}, returning the intermediate surface model only"
462474
)
463-
brain_n = final_surf_n
464-
brain_f = final_surf_f
465-
brain_el = np.array([])
466-
return brain_n, brain_el, brain_f
475+
continue
476+
# brain_n = final_surf_n
477+
# brain_f = final_surf_f
478+
# brain_el = np.array([])
479+
# return brain_n, brain_el, brain_f
467480

468481
# Removes the elements that are part of the box, but not the brain/head
469482
if dotruncate == 1 or isinstance(dotruncate, str):
@@ -1761,7 +1774,7 @@ def brain1020(
17611774

17621775

17631776
def label2tpm(
1764-
vol: np.ndarray, names: Optional[Union[List[str], Dict[int, str]]] = None
1777+
vol: np.ndarray, names: Optional[Union[List[str], Dict[int, str]]] = None, **kwargs
17651778
) -> Dict[str, np.ndarray]:
17661779
"""
17671780
Converting a multi-label volume to binary tissue probabilistic maps (TPMs)
@@ -1824,6 +1837,17 @@ def label2tpm(
18241837
# MATLAB: seg.(nm) = uint8(vol == val(i))
18251838
seg[nm] = (vol == val[i]).astype(np.uint8)
18261839

1840+
if kwargs.get("sigma", 0) > 0:
1841+
from scipy.ndimage import gaussian_filter
1842+
1843+
segsum = np.zeros_like(seg[next(iter(seg))], dtype=np.float32)
1844+
for key in seg:
1845+
seg[key] = gaussian_filter(seg[key].astype(np.float32), sigma=1)
1846+
segsum += seg[key]
1847+
1848+
for key in seg:
1849+
np.divide(seg[key], segsum, out=seg[key], where=segsum != 0)
1850+
18271851
return seg
18281852

18291853

iso2mesh/core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@ def getintersecttri(tmppath):
983983
eid = []
984984
if status == 0:
985985
ids = re.findall(r" #([0-9]+) ", str_output)
986-
eid = [int(id[0]) for id in ids]
986+
eid = [int(id) for id in ids]
987987

988988
eid = np.unique(eid)
989989
return eid

iso2mesh/modify.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -491,8 +491,14 @@ def removeisolatednode(node, elem, face=None):
491491
Face list of the resulting mesh.
492492
"""
493493

494+
zeroindex = None
495+
494496
oid = np.arange(node.shape[0]) # Old node indices
495-
elem = elem - 1
497+
if not isinstance(elem, list):
498+
elem = elem - 1
499+
zeroindex = np.where(elem < 0)
500+
else:
501+
elem = [e - 1 for e in elem]
496502

497503
if not isinstance(elem, list):
498504
idx = np.setdiff1d(oid, elem.ravel(order="F")) # Indices of isolated nodes
@@ -511,12 +517,16 @@ def removeisolatednode(node, elem, face=None):
511517

512518
if not isinstance(elem, list):
513519
el = oid[elem] # Update element list with new indices
520+
if isinstance(zeroindex, tuple) and len(zeroindex[0]) > 0:
521+
el[zeroindex] = elem[zeroindex]
514522
else:
515523
el = [oid[e] for e in elem]
516524

517525
if face is not None:
526+
zeroindex = np.where(face == 0)
518527
if not isinstance(face, list):
519528
fa = oid[face - 1] # Update face list with new indices
529+
fa[zeroindex] = face[zeroindex] - 1
520530
else:
521531
fa = [oid[f - 1] for f in face]
522532
fa = fa + 1
@@ -866,7 +876,7 @@ def mergesurf(node, elem, *args):
866876
return newnode, newelem
867877

868878

869-
def surfboolean(node, elem, *varargin):
879+
def surfboolean(node, elem, *varargin, **kwargs):
870880
"""
871881
Perform boolean operations on triangular meshes and resolve intersecting elements.
872882
@@ -939,9 +949,12 @@ def surfboolean(node, elem, *varargin):
939949
if "node1" not in locals():
940950
node1 = node
941951
elem1 = elem
942-
newnode[:, 3] = 1
943-
newelem[:, 3] = 1
944-
opstr = " --decouple-inin 1 --shells 2"
952+
newnode = np.hstack((newnode, np.ones((newnode.shape[0], 1))))
953+
newelem = np.hstack((newelem, np.ones((newelem.shape[0], 1))))
954+
if kwargs.get("dir", "in"):
955+
opstr = " --decouple-inin 1 --shells 2"
956+
else:
957+
opstr = " --decouple-outout 1 --shells 2"
945958
saveoff(node1[:, :3], elem1[:, :3], mwpath("pre_decouple1.off"))
946959
if no.shape[1] != 3:
947960
opstr = f"-q --shells {no}"
@@ -1004,7 +1017,10 @@ def surfboolean(node, elem, *varargin):
10041017
[newnode, np.hstack([nnode, np.ones((nnode.shape[0], 1)) * 4])]
10051018
)
10061019
else:
1007-
newnode, newelem = readoff(mwpath("post_surfbool.off"))
1020+
if op == "decouple":
1021+
newnode, newelem = readoff(mwpath("pre_decouple1_fixed.off"))
1022+
else:
1023+
newnode, newelem = readoff(mwpath("post_surfbool.off"))
10081024

10091025
return newnode, newelem
10101026

0 commit comments

Comments
 (0)