cedalion.geometry.registration
Registrating optodes to scalp surfaces.
Functions
|
Selects three points that are spread apart from each other in the dataset. |
|
Calculate the affine transformation matrix T that transforms p1 to p2. |
|
Perform Iterative Closest Point algorithm with full transformation capabilities. |
|
Finds affine transformation between coords_target and coords_trafo. |
|
Iterative Closest Point algorithm for registration. |
|
Affine transformation that just adapts units. |
|
Register optode coordinates onto a scalp mesh via spring relaxation and ICP. |
|
Finds affine transformation between coords_target and coords_trafo. |
|
Finds affine transformation between coords_target and coords_trafo. |
|
Finds affine transformation between coords_target and coords_trafo. |
|
Projects 3D coordinates onto a 2D plane using a simple scalp projection. |
Classes
|
Quality-control details returned by |
- class cedalion.geometry.registration.SpringICPResult(
- initial_positions: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
- nominal_distances: dict,
- spring_errors: DataArray,
- landmark_errors: DataArray,
- snap_displacement_per_iter: ndarray,
- n_iterations: int,
- converged: bool,
Bases:
objectQuality-control details returned by
register_optodes_spring_icp().All distances and displacements are in the same units as the scalp surface.
- initial_positions: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')][source]
Positions after the initial landmark alignment, before spring relaxation.
- nominal_distances: dict[source]
Nominal channel distances
{(src_label, det_label): float}used as spring rest lengths. Measured in scalp units from the phase-1 aligned positions unless supplied by the caller.
- spring_errors: DataArray[source]
Per-channel
actual_distance - nominal_distanceat convergence. Dimchannel; auxiliary coordssourceanddetectorcarry the individual optode labels.
- landmark_errors: DataArray[source]
Per-anchor Euclidean distance between the final optode position and the target landmark position at convergence. Dim
label. Empty when no optode labels overlap withlandmarks_scalp.
- cedalion.geometry.registration.register_identity(
- coords_target: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
- coords_trafo: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
Affine transformation that just adapts units.
- Parameters:
coords_target (LabeledPoints) – Target point cloud.
coords_trafo (LabeledPoints) – Source point cloud.
- Returns:
Affine transformation between the two point clouds.
- Return type:
cdt.AffineTransform
- cedalion.geometry.registration.register_trans_rot(
- coords_target: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
- coords_trafo: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
Finds affine transformation between coords_target and coords_trafo.
Uses translation and roatation rotation. Requires at least 3 common labels between the two point clouds.
- Parameters:
coords_target (LabeledPoints) – Target point cloud.
coords_trafo (LabeledPoints) – Source point cloud.
- Returns:
Affine transformation between the two point clouds.
- Return type:
cdt.AffineTransform
- cedalion.geometry.registration.register_general_affine(
- coords_target: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
- coords_trafo: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
Finds affine transformation between coords_target and coords_trafo.
This method fits all 12 parameters of a 3D affine transformation without constraints. The transform thus contains scaling, rotation, translation, shear and mirroring, i.e. it can transform between left and right handed coordinate systems.
- Parameters:
coords_target (LabeledPoints) – Target point cloud.
coords_trafo (LabeledPoints) – Source point cloud.
- Returns:
Affine transformation between the two point clouds.
- Return type:
cdt.AffineTransform
- cedalion.geometry.registration.register_trans_rot_isoscale(
- coords_target: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
- coords_trafo: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
Finds affine transformation between coords_target and coords_trafo.
Uses translation, rotation and isotropic scaling. Requires at least 3 common labels between the two point clouds.
- Parameters:
coords_target (LabeledPoints) – Target point cloud.
coords_trafo (LabeledPoints) – Source point cloud.
- Returns:
Affine transformation between the two point clouds.
- Return type:
cdt.AffineTransform
- cedalion.geometry.registration.register_trans_rot_scale(
- coords_target: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
- coords_trafo: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
Finds affine transformation between coords_target and coords_trafo.
Uses translation, rotation and scaling. Requires at least 3 common labels between the two point clouds.
- Parameters:
coords_target (LabeledPoints) – Target point cloud.
coords_trafo (LabeledPoints) – Source point cloud.
- Returns:
Affine transformation between the two point clouds.
- Return type:
cdt.AffineTransform
- cedalion.geometry.registration.gen_xform_from_pts(p1: ndarray, p2: ndarray) ndarray[source]
Calculate the affine transformation matrix T that transforms p1 to p2.
- Parameters:
p1 (np.ndarray) – Source points (p x m) where p is the number of points and m is the number of dimensions.
p2 (np.ndarray) – Target points (p x m) where p is the number of points and m is the number of dimensions.
- Returns:
Affine transformation matrix T.
- cedalion.geometry.registration.register_icp(
- surface: Surface,
- landmarks: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
- geo3d: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
- niterations=1000,
- random_sample_fraction=0.5,
Iterative Closest Point algorithm for registration.
- Parameters:
surface (Surface) – Surface mesh to which to register the points.
landmarks (LabeledPoints) – Landmarks to use for registration.
geo3d (LabeledPoints) – Points to register to the surface.
niterations (int) – Number of iterations for the ICP algorithm (default 1000).
random_sample_fraction (float) – Fraction of points to use in each iteration (default 0.5).
- Returns:
Tuple containing the losses and transformations
- Return type:
Tuple[np.ndarray, np.ndarray]
- cedalion.geometry.registration.icp_with_full_transform(
- opt_centers: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
- montage_points: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
- max_iterations: int = 50,
- tolerance: float = 500.0,
Perform Iterative Closest Point algorithm with full transformation capabilities.
- Parameters:
opt_centers – Source point cloud for alignment.
montage_points – Target reference point cloud.
max_iterations – Maximum number of iterations for convergence.
tolerance – Tolerance for convergence check.
- Returns:
- Transformed source points as a numpy array with their coordinates
updated to reflect the best alignment.
- np.ndarray: Transformation parameters array consisting of
[tx, ty, tz, rx, ry, rz, sx, sy, sz], where ‘t’ stands for translation components, ‘r’ for rotation components (in radians), and ‘s’ for scaling components.
- np.ndarray: Indices of the target points that correspond to each source point as
per the nearest neighbor search.
- Return type:
np.ndarray
- cedalion.geometry.registration.find_spread_points(points_xr: DataArray) ndarray[source]
Selects three points that are spread apart from each other in the dataset.
- Parameters:
points_xr – An xarray DataArray containing the points from which to select.
- Returns:
Indices of the initial, farthest, and median-distanced points from the initial point as determined by their positions in the original dataset.
- cedalion.geometry.registration.simple_scalp_projection(
- geo3d: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
Projects 3D coordinates onto a 2D plane using a simple scalp projection.
- Parameters:
geo3d (LabeledPoints) – 3D coordinates of points to project. Requires the landmarks Nz, LPA, and RPA.
- Returns:
A LabeledPoints containing the 2D coordinates of the projected points.
- cedalion.geometry.registration.register_optodes_spring_icp(
- scalp: TrimeshSurface,
- geo3d: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
- channels: list[tuple[str, str]] | Annotated[DataArray, DataArraySchema(dims='time', coords='time', 'time', 'samples')] | DataFrame,
- landmarks_scalp: Annotated[DataArray, DataArraySchema(dims='label', coords='label', 'label', 'type')],
- nominal_distances: dict[tuple[str, str], float] | None = None,
- n_iter: int = 400,
- k_spring: float = 1.0,
- k_anchor: float = 10.0,
- step_size: float = 0.1,
- convergence_tol: float = 0.01,
- initial_align_mode: str = 'general',
Register optode coordinates onto a scalp mesh via spring relaxation and ICP.
Two-phase registration:
Initial alignment — a global transform (translation + rotation + optional scale) is fitted to the matched landmark pairs and applied to
geo3dto bring them into the scalp coordinate system.Spring-relaxation ICP — optodes are iteratively refined:
Hooke’s-law springs between each channel-forming source–detector pair, with rest length equal to the nominal inter-optode distance, resist distortion of channel geometry.
Strong anchor springs pull any coordinate in geo3d whose label appears in
landmarks_scalptoward its known anatomical position on the scalp.After each force step every optode is projected onto the nearest point on the scalp triangulated surface (ICP step).
- Parameters:
scalp – Triangulated scalp surface in the target coordinate system.
geo3d – Probe coordinates (sources, detectors and landmarks) in the probe coordinate system.
channels –
(source_label, detector_label)pairs defining which optode pairs form channels and therefore get a spring.landmarks_scalp – Anatomical landmark positions in the scalp CRS (same CRS as
scalp). Any label that also appears inoptodesis used as a strong anchor during the relaxation phase.nominal_distances – Optional pre-specified rest lengths for each channel spring, keyed by
(src_label, det_label). When None, distances are measured from the phase-1 aligned positions.n_iter – Maximum number of relaxation iterations.
k_spring – Spring constant for channel springs. Force magnitude scales linearly with extension from the nominal distance.
k_anchor – Spring constant for landmark-anchor springs. Should exceed
k_springto enforce anatomical constraints strongly.step_size – Fraction of the net force vector added to each position per iteration. Reduce if the relaxation is unstable.
convergence_tol – Stop early when the maximum surface-projection displacement across all optodes is below this value (in scalp units).
initial_align_mode – Phase-1 transform type. One of
"trans_rot_isoscale"(7 DOF, default),"trans_rot"(6 DOF),"general"(12 DOF full affine), or"identity"(only adapt units).
- Returns:
SpringICPResultwith the final optode positions and per-iteration / per-channel quality-control metrics.- Raises:
CRSMismatchError – If
landmarks_scalpis not in the same CRS asscalp.ValueError – If
initial_align_modeis not recognised, or if a channel label is absent fromoptodes.