The mesh¶
The mesh every inference reads: DcelData, a multimaterial triangle mesh as a doubly connected edge list.
A DcelData holds the vertices, the triangles with the two materials each separates, and the
half-edge structure the geometry (foambryo.geometry, foambryo.curvature) walks. Build one with
foambryo.dcel_mesh_from_segmentation_mask, foambryo.dcel_mesh_from_file or
foambryo.dcel_mesh_from_multimaterial_mesh.
Sacha Ichbiah, 2021. Matthieu Perez, 2024.
Vertex
dataclass
¶
Vertex(x: float = 0.0, y: float = 0.0, z: float = 0.0, key: int = 0)
Vertex in 2D.
HalfEdge
dataclass
¶
HalfEdge(origin: Vertex = None, destination: Vertex = None, material_1: int = 0, material_2: int = 0, twin: HalfEdge = None, incident_face: Face = None, prev_he: HalfEdge = None, next_he: HalfEdge = None, attached: dict = dict(), key: int = 0)
Half-Edge of a DCEL graph.
return_vector ¶
return_vector() -> NDArray[np.float64]
Return a normalized vector from origin to destination.
Face
dataclass
¶
Face(attached: dict = dict(), outer_component: HalfEdge = None, _closed: bool = True, material_1: int = 0, material_2: int = 0, key: int = 0)
Face of a DCEL graph.
get_materials ¶
get_materials() -> None
Set the materials of the face from its outer component HalfEdge.
DcelData ¶
DcelData(points: NDArray[float64], triangles: NDArray[int64], labels: NDArray[int64], *, crop_faces: NDArray[bool_] | NDArray[integer] | None = None, source_spacing: tuple[float, float, float] | None = None)
A multimaterial triangle mesh as a doubly connected edge list (DCEL): faces, half-edges and vertices.
Conventions: label 0 is the exterior medium; every triangle's labels are stored as
material_1 < material_2, its winding flipped to match (_normalize_label_order), so an
interface is keyed (label_1, label_2) with label_1 < label_2; coordinates are in the
mesh's own length unit (voxels, or the unit of the spacing the mesh was reconstructed with).
Attributes:
| Name | Type | Description |
|---|---|---|
v |
NDArray[float64]
|
vertex positions, |
f |
NDArray[int64]
|
triangles and labels, |
materials |
NDArray[int64]
|
the labels present, sorted (0 first when the medium is). |
n_materials |
int
|
their number. |
crop_faces |
NDArray[bool_]
|
|
source_spacing |
tuple[float, float, float] | None
|
the source mask's voxel size, if recorded. |
vertices |
list[Vertex]
|
the DCEL's vertex records, aligned with |
half_edges |
list[HalfEdge]
|
the DCEL's half-edge records. |
faces |
list[Face]
|
the DCEL's face records, aligned with the rows of |
Take a multimaterial mesh as input.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
NDArray[float64]
|
Mesh vertex positions, shape |
required |
triangles
|
NDArray[int64]
|
Triangles as vertex indices, shape |
required |
labels
|
NDArray[int64]
|
The two materials each triangle separates, shape
|
required |
crop_faces
|
NDArray | None
|
which triangles are crop faces: faces on
the boundary of the imaged volume, where the tissue was cut by the crop rather
than bounded by the medium. A boolean mask of shape |
None
|
source_spacing
|
tuple[float, float, float] | None
|
the voxel size of the
mask the mesh was made from, along the mask's axes 0, 1, 2, when the mesh records
it: delaunay-watershed-3d's |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If any triangle carries the same material on both sides, or if
|
source_anisotropy
property
¶
source_anisotropy: float | None
Longest over shortest source voxel size (1.0 for cubic voxels); None when the spacing is unknown.
has_crop_faces
property
¶
has_crop_faces: bool
Whether any triangle is a crop face. When False, no inference method applies a crop-face rule.
crop_vertices
property
¶
crop_vertices: NDArray[int64]
Sorted keys of the vertices that lie on a crop face (empty without crop faces).
cut_cells
property
¶
cut_cells: tuple[int, ...]
The cells the crop cuts: a cell with a crop face or with a vertex on one, sorted.
Their volume and part of their surface lie outside the imaged volume, so a pressure
inferred for them is not a measurement: the pressure methods report it as nan.
crop_interfaces
property
¶
crop_interfaces: tuple[tuple[int, int], ...]
Interfaces (0, c) all of whose triangles are crop faces, sorted.
They are the crop itself, not a contact between a cell and the medium, so they carry no
tension: no inference method gives them an unknown's value, and the tension maps leave
them out. An interface (0, c) with crop faces and real contact with the medium keeps
its tension, which then describes the real contact only.
compute_scattered_arrays ¶
compute_scattered_arrays(coeff: float) -> None
Modify the mesh to obtain the alternative "scattered" mesh, with each region separated from others.
coeff = 0 means no displacement.
compute_areas_faces ¶
compute_areas_faces() -> None
Compute the area of every triangle using Heron's formula.
compute_vertex_normals ¶
compute_vertex_normals() -> NDArray[np.float64]
Compute normals at every vertex, from the mesh's own points and triangles.
Returns:
| Type | Description |
|---|---|
NDArray[float64]
|
NDArray[np.float64]: normal for every vertex |
compute_verts_faces_interfaces ¶
compute_verts_faces_interfaces() -> tuple[dict[tuple[int, int], NDArray[np.float64]], dict[tuple[int, int], NDArray[np.int64]]]
Returns two dicts that maps (label1, label2) of an interface to array of vertices & triangles.
compute_networkx_graph ¶
compute_networkx_graph() -> networkx.Graph
Compute a graph with values extracted from the mesh. Nodes = regions, edges = interfaces.
find_trijunctional_edges ¶
find_trijunctional_edges() -> NDArray[np.int64]
Return an array of edges on trijunction.
Each edge is [index of point 1, index of point 2].
compute_centroids_cells ¶
compute_centroids_cells() -> None
Compute internally an array of each region's centroid.
mark_trijunctional_vertices ¶
mark_trijunctional_vertices(return_list: bool = False) -> NDArray[np.int64]
Check for vertices on trijunction and mark them as such. Can return the keys of those vertices.
compute_length_trijunctions ¶
compute_length_trijunctions(prints: bool = False) -> dict[tuple[int, int, int], float]
Compute the length of trijunctions, identified by their 3 adjacent regions.
compute_areas_interfaces ¶
compute_areas_interfaces() -> dict[tuple[int, int], float]
Compute area of every interface (label1, label2) in mesh.
compute_area_derivatives_slow ¶
compute_area_derivatives_slow() -> dict[tuple[int, int], NDArray[np.float64]]
Compute dict that maps interface (label1, label2) to array of change of area per point.
Alias of :meth:compute_area_derivatives, kept for backward compatibility. Both return the
closed-form (float64) derivative — the _slow name predates that being the default.
compute_area_derivatives ¶
compute_area_derivatives() -> dict[tuple[int, int], NDArray[np.float64]]
Compute dict that maps interface (label1, label2) to array of change of area per point.
Closed-form float64 derivative (the current default; the former float32 autodiff path
lives in :mod:foambryo._autodiff_derivatives as a gradient check). The variational
solve itself uses the sparse operator :func:foambryo.geometry.compute_area_derivative_sparse;
this dict form is kept for callers that want a per-interface field (e.g. viewing).
compute_volumes_cells ¶
compute_volumes_cells() -> dict[int, float]
Compute map cell number -> volume.
compute_volume_derivatives_slow ¶
compute_volume_derivatives_slow() -> dict[int, NDArray[np.float64]]
Compute map cell number -> derivative of volume wrt to each point.
Alias of :meth:compute_volume_derivatives, kept for backward compatibility (see
:meth:compute_area_derivatives_slow).
compute_volume_derivatives ¶
compute_volume_derivatives() -> dict[int, NDArray[np.float64]]
Compute map cell number -> derivative of volume wrt to each point.
Closed-form float64 derivative (the current default; see :meth:compute_area_derivatives).
compute_length_derivatives ¶
compute_length_derivatives() -> dict[tuple[int, int, int], NDArray[np.float64]]
Compute map trijunction (id reg 1, id reg 2, id reg 3) -> change of length wrt points.
Closed-form float64 derivative (the current default; the former autodiff path lives in
:mod:foambryo._autodiff_derivatives).
compute_angles_junctions ¶
compute_angles_junctions(unique: bool = True, *, reading: str = CHORD_READING) -> dict[tuple[int, int, int], float]
Compute a map trijunction (id reg 1, id reg 2, id reg 3) to mean angle in radians.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
unique
|
bool
|
Count each geometric edge once. Defaults to True. |
True
|
reading
|
str
|
angle reading, one of
|
CHORD_READING
|
Returns:
| Type | Description |
|---|---|
dict[tuple[int, int, int], float]
|
dict[tuple[int, int, int], float]: mean angle in radians, by wedge key. |
compute_angles_tri ¶
compute_angles_tri(unique: bool = True, *, reading: str = CHORD_READING) -> tuple[dict[tuple[int, int, int], float], dict[tuple[int, int, int], float], dict[tuple[int, int, int], float]]
Compute three maps trijunction (id reg 1, id reg 2, id reg 3) to mean angle, mean angle (deg), length.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
unique
|
bool
|
Count each geometric edge once. Defaults to True. |
True
|
reading
|
str
|
angle reading, one of
|
CHORD_READING
|
Returns:
| Type | Description |
|---|---|
tuple[dict[tuple[int, int, int], float], dict[tuple[int, int, int], float], dict[tuple[int, int, int], float]]
|
tuple[dict, dict, dict]: mean angle (rad), mean angle (deg) and accumulated length. |
compute_angles_tri_with_report ¶
compute_angles_tri_with_report(unique: bool = True, *, reading: str = CHORD_READING) -> tuple[dict[tuple[int, int, int], float], dict[tuple[int, int, int], float], dict[tuple[int, int, int], float], AngleReadingReport]
:meth:compute_angles_tri, plus the reading's coverage report.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
unique
|
bool
|
Count each geometric edge once. Defaults to True. |
True
|
reading
|
str
|
angle reading, one of
|
CHORD_READING
|
Returns:
| Type | Description |
|---|---|
tuple[dict[tuple[int, int, int], float], dict[tuple[int, int, int], float], dict[tuple[int, int, int], float], AngleReadingReport]
|
tuple[dict, dict, dict, AngleReadingReport]: mean angle (rad), mean angle (deg), accumulated length, and which trijunction faces the reading actually covered. |
compute_curvatures_interfaces ¶
compute_curvatures_interfaces(weighted: bool = True) -> dict[tuple[int, int], float]
Compute the mean curvature on the interfaces of the mesh.
load ¶
load(filename: str | Path) -> None
Unpickle list of vertices, half edges and faces (might be dangerous).
separate_faces_dict ¶
separate_faces_dict(triangles_and_labels: NDArray[int64]) -> dict[int, NDArray[np.int64]]
Construct a dictionnary that maps a region id to the array of triangles forming this region.
renormalize_verts ¶
renormalize_verts(points: NDArray[float64], triangles: NDArray[int64]) -> tuple[NDArray[np.float64], NDArray[np.int64]]
Take a mesh made from points and triangles and remove points not indexed in triangles. Re-index triangles.
Return the filtered points and reindexed triangles.
separate_faces_dict_keep_idx ¶
separate_faces_dict_keep_idx(triangles_and_labels: NDArray[int64]) -> tuple[dict[int, NDArray[np.int64]], dict[int, NDArray[np.int64]]]
Construct two dictionnaries to map region -> triangles.
One that maps a region id to the array of triangles forming this region. The other maps a region id to the indices of triangles in the triangles array.
compute_scattered_arrays ¶
compute_scattered_arrays(mesh: DcelData, coeff: float) -> None
Modify the mesh to obtain the alternative "scattered" mesh, with each region separated from others.
coeff = 0 means no displacement.
compute_normal_faces ¶
compute_normal_faces(points: NDArray[float64], triangles: NDArray[int64]) -> NDArray[np.float64]
Compute normals on every triangle.
build_lists ¶
build_lists(points: NDArray[float64], triangles_and_labels: NDArray[int64]) -> tuple[list[Vertex], list[HalfEdge], list[Face]]
Build lists of DCEL objects from mesh.
make_vertices_list ¶
make_vertices_list(points: NDArray[float64]) -> list[Vertex]
Build the list of Vertex from the mesh's points.
mark_trijunctional_vertices ¶
mark_trijunctional_vertices(mesh: DcelData, return_list: bool = False) -> NDArray[np.int64]
Check for vertices on trijunction and mark them as such. Can return the keys of those vertices.
find_trijunctional_edges ¶
find_trijunctional_edges(mesh: DcelData) -> NDArray[np.int64]
Return an array of edges on trijunction.
Each edge is [index of point 1, index of point 2].
compute_length_halfedges ¶
compute_length_halfedges(mesh: DcelData) -> None
Compute all lengths of HalfEdges.
compute_faces_areas ¶
compute_faces_areas(points: NDArray[float64], triangles: NDArray[int64]) -> NDArray[np.float64]
Compute the area of every triangle using Heron's formula.
compute_vertex_normals ¶
compute_vertex_normals(points: NDArray[float64], triangles: NDArray[int64]) -> NDArray[np.float64]
Compute normals at every vertex.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
NDArray[float64]
|
points of the mesh |
required |
triangles
|
NDArray[int64]
|
triangles of the mesh |
required |
Returns:
| Type | Description |
|---|---|
NDArray[float64]
|
NDArray[np.float64]: normal for every vertex |
remove_unused_vertices ¶
remove_unused_vertices(points: NDArray[float64], triangles_and_labels: NDArray[int64]) -> tuple[NDArray[np.float64], NDArray[np.int64]]
From points and triangles with labels ; remove points not indexed in triangles. Re-index triangles and labels.
Return the filtered points and reindexed triangles and labels.
compute_centroids_graph ¶
compute_centroids_graph(mesh: DcelData) -> NDArray[np.float64]
Return an array of each region's centroid.
compute_networkx_graph ¶
compute_networkx_graph(mesh: DcelData) -> networkx.Graph
Compute a graph with values extracted from the mesh. Nodes = regions, edges = interfaces.
update_graph_with_scattered_values ¶
update_graph_with_scattered_values(graph: Graph, mesh: DcelData) -> networkx.Graph
Move the graph to the mesh's scattered ("exploded") view, from its unexploded positions.
Each cell node, and the vertices of each interface with the medium, move by the displacement of their cell
(mesh.clusters_displacements). Call it after mesh.compute_scattered_arrays(coeff). Every node then sits at
its exploded cell's barycentre (up to rounding), and an interface with the medium moves with its cell; an
interface between two cells does not move (its edge in the graph view is drawn between the two nodes).
The positions are computed from the graph's unexploded ones each time, into new arrays: they are recorded in
graph.graph["unexploded_centroid"] and graph.graph["unexploded_verts"] at the first call, so that calling
it again on the same graph (a new coefficient) does not add a second displacement, and the arrays the graph was
built with (mesh.centroids itself for the nodes) are never modified.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
graph
|
Graph
|
the mesh's graph ( |
required |
mesh
|
DcelData
|
the mesh, after |
required |
Returns:
| Type | Description |
|---|---|
Graph
|
networkx.Graph: |
compute_verts_and_faces_interfaces ¶
compute_verts_and_faces_interfaces(mesh: DcelData) -> tuple[dict[tuple[int, int], NDArray[np.float64]], dict[tuple[int, int], NDArray[np.int64]]]
Returns two dicts that maps (label1, label2) of an interface to array of vertices & triangles.