Skip to content

Commit abe1acb

Browse files
author
Jordan DeKraker
committed
moved conncomp from laplace_beltrami.py to gen_isosurface.py
1 parent 272a46d commit abe1acb

File tree

2 files changed

+48
-46
lines changed

2 files changed

+48
-46
lines changed

hippunfold/workflow/scripts/gen_isosurface.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import nibabel as nib
33
import numpy as np
44
from copy import deepcopy
5+
import networkx as nx
56

67

78
def write_surface_to_gifti(points, faces, out_surf_gii):
@@ -21,6 +22,48 @@ def write_surface_to_gifti(points, faces, out_surf_gii):
2122
gifti.to_filename(out_surf_gii)
2223

2324

25+
def largest_connected_component(vertices: np.ndarray, faces: np.ndarray):
26+
"""
27+
Returns the vertices, faces, and original indices of the largest connected component of a 3D surface mesh.
28+
29+
Parameters:
30+
vertices (np.ndarray): Array of vertex coordinates (N x 3).
31+
faces (np.ndarray): Array of face indices (M x 3).
32+
33+
Returns:
34+
tuple: (new_vertices, new_faces, largest_component), where new_vertices are the vertex coordinates of the largest component,
35+
new_faces are the face indices adjusted to the new vertex order, and largest_component contains the indices of the original vertices.
36+
"""
37+
# Build adjacency graph from face connectivity
38+
G = nx.Graph()
39+
for face in faces:
40+
G.add_edges_from(
41+
[(face[i], face[j]) for i in range(3) for j in range(i + 1, 3)]
42+
)
43+
44+
# Find connected components
45+
components = list(nx.connected_components(G))
46+
47+
# Select the largest connected component
48+
largest_component = max(components, key=len)
49+
largest_component = np.array(list(largest_component))
50+
51+
# Create a mapping from old vertex indices to new ones
52+
index_map = {old_idx: new_idx for new_idx, old_idx in enumerate(largest_component)}
53+
54+
# Filter the vertices and faces
55+
new_vertices = vertices[largest_component]
56+
new_faces = np.array(
57+
[
58+
[index_map[v] for v in face]
59+
for face in faces
60+
if all(v in index_map for v in face)
61+
]
62+
)
63+
64+
return new_vertices, new_faces, largest_component
65+
66+
2467
def remove_nan_vertices(vertices, faces):
2568
"""
2669
Removes vertices containing NaNs and updates faces accordingly.
@@ -186,5 +229,9 @@ def compute_geodesic_distances(vertices, faces, source_indices):
186229
points, faces = remove_nan_vertices(points, faces)
187230

188231

232+
# apply largest connected component
233+
points, faces, i_concomp = largest_connected_component(vertices_orig, faces)
234+
235+
189236
# write to gifti
190237
write_surface_to_gifti(points, faces, snakemake.output.surf_gii)

hippunfold/workflow/scripts/laplace_beltrami.py

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,49 +3,6 @@
33
import nibabel as nib
44
from scipy.interpolate import NearestNDInterpolator
55
from collections import defaultdict
6-
import networkx as nx
7-
8-
9-
def largest_connected_component(vertices: np.ndarray, faces: np.ndarray):
10-
"""
11-
Returns the vertices, faces, and original indices of the largest connected component of a 3D surface mesh.
12-
13-
Parameters:
14-
vertices (np.ndarray): Array of vertex coordinates (N x 3).
15-
faces (np.ndarray): Array of face indices (M x 3).
16-
17-
Returns:
18-
tuple: (new_vertices, new_faces, largest_component), where new_vertices are the vertex coordinates of the largest component,
19-
new_faces are the face indices adjusted to the new vertex order, and largest_component contains the indices of the original vertices.
20-
"""
21-
# Build adjacency graph from face connectivity
22-
G = nx.Graph()
23-
for face in faces:
24-
G.add_edges_from(
25-
[(face[i], face[j]) for i in range(3) for j in range(i + 1, 3)]
26-
)
27-
28-
# Find connected components
29-
components = list(nx.connected_components(G))
30-
31-
# Select the largest connected component
32-
largest_component = max(components, key=len)
33-
largest_component = np.array(list(largest_component))
34-
35-
# Create a mapping from old vertex indices to new ones
36-
index_map = {old_idx: new_idx for new_idx, old_idx in enumerate(largest_component)}
37-
38-
# Filter the vertices and faces
39-
new_vertices = vertices[largest_component]
40-
new_faces = np.array(
41-
[
42-
[index_map[v] for v in face]
43-
for face in faces
44-
if all(v in index_map for v in face)
45-
]
46-
)
47-
48-
return new_vertices, new_faces, largest_component
496

507

518
def find_boundary_vertices(vertices, faces):
@@ -154,11 +111,9 @@ def solve_laplace_beltrami_open_mesh(vertices, faces, boundary_conditions=None):
154111

155112

156113
surf = nib.load(snakemake.input.surf_gii)
157-
vertices_orig = surf.agg_data("NIFTI_INTENT_POINTSET")
114+
vertices = surf.agg_data("NIFTI_INTENT_POINTSET")
158115
faces = surf.agg_data("NIFTI_INTENT_TRIANGLE")
159116

160-
vertices, faces, i_concomp = largest_connected_component(vertices_orig, faces)
161-
162117

163118
# get source/sink vertices by nearest neighbour (only of edge vertices)
164119
boundary_vertices = np.array(find_boundary_vertices(vertices, faces))

0 commit comments

Comments
 (0)