Skip to content

Commit af3fc57

Browse files
Improve skinseg module documentation (#149)
1 parent c26cdf5 commit af3fc57

File tree

1 file changed

+28
-0
lines changed

1 file changed

+28
-0
lines changed

src/openlifu/seg/skinseg.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
"""Tools to get a skin surface from an MRI.
2+
3+
Example workflow, starting from
4+
5+
- an MRI volume `vol_array`, as a numpy array
6+
- an associated 4x4 `affine` transform, as a numpy array
7+
- a desired spherical coordinate system `origin` location inside the volume (e.g. the sonication target)
8+
9+
foreground_mask_array = compute_foreground_mask(vol_array)
10+
foreground_mask_vtk_image = vtk_img_from_array_and_affine(foreground_mask_array, affine)
11+
skin_mesh = create_closed_surface_from_labelmap(foreground_mask_vtk_image)
12+
skin_interpolator = spherical_interpolator_from_mesh(skin_mesh, origin)
13+
"""
14+
115
from typing import Callable, List, Optional, Tuple
216

317
import numpy as np
@@ -265,6 +279,20 @@ def spherical_interpolator_from_mesh(
265279
Returns:
266280
A spherical interpolator, which is a callable that maps (theta,phi) pairs of spherical coordinates (phi being azimuthal)
267281
to r values (radial spherical coordinate values). The angles are in radians.
282+
283+
Summary of the algorithm:
284+
- Transform the input mesh based on the desired origin and orientation of the spherical coordinate system.
285+
- We will gather some points into a set $S$. For each point $P$ on the mesh consider the ray $\\vec{OP}$
286+
from the origin through $P$ and look at all the intersections of this ray $\\vec{OP}$ with the mesh.
287+
If none of those intersections are further out from the origin than $P$ is, then we put $P$ into our set $S$.
288+
- Using the spherical coordinates of the points in $S$, build a `scipy.interpolate.LinearNDInterpolator`
289+
that interpolates spherical $r$ values from the spherical $(\\theta,\\phi)$ values.
290+
- Problem: All the gathered $(\\theta,\\phi)$ values are likely strictly inside the square $[0,\\pi]\\times[-\\pi,\\pi]$,
291+
and `LinearNDInterpolator` does not _extrapolate_, and so angles close to the "seams" of the spherical coordinate
292+
system (the boundaries of that square) generate NaNs through the interpolator. The solution used here is to first
293+
clone the gathered points with appropriate angular shifts so as to cover those seams, and then give that larger set
294+
of points to the interpolator.
295+
- Return the interpolator.
268296
"""
269297

270298
if xyz_direction_columns is None:

0 commit comments

Comments
 (0)