| Title: | Geometric Transforms for Neuroimaging Data |
|---|---|
| Description: | A self-contained, dependency-light library for geometric transforms in neuroimaging. Provides affine and nonlinear (warp) mappings between coordinate systems, plus volume-to-surface mapping primitives. Emphasizes correctness, elegance, and composability with a category-theoretic flavor. |
| Authors: | Brad Buchsbaum [aut, cre] |
| Maintainer: | Brad Buchsbaum <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.0 |
| Built: | 2026-05-27 06:17:53 UTC |
| Source: | https://github.com/bbuchsbaum/neurotransform |
Returns an adjoint morphism when defined.
adjoint(object, ...) ## S4 method for signature 'Morphism' adjoint(object, ...) ## S4 method for signature 'IdentityMorphism' adjoint(object, ...) ## S4 method for signature 'Affine3DMorphism' adjoint(object, ...) ## S4 method for signature 'Warp3DMorphism' adjoint(object, ...) ## S4 method for signature 'VolToSurfMorphism' adjoint(object, ...) ## S4 method for signature 'SurfToSurfMorphism' adjoint(object, ...)adjoint(object, ...) ## S4 method for signature 'Morphism' adjoint(object, ...) ## S4 method for signature 'IdentityMorphism' adjoint(object, ...) ## S4 method for signature 'Affine3DMorphism' adjoint(object, ...) ## S4 method for signature 'Warp3DMorphism' adjoint(object, ...) ## S4 method for signature 'VolToSurfMorphism' adjoint(object, ...) ## S4 method for signature 'SurfToSurfMorphism' adjoint(object, ...)
object |
A Morphism object |
... |
Additional arguments |
For invertible morphisms, adjoint() is defined and equals invert().
For other morphisms, adjoint() may not be implemented and will error.
Adjoint morphism or error if not available
Wrap an affine matrix built from components into an Affine3DMorphism
affine_from_components(source, target, ...)affine_from_components(source, target, ...)
source |
Source domain identifier |
target |
Target domain identifier |
... |
Arguments passed to |
Affine3DMorphism object
Lightweight helpers for building, decomposing, and testing affine transforms without introducing external dependencies or tool-specific semantics.
Represents an affine transformation between volume spaces. The matrix maps target coords -> source coords (pullback semantics).
Affine3DMorphism(source, target, matrix, cost = 1, method_tag = "anatomical")Affine3DMorphism(source, target, matrix, cost = 1, method_tag = "anatomical")
source |
Source domain hash |
target |
Target domain hash |
matrix |
4x4 affine matrix (target -> source) |
cost |
Path cost (default 1.0) |
method_tag |
Method tag (default "anatomical") |
Affine3DMorphism object
# Translation by (10, 20, 30) mat <- diag(4) mat[1:3, 4] <- c(10, 20, 30) aff <- Affine3DMorphism("native", "mni", mat)# Translation by (10, 20, 30) mat <- diag(4) mat[1:3, 4] <- c(10, 20, 30) aff <- Affine3DMorphism("native", "mni", mat)
Represents an affine transformation (rotation, translation, scaling, shear) between volume spaces.
matrix4x4 affine transformation matrix (maps target -> source)
Converts an AFNI RAI affine matrix to our internal RAS convention by flipping the Z axis. Optionally applies AFNI-style deobliquing compensation when source/target image affines are provided.
afni_aff12_to_ras( mat_rai, source_affine = NULL, target_affine = NULL, oblique_correction = TRUE )afni_aff12_to_ras( mat_rai, source_affine = NULL, target_affine = NULL, oblique_correction = TRUE )
mat_rai |
4x4 affine in RAI coordinates |
source_affine |
Optional 4x4 source (moving) voxel-to-world affine |
target_affine |
Optional 4x4 target (reference) voxel-to-world affine |
oblique_correction |
Logical; apply AFNI cardinal rotation correction |
4x4 affine in RAS coordinates
mat_rai <- diag(4) mat_ras <- afni_aff12_to_ras(mat_rai)mat_rai <- diag(4) mat_ras <- afni_aff12_to_ras(mat_rai)
Detect whether an affine is oblique (not cardinal axis-aligned)
afni_is_oblique(affine, threshold_deg = 0.01)afni_is_oblique(affine, threshold_deg = 0.01)
affine |
4x4 voxel-to-world affine |
threshold_deg |
Angular threshold in degrees |
Logical
Reads a 3x4 affine matrix in RAI coordinates and returns a 4x4 matrix.
afni_read_aff12(path)afni_read_aff12(path)
path |
Path to .aff12.1D file |
4x4 affine matrix (in RAI)
## Not run: mat_rai <- afni_read_aff12("transform.aff12.1D") ## End(Not run)## Not run: mat_rai <- afni_read_aff12("transform.aff12.1D") ## End(Not run)
AFNI-specific coordinate convention handling. AFNI 3dQwarp stores displacement fields in DICOM/LPS convention. These functions handle the LPS <-> RAS conversion for warps and RAI <-> RAS for affines.
LPS (DICOM, used in AFNI warp displacements): +X=Left, +Y=Posterior, +Z=Superior
RAI (AFNI affines): +X=Right, +Y=Anterior, +Z=Inferior
RAS (NIfTI/neuroim2): +X=Right, +Y=Anterior, +Z=Superior
LPS to RAS: negate X and Y (Z is the same). RAI to RAS: negate Z only (X and Y are the same).
S4 class definitions for the neurotransform package. This file defines the morphism class hierarchy. neurotransform is a pure transform kernel; domain and geometry abstractions live in higher-level packages.
Morphism (virtual) |-- IdentityMorphism |-- Affine3DMorphism |-- Warp3DMorphism |-- VolToSurfMorphism |-- SurfToSurfMorphism MorphismPath (lightweight list wrapper for composed paths)
A morphism A -> B maps coordinates in B to coordinates in A (pullback semantics). This is the natural convention for resampling: to get a value at target location, you need to know where to sample from in the source.
Generic function definitions for the neurotransform package. These define the core API for coordinate transforms.
Creates a morphism (or MorphismPath) from an ANTs composite H5 transform file. These files typically contain both a displacement field and an affine transform.
ants_h5_morphism( path, source = "source", target = "target", apply_affine = TRUE )ants_h5_morphism( path, source = "source", target = "target", apply_affine = TRUE )
path |
Path to ANTs H5 file |
source |
Source coordinate space identifier |
target |
Target coordinate space identifier |
apply_affine |
If TRUE and an embedded affine is present, return a MorphismPath combining warp and affine. If FALSE, return only the warp. |
Warp3DMorphism (if no affine or apply_affine=FALSE) or MorphismPath
When apply_affine=TRUE, returns a MorphismPath ordered as [warp, affine].
This ordering is critical for correct pullback (resampling) semantics:
MorphismPath applies transforms right-to-left for pullback
[warp, affine] means: affine_pullback(warp_pullback(coords))
Target coords -> warp lookup -> affine transform -> source coords
The ANTs forward transform is "affine then warp", so pullback (inverse) is
"inverse_warp then inverse_affine" - hence the [warp, affine] order.
Generic function to apply a 4x4 affine matrix to 3D coordinates.
apply_affine(coords, affine)apply_affine(coords, affine)
coords |
Numeric matrix (N x 3) or vector of length 3 |
affine |
4x4 affine transformation matrix |
Transformed coordinates
coords <- matrix(c(10, 20, 30), ncol = 3) affine <- diag(4) affine[1:3, 4] <- c(5, 10, 15) # translation apply_affine(coords, affine)coords <- matrix(c(10, 20, 30), ncol = 3) affine <- diag(4) affine[1:3, 4] <- c(5, 10, 15) # translation apply_affine(coords, affine)
Apply a resampling plan to a volume
apply_resampling_plan( plan, source_data, outside = NA_real_, modulate = c("none", "jacobian", "sqrt_jacobian") )apply_resampling_plan( plan, source_data, outside = NA_real_, modulate = c("none", "jacobian", "sqrt_jacobian") )
plan |
ResamplingPlan |
source_data |
3D or 4D array in source_grid geometry |
outside |
Value for out-of-bounds sampling |
modulate |
Jacobian modulation: "none", "jacobian", "sqrt_jacobian" |
Array with target_grid dimensions (and trailing data dim if 4D input)
Apply a surface resampling plan to vertex data
apply_surface_resampling( plan, x, inverse = FALSE, normalize = c("element", "sum", "none") )apply_surface_resampling( plan, x, inverse = FALSE, normalize = c("element", "sum", "none") )
plan |
A |
x |
Vertex data ( |
inverse |
Logical; apply inverse direction ( |
normalize |
One of |
Resampled vector or matrix
Coerce list/paths to MorphismPath
as_morphism_path(...)as_morphism_path(...)
... |
Morphism objects or file paths to transforms |
MorphismPath object
Implements a simple backprojection operator that distributes each surface value into the source volume grid using the same interpolation weights that forward sampling would use.
backproject_surface_to_volume( surface_values, morphism, grid, surface_coords = NULL, method = c("linear", "nearest", "ribbon"), outside = 0 )backproject_surface_to_volume( surface_values, morphism, grid, surface_coords = NULL, method = c("linear", "nearest", "ribbon"), outside = 0 )
surface_values |
Numeric vector (length N) or matrix (N x k) of values at surface points |
morphism |
VolToSurfMorphism |
grid |
Source Grid (volume geometry) |
surface_coords |
Optional N x 3 world coordinates; defaults to morphism@params$mid_coords |
method |
"linear", "nearest", or "ribbon" |
outside |
Value used for out-of-bounds (default 0) |
This is the transpose/adjoint of the linear sampling operator for
sample_volume_on_surface(..., method="linear") when the same
surface_coords are used.
3D array (or 4D if multivariate surface_values) in grid geometry
Build a 4x4 affine matrix from components
build_affine_matrix( translation = c(0, 0, 0), scales = c(1, 1, 1), skews = c(0, 0, 0), angles = c(0, 0, 0), anchor = c("none", "origin", "centre", "center") )build_affine_matrix( translation = c(0, 0, 0), scales = c(1, 1, 1), skews = c(0, 0, 0), angles = c(0, 0, 0), anchor = c("none", "origin", "centre", "center") )
translation |
length-3 translation vector (applied last) |
scales |
length-3 scaling |
skews |
length-3 shear terms (xy, xz, yz) |
angles |
length-3 rotation angles (radians) about x, y, z (applied in Z-Y-X order) |
anchor |
Either |
4x4 numeric matrix
Returns the composition g . f (f applied first, then g). The result is a MorphismPath that can be passed to transform().
compose(f, g) ## S4 method for signature 'Morphism,Morphism' compose(f, g) ## S4 method for signature 'MorphismPath,Morphism' compose(f, g) ## S4 method for signature 'Morphism,MorphismPath' compose(f, g) ## S4 method for signature 'MorphismPath,MorphismPath' compose(f, g)compose(f, g) ## S4 method for signature 'Morphism,Morphism' compose(f, g) ## S4 method for signature 'MorphismPath,Morphism' compose(f, g) ## S4 method for signature 'Morphism,MorphismPath' compose(f, g) ## S4 method for signature 'MorphismPath,MorphismPath' compose(f, g)
f |
First morphism (applied first) |
g |
Second morphism (applied second) |
MorphismPath representing the composition
aff1 <- Affine3DMorphism("a", "b", diag(4)) aff2 <- Affine3DMorphism("b", "c", diag(4)) path <- compose(aff1, aff2) # a -> b -> caff1 <- Affine3DMorphism("a", "b", diag(4)) aff2 <- Affine3DMorphism("b", "c", diag(4)) path <- compose(aff1, aff2) # a -> b -> c
Returns the composition B(A(x)) = BA * x.
compose_affines(A, B)compose_affines(A, B)
A |
First affine (applied first) |
B |
Second affine (applied second) |
Composed 4x4 affine matrix
A <- diag(4); A[1:3, 4] <- c(1, 2, 3) B <- diag(4); B[1:3, 4] <- c(4, 5, 6) compose_affines(A, B)A <- diag(4); A[1:3, 4] <- c(1, 2, 3) B <- diag(4); B[1:3, 4] <- c(4, 5, 6) compose_affines(A, B)
Creates a reproducible hash using digest with serialize=TRUE.
compute_hash(..., algo = "xxhash64")compute_hash(..., algo = "xxhash64")
... |
Objects to hash |
algo |
Hash algorithm (default "xxhash64" for speed) |
Character string hash
compute_hash("hello", "world") compute_hash(list(a = 1, b = 2))compute_hash("hello", "world") compute_hash(list(a = 1, b = 2))
Convert affine conventions between "generic" (target→source world) and "fsl" (source→target vox)
convert_affine_convention( matrix, source_affine, target_affine, source_dim = NULL, target_dim = NULL, from = c("generic", "fsl"), to = c("generic", "fsl") )convert_affine_convention( matrix, source_affine, target_affine, source_dim = NULL, target_dim = NULL, from = c("generic", "fsl"), to = c("generic", "fsl") )
matrix |
4x4 matrix in the |
source_affine |
4x4 voxel-to-world for source image |
target_affine |
4x4 voxel-to-world for target image |
source_dim |
Optional source image dimensions (for FSL handedness swap) |
target_dim |
Optional target image dimensions (for FSL handedness swap) |
from |
Input convention ("generic", "fsl") |
to |
Output convention ("generic", "fsl") |
Functions for converting between coordinate conventions used in neuroimaging.
Internal convention: RAS (Right-Anterior-Superior) in millimeters.
RAS: Right-Anterior-Superior (internal standard)
LPS: Left-Posterior-Superior (ANTs/ITK convention)
tkRAS: FreeSurfer tkregister RAS
FSL: FSL world coordinates (mm, may need scaling)
Apply affines -> warp -> affines to coordinates (target -> source)
cpp_path_apply_affine_warp_affine( coords, affines_pre, field, dim, world_to_vox, cubic, affines_post )cpp_path_apply_affine_warp_affine( coords, affines_pre, field, dim, world_to_vox, cubic, affines_post )
coords |
n x 3 target world coords |
affines_pre |
list of 4x4 matrices applied before warp |
field |
displacement field |
dim |
field dims |
world_to_vox |
warp world_to_vox |
cubic |
use cubic sampling |
affines_post |
list of 4x4 matrices applied after warp |
n x 3 source world coords
Apply arbitrary steps (affine/warp) to coordinates (target -> source)
cpp_path_apply_steps(coords, steps)cpp_path_apply_steps(coords, steps)
coords |
n x 3 target world coords |
steps |
list of steps with kind \"affine\" or \"warp\" and associated data |
n x 3 transformed coords
Decompose a 4x4 affine matrix into components
decompose_affine_matrix(matrix)decompose_affine_matrix(matrix)
matrix |
4x4 numeric matrix |
list with translation, rotation_matrix, scales, skews, angles
Helpers to materialize morphisms on voxel grids for visualization or export, keeping the core morphism API untouched.
deformation_field(morphism, grid, with_jacobian = TRUE, log = FALSE)deformation_field(morphism, grid, with_jacobian = TRUE, log = FALSE)
morphism |
A Morphism (affine or warp) |
grid |
A Grid object (see grid_spec/grid_from_data) |
with_jacobian |
Logical; attach Jacobian determinant volume |
log |
If TRUE, store log-Jacobian |
An array with dim = c(grid@dims, 3) and class "DeformationField"
Heuristically determines whether an FNIRT warp stores relative displacements or absolute coordinates.
detect_fnirt_def_type(warp_path, sample_n = 200, threshold_mm = 5)detect_fnirt_def_type(warp_path, sample_n = 200, threshold_mm = 5)
warp_path |
Path to FNIRT warp file |
sample_n |
Number of voxels to sample for heuristic |
threshold_mm |
Threshold for displacement magnitude heuristic |
"relative" or "absolute"
## Not run: def_type <- detect_fnirt_def_type("warp.nii.gz") ## End(Not run)## Not run: def_type <- detect_fnirt_def_type("warp.nii.gz") ## End(Not run)
Detect transform type from a file path
detect_transform_type(path, source_affine = NULL, target_affine = NULL)detect_transform_type(path, source_affine = NULL, target_affine = NULL)
path |
Transform file path |
source_affine |
Optional source affine used to disambiguate linear files |
target_affine |
Optional target affine used to disambiguate linear files |
Character scalar naming the detected transform family
Convenience wrapper returning the Dice coefficient from overlap_metrics().
dice_coefficient( x, y, threshold = 0, label = NULL, na.rm = TRUE, empty = c("one", "zero", "na"), check_geometry = TRUE, tolerance = sqrt(.Machine$double.eps) )dice_coefficient( x, y, threshold = 0, label = NULL, na.rm = TRUE, empty = c("one", "zero", "na"), check_geometry = TRUE, tolerance = sqrt(.Machine$double.eps) )
x, y
|
Arrays or image objects with matching dimensions. |
threshold |
Numeric scalar used to form foreground masks when |
label |
Optional single label value. If supplied, Dice is computed for that label instead of by thresholding. |
na.rm |
Logical; if |
empty |
How to score Dice, Jaccard, overlap coefficient, and volume
similarity when both masks are empty. |
check_geometry |
Logical; if |
tolerance |
Numeric tolerance used for affine comparisons. |
Numeric scalar Dice coefficient.
x <- array(c(TRUE, TRUE, FALSE, FALSE), dim = c(2, 2, 1)) y <- array(c(TRUE, FALSE, TRUE, FALSE), dim = c(2, 2, 1)) dice_coefficient(x, y)x <- array(c(TRUE, TRUE, FALSE, FALSE), dim = c(2, 2, 1)) y <- array(c(TRUE, FALSE, TRUE, FALSE), dim = c(2, 2, 1)) dice_coefficient(x, y)
Extract affine matrix from data
extract_affine(x) ## S4 method for signature 'array' extract_affine(x) ## S4 method for signature 'matrix' extract_affine(x) ## S4 method for signature 'ANY' extract_affine(x) ## S4 method for signature 'DenseNeuroVol' extract_affine(x) ## S4 method for signature 'DenseNeuroVec' extract_affine(x)extract_affine(x) ## S4 method for signature 'array' extract_affine(x) ## S4 method for signature 'matrix' extract_affine(x) ## S4 method for signature 'ANY' extract_affine(x) ## S4 method for signature 'DenseNeuroVol' extract_affine(x) ## S4 method for signature 'DenseNeuroVec' extract_affine(x)
x |
Data object |
4x4 affine matrix
Given a FLIRT matrix (source_FSL -> ref_FSL), returns the internal ref_world -> src_world affine for pullback semantics.
fsl_flirt_to_internal_affine( flirt_mat, source_affine, ref_affine, source_dim = NULL, ref_dim = NULL )fsl_flirt_to_internal_affine( flirt_mat, source_affine, ref_affine, source_dim = NULL, ref_dim = NULL )
flirt_mat |
4x4 FLIRT matrix |
source_affine |
4x4 voxel-to-world for source image |
ref_affine |
4x4 voxel-to-world for reference image |
source_dim |
Optional source image dimensions (needed for handedness swap) |
ref_dim |
Optional reference image dimensions (needed for handedness swap) |
4x4 internal affine (ref_world -> src_world)
## Not run: flirt_mat <- as.matrix(read.table("xform.mat")) src_aff <- diag(4) # from source image header ref_aff <- diag(4) # from reference image header internal <- fsl_flirt_to_internal_affine(flirt_mat, src_aff, ref_aff) ## End(Not run)## Not run: flirt_mat <- as.matrix(read.table("xform.mat")) src_aff <- diag(4) # from source image header ref_aff <- diag(4) # from reference image header internal <- fsl_flirt_to_internal_affine(flirt_mat, src_aff, ref_aff) ## End(Not run)
FSL-specific coordinate convention handling. FSL uses scaled voxel coordinates for FLIRT matrices and has specific conventions for FNIRT warp fields (relative vs absolute).
Returns a small factory descriptor for linear transform IO, including canonical format and reader/writer function handles.
get_linear_factory(fmt, is_array = TRUE)get_linear_factory(fmt, is_array = TRUE)
fmt |
Format name (e.g. |
is_array |
Logical; if |
List with format, reader, and writer
Gets a loader function from the registry.
get_loader(name = NULL) get_warp_loader(name = NULL)get_loader(name = NULL) get_warp_loader(name = NULL)
name |
Loader name (default "neuroim2") |
Loader function
loader <- get_loader("neuroim2")loader <- get_loader("neuroim2")
Get world coordinates for a grid
grid_coords(grid)grid_coords(grid)
grid |
Grid object |
Numeric matrix (prod(dims) x 3)
Get grid specification from volume data
grid_from_data(data)grid_from_data(data)
data |
Volume with geometry |
Grid object
Extract Grid from volume or grid-like input
grid_of(x)grid_of(x)
x |
neuroim2 volume, array, or Grid |
Grid
Create a grid specification
grid_spec(dims, affine)grid_spec(dims, affine)
dims |
Integer vector of dimensions |
affine |
4x4 voxel-to-world matrix |
Grid object
Grid: regular coordinate grid specification
## S4 method for signature 'Grid' show(object)## S4 method for signature 'Grid' show(object)
object |
A Grid object (for show method) |
dimsInteger: grid dimensions
affine4x4 voxel-to-world matrix
Returns TRUE if adjoint() is available for this morphism.
For linear/invertible morphisms, the adjoint is the inverse.
has_adjoint(object)has_adjoint(object)
object |
A Morphism object |
Logical
The identity morphism maps a domain to itself. Cost is 0.
IdentityMorphism(domain)IdentityMorphism(domain)
domain |
Domain hash string |
IdentityMorphism object
id <- IdentityMorphism("my_domain_hash")id <- IdentityMorphism("my_domain_hash")
The identity morphism maps a domain to itself. Required for categorical structure and useful for composition.
Returns the inverse morphism if available (inverse_type == "exact" or "approximate"). For morphisms with approximate or adjoint inverses, use adjoint() instead.
invert(object) ## S4 method for signature 'Morphism' invert(object) ## S4 method for signature 'IdentityMorphism' invert(object) ## S4 method for signature 'Affine3DMorphism' invert(object) ## S4 method for signature 'Warp3DMorphism' invert(object)invert(object) ## S4 method for signature 'Morphism' invert(object) ## S4 method for signature 'IdentityMorphism' invert(object) ## S4 method for signature 'Affine3DMorphism' invert(object) ## S4 method for signature 'Warp3DMorphism' invert(object)
object |
A Morphism object |
Inverted morphism
aff <- Affine3DMorphism("a", "b", diag(4)) inv <- invert(aff) # b -> aaff <- Affine3DMorphism("a", "b", diag(4)) inv <- invert(aff) # b -> a
Invert an affine transformation
invert_affine(affine)invert_affine(affine)
affine |
4x4 affine matrix |
Inverted 4x4 affine matrix
affine <- diag(4) affine[1:3, 4] <- c(5, 10, 15) inv <- invert_affine(affine)affine <- diag(4) affine[1:3, 4] <- c(5, 10, 15) inv <- invert_affine(affine)
Check if an object is a numeric 4x4 affine matrix
is_affine_matrix(x)is_affine_matrix(x)
x |
Object to test |
Logical
Check if an object is an Affine3DMorphism
is_affine_morphism(x)is_affine_morphism(x)
x |
Object to test |
Logical
Returns TRUE only if a geometric inverse is available via invert().
is_invertible(object)is_invertible(object)
object |
A Morphism object |
Logical
aff <- Affine3DMorphism("a", "b", diag(4)) is_invertible(aff) # TRUEaff <- Affine3DMorphism("a", "b", diag(4)) is_invertible(aff) # TRUE
Check if morphism is linear (affine or identity)
is_linear_morphism(object)is_linear_morphism(object)
object |
A Morphism object |
Logical
Returns TRUE if the path is composable, FALSE otherwise.
is_valid_path(path)is_valid_path(path)
path |
List of Morphism objects |
Logical
aff1 <- Affine3DMorphism("a", "b", diag(4)) aff2 <- Affine3DMorphism("b", "c", diag(4)) is_valid_path(list(aff1, aff2)) # TRUEaff1 <- Affine3DMorphism("a", "b", diag(4)) aff2 <- Affine3DMorphism("b", "c", diag(4)) is_valid_path(list(aff1, aff2)) # TRUE
Check if morphism is a warp field
is_warp_morphism(object)is_warp_morphism(object)
object |
A Morphism object |
Logical
Convenience wrapper returning the Jaccard index from overlap_metrics().
jaccard_index( x, y, threshold = 0, label = NULL, na.rm = TRUE, empty = c("one", "zero", "na"), check_geometry = TRUE, tolerance = sqrt(.Machine$double.eps) )jaccard_index( x, y, threshold = 0, label = NULL, na.rm = TRUE, empty = c("one", "zero", "na"), check_geometry = TRUE, tolerance = sqrt(.Machine$double.eps) )
x, y
|
Arrays or image objects with matching dimensions. |
threshold |
Numeric scalar used to form foreground masks when |
label |
Optional single label value. If supplied, Dice is computed for that label instead of by thresholding. |
na.rm |
Logical; if |
empty |
How to score Dice, Jaccard, overlap coefficient, and volume
similarity when both masks are empty. |
check_geometry |
Logical; if |
tolerance |
Numeric tolerance used for affine comparisons. |
Numeric scalar Jaccard index.
x <- array(c(1, 1, 0, 0), dim = c(2, 2, 1)) y <- array(c(1, 0, 1, 0), dim = c(2, 2, 1)) jaccard_index(x, y)x <- array(c(1, 1, 0, 0), dim = c(2, 2, 1)) y <- array(c(1, 0, 1, 0), dim = c(2, 2, 1)) jaccard_index(x, y)
Compute Jacobian matrices and determinants for morphisms. The Jacobian is the derivative of the coordinate transformation.
jacobian(morphism, coords, mode = c("pullback", "pushforward")) ## S4 method for signature 'IdentityMorphism,ANY' jacobian(morphism, coords, mode = c("pullback", "pushforward")) ## S4 method for signature 'Affine3DMorphism,ANY' jacobian(morphism, coords, mode = c("pullback", "pushforward")) ## S4 method for signature 'Warp3DMorphism,ANY' jacobian(morphism, coords, mode = c("pullback", "pushforward")) ## S4 method for signature 'MorphismPath,ANY' jacobian(morphism, coords, mode = c("pullback", "pushforward")) ## S4 method for signature 'VolToSurfMorphism,ANY' jacobian(morphism, coords, mode = c("pullback", "pushforward")) ## S4 method for signature 'SurfToSurfMorphism,ANY' jacobian(morphism, coords, mode = c("pullback", "pushforward")) ## S4 method for signature 'DeformationField,missing' jacobian(morphism, coords, mode = c("pullback", "pushforward"))jacobian(morphism, coords, mode = c("pullback", "pushforward")) ## S4 method for signature 'IdentityMorphism,ANY' jacobian(morphism, coords, mode = c("pullback", "pushforward")) ## S4 method for signature 'Affine3DMorphism,ANY' jacobian(morphism, coords, mode = c("pullback", "pushforward")) ## S4 method for signature 'Warp3DMorphism,ANY' jacobian(morphism, coords, mode = c("pullback", "pushforward")) ## S4 method for signature 'MorphismPath,ANY' jacobian(morphism, coords, mode = c("pullback", "pushforward")) ## S4 method for signature 'VolToSurfMorphism,ANY' jacobian(morphism, coords, mode = c("pullback", "pushforward")) ## S4 method for signature 'SurfToSurfMorphism,ANY' jacobian(morphism, coords, mode = c("pullback", "pushforward")) ## S4 method for signature 'DeformationField,missing' jacobian(morphism, coords, mode = c("pullback", "pushforward"))
morphism |
A Morphism or MorphismPath |
coords |
Numeric matrix (n x 3) of coordinates |
mode |
"pullback" (default) or "pushforward" |
JacobianField object
For a morphism with pullback semantics (transform maps target -> source), the pullback Jacobian is d(source)/d(target), evaluated at target coordinates.
"pullback": d(source)/d(target) - natural for resampling
"pushforward": d(target)/d(source) - requires invertible morphism
aff <- Affine3DMorphism("a", "b", diag(4)) coords <- matrix(c(0, 0, 0, 10, 20, 30), ncol = 3, byrow = TRUE) J <- jacobian(aff, coords)aff <- Affine3DMorphism("a", "b", diag(4)) coords <- matrix(c(0, 0, 0, 10, 20, 30), ncol = 3, byrow = TRUE) J <- jacobian(aff, coords)
Compute Jacobian determinants
jacobian_det( morphism, coords, log = FALSE, mode = c("pullback", "pushforward") ) ## S4 method for signature 'IdentityMorphism' jacobian_det( morphism, coords, log = FALSE, mode = c("pullback", "pushforward") ) ## S4 method for signature 'Affine3DMorphism' jacobian_det( morphism, coords, log = FALSE, mode = c("pullback", "pushforward") ) ## S4 method for signature 'Warp3DMorphism' jacobian_det( morphism, coords, log = FALSE, mode = c("pullback", "pushforward") ) ## S4 method for signature 'MorphismPath' jacobian_det( morphism, coords, log = FALSE, mode = c("pullback", "pushforward") )jacobian_det( morphism, coords, log = FALSE, mode = c("pullback", "pushforward") ) ## S4 method for signature 'IdentityMorphism' jacobian_det( morphism, coords, log = FALSE, mode = c("pullback", "pushforward") ) ## S4 method for signature 'Affine3DMorphism' jacobian_det( morphism, coords, log = FALSE, mode = c("pullback", "pushforward") ) ## S4 method for signature 'Warp3DMorphism' jacobian_det( morphism, coords, log = FALSE, mode = c("pullback", "pushforward") ) ## S4 method for signature 'MorphismPath' jacobian_det( morphism, coords, log = FALSE, mode = c("pullback", "pushforward") )
morphism |
A Morphism or MorphismPath |
coords |
Numeric matrix (n x 3) of coordinates |
log |
Return log(|det(J)|)? |
mode |
"pullback" or "pushforward" |
Numeric vector of determinants
aff <- Affine3DMorphism("a", "b", diag(4) * 2) coords <- matrix(c(0, 0, 0), ncol = 3) jacobian_det(aff, coords) # 8 (2^3) jacobian_det(aff, coords, log = TRUE) # log(8)aff <- Affine3DMorphism("a", "b", diag(4) * 2) coords <- matrix(c(0, 0, 0), ncol = 3) jacobian_det(aff, coords) # 8 (2^3) jacobian_det(aff, coords, log = TRUE) # log(8)
Extract Jacobian determinant volume from a morphism on a grid
jacobian_det_field(morphism, grid, log = FALSE)jacobian_det_field(morphism, grid, log = FALSE)
morphism |
A Morphism (affine or warp) |
grid |
A Grid object |
log |
Logical; if TRUE, return log-Jacobian determinants |
Array with grid dimensions containing Jacobian determinants
Jacobian field: collection of 3x3 Jacobian matrices
Extract single Jacobian matrix or subset
Number of Jacobians
Compute determinants
Invert Jacobians (for mode switching)
## S4 method for signature 'JacobianField' show(object) ## S4 method for signature 'JacobianField,numeric,ANY,ANY' x[i, j, ..., drop = TRUE] ## S4 method for signature 'JacobianField' length(x) ## S4 method for signature 'JacobianField' det(x, ...) ## S4 method for signature 'JacobianField,missing' solve(a, b, ...)## S4 method for signature 'JacobianField' show(object) ## S4 method for signature 'JacobianField,numeric,ANY,ANY' x[i, j, ..., drop = TRUE] ## S4 method for signature 'JacobianField' length(x) ## S4 method for signature 'JacobianField' det(x, ...) ## S4 method for signature 'JacobianField,missing' solve(a, b, ...)
object |
A JacobianField object (for show method) |
x |
A JacobianField object (for other methods) |
i |
Numeric index for subsetting |
j |
Second index (optional) |
... |
Additional arguments |
drop |
Logical; if TRUE drop dimensions |
a |
A JacobianField object (for solve method) |
b |
Missing (solve method signature) |
valuesNumeric array (n x 3 x 3) of Jacobian matrices
coordsNumeric matrix (n x 3) of coordinate locations
modeCharacter: "pullback" or "pushforward"
morphism_hashHash of source morphism
List all registered loaders
list_loaders()list_loaders()
Character vector of registered loader names
list_loaders()list_loaders()
ANTs and ITK use LPS (Left-Posterior-Superior) convention. This function converts to our internal RAS convention by flipping the first two axes.
lps_to_ras(coords)lps_to_ras(coords)
coords |
Numeric matrix (N x 3) or vector of length 3 in LPS |
Coordinates in RAS convention
lps <- c(-10, -20, 30) ras <- lps_to_ras(lps)lps <- c(-10, -20, 30) ras <- lps_to_ras(lps)
Read/write FreeSurfer LTA linear transform files (single or array forms).
Build a resampling plan
make_resampling_plan( morphism, source_grid, target_grid, interpolation = c("linear", "cubic", "nearest"), reuse_count = 1L, cache = TRUE )make_resampling_plan( morphism, source_grid, target_grid, interpolation = c("linear", "cubic", "nearest"), reuse_count = 1L, cache = TRUE )
morphism |
Morphism or MorphismPath |
source_grid |
Grid describing the source volume geometry |
target_grid |
Grid describing the target geometry |
interpolation |
"linear", "cubic", or "nearest" |
reuse_count |
Hint for expected reuse; >1 enables caching |
cache |
Logical; cache the plan by hash |
A ResamplingPlan object
Check whether a surface mesh is approximately spherical
mesh_is_sphere(mesh, tolerance = 1.001)mesh_is_sphere(mesh, tolerance = 1.001)
mesh |
SurfaceMesh object |
tolerance |
Ratio tolerance for min/max radius comparison |
Logical
Set mesh radius for spherical meshes
mesh_set_radius(mesh, radius = 100)mesh_set_radius(mesh, radius = 100)
mesh |
SurfaceMesh object |
radius |
Target radius |
SurfaceMesh object with rescaled coordinates
Constructors and methods for morphism classes. Morphisms represent coordinate transformations with pullback semantics.
Creates a stable hash from morphism properties for identity and caching.
morphism_hash(object)morphism_hash(object)
object |
A Morphism object |
Character hash string
Returns the morphism kind (identity, affine3d, warp3d, vol2surf, surf2surf).
morphism_kind(object)morphism_kind(object)
object |
A Morphism object |
Character string indicating kind
aff <- Affine3DMorphism("a", "b", diag(4)) morphism_kind(aff) # "affine3d"aff <- Affine3DMorphism("a", "b", diag(4)) morphism_kind(aff) # "affine3d"
A Morphism represents a coordinate transformation between domains. Direction convention: a morphism A -> B maps coordinates in B to coordinates in A (pullback semantics). Data flows opposite: from A to B.
## S4 method for signature 'Morphism' show(object)## S4 method for signature 'Morphism' show(object)
object |
A Morphism object (for show method) |
idCharacter identifier
sourceCharacter: source domain hash (opaque string)
targetCharacter: target domain hash (opaque string)
kindCharacter morphism kind (identity, affine3d, warp3d, vol2surf, surf2surf)
paramsList: forward params/metadata
inverse_paramsList: inverse params/metadata
method_tagCharacter: path selection tag (anatomical/functional/etc.)
coverageOptional mask/metadata for valid region
costNumeric: cost/weight for graph traversal
hashStable hash of morphism
inverse_typeOne of "exact", "approximate", "adjoint", "none"
inverse_qualityNumeric in range 0 to 1, optional confidence for inverse
inverse_methodDescription/label for inverse strategy
provenanceList: metadata about the transform origin
cacheEnvironment for cached data
A lightweight wrapper around a list of morphisms representing a composed path. When passed to transform(), applies the full sequence efficiently. Order convention: path = list(f, g) means f first, then g (like g . f).
morphismsList of Morphism objects
sourceSource domain hash (from first morphism)
targetTarget domain hash (from last morphism)
Compute voxelwise overlap summaries for two images or masks. Inputs may be
plain arrays or image objects that can be coerced with as.array(), including
neuroim2 volumes.
overlap_metrics( x, y, threshold = 0, labels = NULL, na.rm = TRUE, empty = c("one", "zero", "na"), check_geometry = TRUE, tolerance = sqrt(.Machine$double.eps) )overlap_metrics( x, y, threshold = 0, labels = NULL, na.rm = TRUE, empty = c("one", "zero", "na"), check_geometry = TRUE, tolerance = sqrt(.Machine$double.eps) )
x, y
|
Arrays or image objects with matching dimensions. |
threshold |
Numeric scalar used to form foreground masks when |
labels |
Optional vector of label values to compare. When supplied,
|
na.rm |
Logical; if |
empty |
How to score Dice, Jaccard, overlap coefficient, and volume
similarity when both masks are empty. |
check_geometry |
Logical; if |
tolerance |
Numeric tolerance used for affine comparisons. |
By default, numeric images are converted to foreground masks with
value > threshold, and logical images use TRUE as foreground. Supply
labels to compute label-wise overlap instead.
A data frame with voxel counts and overlap metrics. sensitivity
is intersection / n_x; precision is intersection / n_y.
x <- array(c(1, 1, 0, 0), dim = c(2, 2, 1)) y <- array(c(1, 0, 1, 0), dim = c(2, 2, 1)) overlap_metrics(x, y)x <- array(c(1, 1, 0, 0), dim = c(2, 2, 1)) y <- array(c(1, 0, 1, 0), dim = c(2, 2, 1)) overlap_metrics(x, y)
Converts from our internal RAS convention to ANTs/ITK LPS convention.
ras_to_lps(coords)ras_to_lps(coords)
coords |
Numeric matrix (N x 3) or vector of length 3 in RAS |
Coordinates in LPS convention
ras <- c(10, 20, 30) lps <- ras_to_lps(ras)ras <- c(10, 20, 30) lps <- ras_to_lps(ras)
Converts from scanner RAS to FreeSurfer's tkRAS coordinate system.
ras_to_tkras(ras, c_ras)ras_to_tkras(ras, c_ras)
ras |
Numeric matrix (N x 3) or vector of length 3 in scanner RAS |
c_ras |
Numeric vector of length 3: the c_ras offset from FreeSurfer |
Coordinates in tkRAS
scanner_ras <- c(0.5, -2.3, 1.1) c_ras <- c(0.5, -2.3, 1.1) tkras <- ras_to_tkras(scanner_ras, c_ras)scanner_ras <- c(0.5, -2.3, 1.1) c_ras <- c(0.5, -2.3, 1.1) tkras <- ras_to_tkras(scanner_ras, c_ras)
Comment lines (starting with "#") are ignored. If a line contains "affineType:" the value is returned as the detected type.
read_affine_matrix_txt(file, type = NULL)read_affine_matrix_txt(file, type = NULL)
file |
Path to text file containing affine matrix |
type |
Optional type hint (overrides auto-detection) |
list(matrix = 4x4, type = character|NULL)
Simple image I/O using neuroim2
read_image(path)read_image(path)
path |
File path |
neuroim2 volume (DenseNeuroVol or DenseNeuroVec) or array fallback
Read an affine transform file into an Affine3DMorphism
read_linear_transform( path, format = c("generic", "fsl", "afni", "itk", "lta", "x5"), source = "source", target = "target", source_affine = NULL, target_affine = NULL, source_dim = NULL, target_dim = NULL, oblique_correction = TRUE, invert = FALSE )read_linear_transform( path, format = c("generic", "fsl", "afni", "itk", "lta", "x5"), source = "source", target = "target", source_affine = NULL, target_affine = NULL, source_dim = NULL, target_dim = NULL, oblique_correction = TRUE, invert = FALSE )
path |
Path to transform file |
format |
One of "generic", "fsl", "afni", or "itk" |
source |
Source domain id |
target |
Target domain id |
source_affine |
Source voxel-to-world affine (required for fsl) |
target_affine |
Target voxel-to-world affine (required for fsl) |
source_dim |
Optional source image dimensions for FSL handedness-aware conversion |
target_dim |
Optional target image dimensions for FSL handedness-aware conversion |
oblique_correction |
Logical; for AFNI format, apply cardinal/deoblique correction |
invert |
Logical; if TRUE, invert the read matrix before wrapping |
Affine3DMorphism
Supports single-file transforms and FSL/MCFLIRT-style indexed files
(path.000, path.001, ...).
read_linear_transform_array( path, format = c("generic", "fsl", "afni", "itk", "lta", "x5"), source = "source", target = "target", ... )read_linear_transform_array( path, format = c("generic", "fsl", "afni", "itk", "lta", "x5"), source = "source", target = "target", ... )
path |
Base file path |
format |
One of |
source |
Source domain id |
target |
Target domain id |
... |
Passed to |
A LinearTransformArray object
Read transform from file into a Morphism
read_transform( path, type = NULL, source = NULL, target = NULL, apply_affine = TRUE, ... )read_transform( path, type = NULL, source = NULL, target = NULL, apply_affine = TRUE, ... )
path |
Path or Morphism |
type |
Optional type hint: ants_h5, ants, fsl, fsl_coef, afni, x5, linear, fsl_affine, afni_affine, itk_affine, lta_affine |
source |
Optional source id |
target |
Optional target id |
apply_affine |
Logical; for ANTs H5 files, whether to include embedded affine |
... |
Passed to morphism constructors |
A Morphism or MorphismPath object
Read X5 transform file
read_x5(path)read_x5(path)
path |
Input file path |
List of X5Transform objects
Adds a loader function to the registry. Loaders are used to read warp displacement fields from various file formats.
register_loader(name, loader) register_warp_loader(name, loader)register_loader(name, loader) register_warp_loader(name, loader)
name |
Character identifier for the loader |
loader |
Function(path) -> list(array, dim, world_to_vox) |
Invisibly returns the name
# Register a custom loader my_loader <- function(path) { # Load and return list(array, dim, world_to_vox) } register_loader("my_format", my_loader)# Register a custom loader my_loader <- function(path) { # Load and return list(array, dim, world_to_vox) } register_loader("my_format", my_loader)
The fundamental resampling operation: transform coordinates via morphism, then evaluate sampler at transformed coordinates.
resample( sampler, morphism, coords, modulate = c("none", "jacobian", "sqrt_jacobian") )resample( sampler, morphism, coords, modulate = c("none", "jacobian", "sqrt_jacobian") )
sampler |
Sampler object |
morphism |
Morphism or MorphismPath |
coords |
Target coords (n x 3 matrix) or Grid |
modulate |
Jacobian modulation: "none", "jacobian", "sqrt_jacobian" |
Sampled values
# Create volume and sampler vol <- array(1:27, dim = c(3, 3, 3)) sampler <- volume_sampler(vol, affine = diag(4)) # Create identity morphism morph <- IdentityMorphism("test") # Resample at specific coordinates coords <- matrix(c(0, 0, 0, 1, 1, 1), ncol = 3, byrow = TRUE) resample(sampler, morph, coords)# Create volume and sampler vol <- array(1:27, dim = c(3, 3, 3)) sampler <- volume_sampler(vol, affine = diag(4)) # Create identity morphism morph <- IdentityMorphism("test") # Resample at specific coordinates coords <- matrix(c(0, 0, 0, 1, 1, 1), ncol = 3, byrow = TRUE) resample(sampler, morph, coords)
High-level resampling helper
resample_to(moving, target, transform, method = "linear", modulate = "none")resample_to(moving, target, transform, method = "linear", modulate = "none")
moving |
Source volume (neuroim2 or array) |
target |
Target volume or Grid |
transform |
Morphism, MorphismPath, or file path |
method |
Interpolation method |
modulate |
Jacobian modulation |
neuroim2 volume (matching target geometry)
Convenience wrapper for common volume-to-volume resampling.
resample_volume(data, morphism, target, method = "linear", modulate = "none")resample_volume(data, morphism, target, method = "linear", modulate = "none")
data |
Source volume |
morphism |
Transform |
target |
Target geometry (Grid or volume) |
method |
Interpolation method |
modulate |
Jacobian modulation |
Array with target dimensions
Plan once, apply many times: precompute target voxel centres and flatten the morphism path so repeated resampling of multiple volumes is cheap while keeping the public API small.
Project volumetric data onto surface vertices.
sample_volume_on_surface( data, morphism, surface_coords = NULL, method = "linear" )sample_volume_on_surface( data, morphism, surface_coords = NULL, method = "linear" )
data |
Source volume |
morphism |
VolToSurfMorphism |
surface_coords |
Surface vertex coordinates (optional) |
method |
Interpolation method |
Values at surface vertices
Construct sampled points
sampled_points(coords)sampled_points(coords)
coords |
Numeric matrix with 3 columns (N x 3) |
SampledPoints object
Lightweight container for point samples in world coordinates.
## S4 method for signature 'SampledPoints' show(object)## S4 method for signature 'SampledPoints' show(object)
coordsNumeric matrix (N x 3)
Samplers encapsulate data + interpolation strategy, enabling elegant composition with morphisms for resampling operations.
A Sampler wraps volumetric or surface data with an interpolation method. The core operation is: given coordinates, return interpolated values.
Resampling through a morphism is then simply:
source_coords <- transform(morphism, target_coords) values <- sampler(source_coords)
Sampler: data + interpolation encapsulation
## S4 method for signature 'Sampler' show(object)## S4 method for signature 'Sampler' show(object)
object |
A Sampler object (for show method) |
evaluateFunction: (coords) -> values
dimsInteger: data dimensions
vdimInteger: output dimensionality per point
boundsList: min/max coordinate bounds
methodCharacter: interpolation method
outsideValue for out-of-bounds queries
Mirrors the common neuroimaging convention where voxel sizes define the linear part and the image center maps to world origin.
shape_zoom_affine(shape, zooms, x_flip = TRUE, y_flip = FALSE)shape_zoom_affine(shape, zooms, x_flip = TRUE, y_flip = FALSE)
shape |
Length-N image shape |
zooms |
Length-N voxel sizes |
x_flip |
Logical; if TRUE, flip X axis (radiological-on-disk style) |
y_flip |
Logical; if TRUE, also flip Y axis (with x_flip gives DICOM style) |
4x4 affine matrix
Get source domain of a morphism
source_of(object) source_domain(object) ## S4 method for signature 'Morphism' source_of(object) ## S4 method for signature 'Morphism' source_domain(object) ## S4 method for signature 'MorphismPath' source_of(object)source_of(object) source_domain(object) ## S4 method for signature 'Morphism' source_of(object) ## S4 method for signature 'Morphism' source_domain(object) ## S4 method for signature 'MorphismPath' source_of(object)
object |
A Morphism object |
Source domain hash (character)
Construct a surface mesh
surface_mesh(vertices, faces = NULL)surface_mesh(vertices, faces = NULL)
vertices |
Numeric matrix with 3 columns (V x 3) |
faces |
Optional matrix with 3 columns (F x 3), 0- or 1-based indices |
SurfaceMesh object
Lightweight surface-to-surface resampling using precomputed sparse triplets. This keeps the core API small while enabling reusable vertex-data transport.
Computes reusable interpolation weights mapping vertex data from a moving mesh onto a reference mesh.
surface_resampling_plan( reference, moving, method = c("barycentric", "nearest"), spherical = TRUE, radius = 100 )surface_resampling_plan( reference, moving, method = c("barycentric", "nearest"), spherical = TRUE, radius = 100 )
reference |
Reference/output surface ( |
moving |
Moving/input surface ( |
method |
Interpolation method: |
spherical |
Logical; if |
radius |
Radius used when |
A SurfaceResamplingPlan object
Create a surface sampler
surface_sampler( vertices, data, faces = NULL, method = c("nearest", "barycentric") )surface_sampler( vertices, data, faces = NULL, method = c("nearest", "barycentric") )
vertices |
Vertex coordinates (V x 3), SampledPoints, or SurfaceMesh |
data |
Vertex data (length V or V x k) |
faces |
Face indices (F x 3, optional) |
method |
"nearest" or "barycentric" |
Sampler object
Lightweight mesh reference for surface operations.
## S4 method for signature 'SurfaceMesh' show(object)## S4 method for signature 'SurfaceMesh' show(object)
coordsNumeric matrix (V x 3) of vertices
facesInteger matrix (F x 3) of 0-based triangle indices
Maps between surface meshes via spherical registration.
SurfToSurfMorphism( source, target, method = c("sphere", "area", "sulc"), source_sphere = "", target_sphere = "", mapping = c("nearest", "barycentric"), source_vertices = NULL, target_vertices = NULL, faces = NULL, cost = 1, method_tag = "anatomical" )SurfToSurfMorphism( source, target, method = c("sphere", "area", "sulc"), source_sphere = "", target_sphere = "", mapping = c("nearest", "barycentric"), source_vertices = NULL, target_vertices = NULL, faces = NULL, cost = 1, method_tag = "anatomical" )
source |
Source surface domain hash |
target |
Target surface domain hash |
method |
Registration method: "sphere", "area", "sulc" |
source_sphere |
Path to source sphere surface |
target_sphere |
Path to target sphere surface |
mapping |
How to map target points onto the source mesh.
|
source_vertices |
Optional V x 3 numeric matrix of source mesh vertices.
Required for |
target_vertices |
Optional V x 3 numeric matrix of target mesh vertices.
Required for |
faces |
Optional F x 3 integer matrix of triangle vertex indices (0- or 1-based).
Required for |
cost |
Path cost (default 1.0) |
method_tag |
Method tag (default "anatomical") |
SurfToSurfMorphism object
Maps between surface meshes (e.g., native to fsaverage via spherical registration).
methodRegistration method ("sphere", "area", "sulc")
source_spherePath to source sphere surface
target_spherePath to target sphere surface
Get target domain of a morphism
target_of(object) target_domain(object) ## S4 method for signature 'Morphism' target_of(object) ## S4 method for signature 'Morphism' target_domain(object) ## S4 method for signature 'MorphismPath' target_of(object)target_of(object) target_domain(object) ## S4 method for signature 'Morphism' target_of(object) ## S4 method for signature 'Morphism' target_domain(object) ## S4 method for signature 'MorphismPath' target_of(object)
object |
A Morphism object |
Target domain hash (character)
FreeSurfer's tkregister uses a shifted coordinate system (tkRAS) that differs from scanner RAS by the c_ras offset stored in the surface header.
tkras_to_ras(tkras, c_ras)tkras_to_ras(tkras, c_ras)
tkras |
Numeric matrix (N x 3) or vector of length 3 in tkRAS |
c_ras |
Numeric vector of length 3: the c_ras offset from FreeSurfer |
Coordinates in scanner RAS
tkras <- c(0, 0, 0) c_ras <- c(0.5, -2.3, 1.1) scanner_ras <- tkras_to_ras(tkras, c_ras)tkras <- c(0, 0, 0) c_ras <- c(0.5, -2.3, 1.1) scanner_ras <- tkras_to_ras(tkras, c_ras)
Applies the coordinate pullback: given coordinates in the target domain, returns corresponding coordinates in the source domain.
transform(morphism, coords) ## S4 method for signature 'IdentityMorphism' transform(morphism, coords) ## S4 method for signature 'Affine3DMorphism' transform(morphism, coords) ## S4 method for signature 'Warp3DMorphism' transform(morphism, coords) ## S4 method for signature 'VolToSurfMorphism' transform(morphism, coords) ## S4 method for signature 'SurfToSurfMorphism' transform(morphism, coords) ## S4 method for signature 'MorphismPath' transform(morphism, coords)transform(morphism, coords) ## S4 method for signature 'IdentityMorphism' transform(morphism, coords) ## S4 method for signature 'Affine3DMorphism' transform(morphism, coords) ## S4 method for signature 'Warp3DMorphism' transform(morphism, coords) ## S4 method for signature 'VolToSurfMorphism' transform(morphism, coords) ## S4 method for signature 'SurfToSurfMorphism' transform(morphism, coords) ## S4 method for signature 'MorphismPath' transform(morphism, coords)
morphism |
A Morphism object or MorphismPath |
coords |
Matrix of coordinates (N x 3) in target domain |
Matrix of coordinates (N x 3) in source domain
# Create an affine morphism aff <- Affine3DMorphism("source_hash", "target_hash", diag(4)) coords <- matrix(c(10, 20, 30), ncol = 3) transform(aff, coords)# Create an affine morphism aff <- Affine3DMorphism("source_hash", "target_hash", diag(4)) coords <- matrix(c(10, 20, 30), ncol = 3) transform(aff, coords)
Alias for transform() to maintain neurofunctor compatibility.
transform_coords(object, coords) ## S4 method for signature 'Morphism' transform_coords(object, coords) ## S4 method for signature 'MorphismPath' transform_coords(object, coords)transform_coords(object, coords) ## S4 method for signature 'Morphism' transform_coords(object, coords) ## S4 method for signature 'MorphismPath' transform_coords(object, coords)
object |
A Morphism object |
coords |
Matrix of coordinates (N x 3) |
Transformed coordinates
Lightweight IO helpers for linear transform backends, including format factories, typed IO conditions, and array-style linear transform IO.
Apply a morphism path to coordinates using optimized warp chain.
Given a path of morphisms from source to target and coordinates in the target domain, returns the corresponding coordinates in the source domain.
transform_path(path, target_coords)transform_path(path, target_coords)
path |
List of Morphism objects ordered source -> target |
target_coords |
Numeric matrix (N x 3) of target world coords |
Numeric matrix (N x 3) of source world coords
Given a path [f: A->B, g: B->C], transform_path applies the pullback:
coords_in_C --(g pullback)--> coords_in_B --(f pullback)--> coords_in_A
The path is applied from last to first (g then f).
# Create affine morphisms aff1 <- Affine3DMorphism("native", "mni", diag(4)) aff2 <- Affine3DMorphism("mni", "template", diag(4)) path <- list(aff1, aff2) # Transform template coords to native space template_coords <- matrix(c(0, 0, 0, 10, 20, 30), ncol = 3, byrow = TRUE) native_coords <- transform_path(path, template_coords)# Create affine morphisms aff1 <- Affine3DMorphism("native", "mni", diag(4)) aff2 <- Affine3DMorphism("mni", "template", diag(4)) path <- list(aff1, aff2) # Transform template coords to native space template_coords <- matrix(c(0, 0, 0, 10, 20, 30), ncol = 3, byrow = TRUE) native_coords <- transform_path(path, template_coords)
Construct a transform file-format error condition
TransformFileError(message)TransformFileError(message)
message |
Error message |
Condition object of class TransformFileError
Construct a transform IO error condition
TransformIOError(message)TransformIOError(message)
message |
Error message |
Condition object of class TransformIOError
Checks that a path is composable (each morphism's target matches the next's source). Raises an error if the path is invalid.
validate_path(path)validate_path(path)
path |
List of Morphism objects |
Invisibly returns the path if valid
aff1 <- Affine3DMorphism("a", "b", diag(4)) aff2 <- Affine3DMorphism("b", "c", diag(4)) validate_path(list(aff1, aff2)) # OKaff1 <- Affine3DMorphism("a", "b", diag(4)) aff2 <- Affine3DMorphism("b", "c", diag(4)) validate_path(list(aff1, aff2)) # OK
Maps from volume domain to surface domain using various sampling strategies.
VolToSurfMorphism( source, target, method = c("trilinear", "ribbon", "mid_thickness", "nearest"), ribbon_inner = "", ribbon_outer = "", ribbon_inner_coords = NULL, ribbon_outer_coords = NULL, n_ribbon_samples = 6L, mid_coords = NULL, cost = 2, method_tag = "anatomical" )VolToSurfMorphism( source, target, method = c("trilinear", "ribbon", "mid_thickness", "nearest"), ribbon_inner = "", ribbon_outer = "", ribbon_inner_coords = NULL, ribbon_outer_coords = NULL, n_ribbon_samples = 6L, mid_coords = NULL, cost = 2, method_tag = "anatomical" )
source |
Volume domain hash |
target |
Surface domain hash |
method |
Sampling method: "trilinear", "ribbon", "mid_thickness", "nearest" |
ribbon_inner |
Path to inner (white) surface for ribbon sampling |
ribbon_outer |
Path to outer (pial) surface for ribbon sampling |
ribbon_inner_coords |
Pre-loaded inner surface coordinates (optional) |
ribbon_outer_coords |
Pre-loaded outer surface coordinates (optional) |
n_ribbon_samples |
Number of samples along ribbon normal |
mid_coords |
Pre-computed midpoint coordinates (optional) |
cost |
Path cost (default 2.0) |
method_tag |
Method tag (default "anatomical") |
VolToSurfMorphism object
Maps volume coordinates to surface vertices. Supports different sampling strategies (ribbon, trilinear point sampling).
methodSampling method ("ribbon", "trilinear", "nearest", "mid_thickness")
ribbon_innerPath to inner (white) surface for ribbon sampling
ribbon_outerPath to outer (pial) surface for ribbon sampling
n_ribbon_samplesNumber of samples along ribbon normal
Create a volume sampler
volume_sampler( data, affine = NULL, method = c("linear", "nearest", "cubic"), outside = NA_real_ )volume_sampler( data, affine = NULL, method = c("linear", "nearest", "cubic"), outside = NA_real_ )
data |
Numeric array (3D/4D) or volume object |
affine |
4x4 voxel-to-world (extracted if NULL) |
method |
Interpolation: "linear", "nearest", "cubic" |
outside |
Value for out-of-bounds |
domain |
Optional domain hash |
Sampler object
vol <- array(rnorm(27), dim = c(3, 3, 3)) sampler <- volume_sampler(vol, affine = diag(4)) coords <- matrix(c(1, 1, 1), ncol = 3) sampler@evaluate(coords)vol <- array(rnorm(27), dim = c(3, 3, 3)) sampler <- volume_sampler(vol, affine = diag(4)) coords <- matrix(c(1, 1, 1), ncol = 3) sampler@evaluate(coords)
Builds a Warp3DMorphism directly from a 4D field array and a grid,
without requiring an on-disk warp file.
warp_from_field( source, target, field, grid = NULL, representation = c("displacements", "deformations"), warp_method = c("linear", "cubic"), cost = 1.5, method_tag = "anatomical", id = NULL )warp_from_field( source, target, field, grid = NULL, representation = c("displacements", "deformations"), warp_method = c("linear", "cubic"), cost = 1.5, method_tag = "anatomical", id = NULL )
source |
Source domain id |
target |
Target domain id |
field |
Numeric array with dims |
grid |
Grid describing voxel geometry. If |
representation |
Either |
warp_method |
Interpolation method for warp lookup |
cost |
Path cost |
method_tag |
Method tag |
id |
Optional stable id for the in-memory warp payload |
Warp3DMorphism
Pluggable loader system for warp displacement fields. Provides a registry for different file formats (NIfTI via neuroim2, AFNI, FSL, ANTs H5) with morphism-level caching.
A loader function must accept a file path and return a list with:
array: Numeric vector of displacement values (flattened 3 x X x Y x Z)
dim: Integer vector c(X, Y, Z)
world_to_vox: 4x4 matrix mapping world coords to voxel indices
Represents a nonlinear warp field transformation.
Warp3DMorphism( source, target, warp_path, warp_type = c("ants", "ants_h5", "fsl", "fsl_coef", "afni", "freesurfer", "dense"), inverse_path = "", def_type = NULL, warp_method = c("linear", "cubic"), cost = 1.5, method_tag = "anatomical" )Warp3DMorphism( source, target, warp_path, warp_type = c("ants", "ants_h5", "fsl", "fsl_coef", "afni", "freesurfer", "dense"), inverse_path = "", def_type = NULL, warp_method = c("linear", "cubic"), cost = 1.5, method_tag = "anatomical" )
source |
Source domain hash |
target |
Target domain hash |
warp_path |
Path to displacement field file |
warp_type |
One of "ants", "ants_h5", "fsl", "fsl_coef", "afni", "freesurfer", "dense" |
inverse_path |
Path to inverse warp (optional) |
def_type |
Deformation type: "relative" (displacement) or "absolute" (coordinates) |
warp_method |
Interpolation method for warp field lookup: "linear" or "cubic" |
cost |
Path cost (default 1.5) |
method_tag |
Method tag (default "anatomical") |
Warp3DMorphism object
warp <- Warp3DMorphism("native", "mni", "path/to/warp.nii.gz")warp <- Warp3DMorphism("native", "mni", "path/to/warp.nii.gz")
Represents a nonlinear warp field transformation (e.g., ANTs SyN, FSL FNIRT). Stores metadata; the actual warp field is loaded on demand.
warp_pathPath to the warp field file
warp_typeType of warp ("ants", "ants_h5", "fsl", "fsl_coef", "afni", "freesurfer", "dense")
inverse_pathPath to inverse warp (if available)
Write a 4x4 affine matrix to a text file
write_affine_matrix_txt(matrix, file, type = NULL, comment = TRUE)write_affine_matrix_txt(matrix, file, type = NULL, comment = TRUE)
matrix |
4x4 numeric affine matrix |
file |
Output file path |
type |
Optional type label to write as comment |
comment |
Logical; if TRUE, write type as comment header |
Invisibly returns the file path
Write image using neuroim2
write_image(x, path)write_image(x, path)
x |
neuroim2 volume or array |
path |
Output path |
Write an affine transform to disk
write_linear_transform( x, path, format = c("generic", "fsl", "afni", "itk", "lta", "x5"), source_affine = NULL, target_affine = NULL, source_dim = NULL, target_dim = NULL, oblique_correction = TRUE, invert = FALSE )write_linear_transform( x, path, format = c("generic", "fsl", "afni", "itk", "lta", "x5"), source_affine = NULL, target_affine = NULL, source_dim = NULL, target_dim = NULL, oblique_correction = TRUE, invert = FALSE )
x |
Affine3DMorphism or 4x4 matrix (internal pullback convention) |
path |
Output file path |
format |
One of "generic", "fsl", "afni", or "itk" |
source_affine |
Source voxel-to-world affine (required for fsl) |
target_affine |
Target voxel-to-world affine (required for fsl) |
source_dim |
Optional source image dimensions for FSL handedness-aware conversion |
target_dim |
Optional target image dimensions for FSL handedness-aware conversion |
oblique_correction |
Logical; for AFNI format, apply cardinal/deoblique correction |
invert |
Logical; if TRUE, invert before writing |
Invisibly returns path
Write a series of linear transforms
write_linear_transform_array( x, path, format = c("generic", "fsl", "afni", "itk", "lta", "x5"), ... )write_linear_transform_array( x, path, format = c("generic", "fsl", "afni", "itk", "lta", "x5"), ... )
x |
A |
path |
Base output path |
format |
One of |
... |
Passed to |
Invisibly returns written path(s)
Convenience wrapper around write_linear_transform() for affine morphisms
and raw 4x4 matrices. For Warp3DMorphism, writes a NIfTI vector field.
write_transform(x, path, type = NULL, ...)write_transform(x, path, type = NULL, ...)
x |
Affine3DMorphism, Warp3DMorphism, or 4x4 numeric matrix |
path |
Output file path |
type |
Optional output type:
|
... |
Passed to |
Invisibly returns path
Write a warp morphism as a NIfTI vector field
write_warp_field( x, path, representation = c("auto", "displacements", "deformations") )write_warp_field( x, path, representation = c("auto", "displacements", "deformations") )
x |
Warp3DMorphism |
path |
Output NIfTI path |
representation |
Output representation: |
Invisibly returns path
Write X5 transform file
write_x5(path, x5_list)write_x5(path, x5_list)
path |
Output file path |
x5_list |
List of |
Invisibly returns path
Create an X5 domain descriptor
x5_domain(grid, size, mapping = NULL, coordinates = NULL)x5_domain(grid, size, mapping = NULL, coordinates = NULL)
grid |
Logical |
size |
Integer vector |
mapping |
Optional matrix |
coordinates |
Optional coordinate kind string |
An X5Domain object
Create an X5 transform descriptor
x5_transform( type, transform, subtype = NULL, representation = NULL, metadata = NULL, dimension_kinds = NULL, domain = NULL, inverse = NULL, jacobian = NULL, additional_parameters = NULL, array_length = 1L )x5_transform( type, transform, subtype = NULL, representation = NULL, metadata = NULL, dimension_kinds = NULL, domain = NULL, inverse = NULL, jacobian = NULL, additional_parameters = NULL, array_length = 1L )
type |
|
transform |
Numeric array of transform parameters |
subtype |
Optional subtype |
representation |
Optional representation label |
metadata |
Optional named list or JSON string |
dimension_kinds |
Optional character vector |
domain |
Optional |
inverse |
Optional inverse array |
jacobian |
Optional Jacobian array |
additional_parameters |
Optional array |
array_length |
Integer array length |
An X5Transform object