nat.fastcore (R)¶
R bindings for the fastcore Rust core, built with
extendr. Intended for use alongside
nat and the rest of the natverse, though the functions
themselves are generic and don't depend on it.
Install¶
Pre-compiled binaries for Windows and macOS are served from R-universe, so no Rust toolchain is required:
install.packages(
"nat.fastcore",
repos = c("https://schlegelp.r-universe.dev", "https://cloud.r-project.org")
)
On Linux this installs from source (compiling the bundled Rust), which needs the Rust toolchain.
Building from source
- Clone the repository
- Make sure the Rust toolchain and the R
rextendr&devtoolspackages are installed - In R, run:
For development, cd into R/nat.fastcore/ and run:
Usage¶
Unlike the Python bindings, nat.fastcore works on an explicit parent-index
vector rather than node/parent IDs — build one with node_indices and pass it
to everything else.
library(nat.fastcore)
# Load a single skeleton
s = read.neurons('test.swc')[[1]]
# Generate node indices from node -> parent IDs
parents = node_indices(s$d$PointNo, s$d$Parent)
# Find distances to roots
all_dists_to_root(parents, sources=NULL, weights=NULL)
#> [1] 0 47 48 49 50 51 ...
# Calculate child -> parent distances
weights = child_to_parent_dists(parents, s$d$X, s$d$Y, s$d$Z)
# Generate all-by-all geodesic distance matrix
dists = geodesic_distances(parents, sources=NULL, targets=NULL, weights=weights, directed=F)
Healing a fragmented skeleton (reconnecting its disconnected fragments):
healed = heal_skeleton(parents, s$d$X, s$d$Y, s$d$Z, method="ALL",
max_dist=NULL, min_size=NULL, mask=NULL,
radius=NULL, use_radius=FALSE)
# ... optionally taking node radii into account, which prefers to connect
# fragments of similar calibre (higher `use_radius` = more influence)
healed = heal_skeleton(parents, s$d$X, s$d$Y, s$d$Z, method="ALL",
max_dist=NULL, min_size=NULL, mask=NULL,
radius=s$d$W, use_radius=TRUE)
Available functions¶
Skeleton / tree (DAG)
node_indices: turn node and parent IDs into parent indicesgeodesic_distances: geodesic distances between all/subsets of nodesgeodesic_pairs: geodesic distances for explicit pairs of nodesgeodesic_nearest: distance to the nearest target for each source (no full matrix)geodesic_farthest: distance to the farthest target for each source (no full matrix)strahler_index: calculate the Strahler indexsubtree_height: distance from each node down to the farthest leaf below itconnected_components: extract connected componentsclassify_nodes: classify nodes into roots, leaves, branch points and slabsall_dists_to_root: distances from all/subsets of nodes to the rootdist_to_root: distance from a single node to the rootprune_twigs: prune twigs under a given size thresholdgenerate_segments/break_segments: split the tree into linear segmentssynapse_flow_centrality: synapse flow centrality per nodehas_cycles: check whether a tree contains cycleschild_to_parent_dists: helper to calculate child -> parent distancesheal_skeleton: reconnect the fragments of a broken skeletonstitch_fragments: find the minimal-length edges that reconnect fragmentsreroot_rewire: regenerate a parent vector after adding edges
Mesh
mesh_connected_components: connected components of a triangle mesh
Neuron similarity (NBLAST / synNBLAST) — see Concepts › NBLAST
nblast/nblast_allbyall: forward NBLAST (query-vs-target / all-by-all)nblast_pairs: forward NBLAST for a set of(query, target)index pairssynblast/synblast_allbyall: synapse-based NBLASTsmat_auto_limit: thelimit_dist="auto"value for a scoring matrix
CMTK transforms — see CMTK transforms for the full story
cmtk_read: read a CMTK.listregistration (or a chain of them)cmtk_xform/cmtk_xform_inv: apply it to points, forwards / backwardscmtk_affine,cmtk_domain,cmtk_dims,cmtk_spacing,cmtk_versions: properties
CMTK itself does not need to be installed — no shelling out to streamxform:
reg <- cmtk_read("JFRC2_FCWB.list")
n <- Cell07PNs[[1]]
xyzmatrix(n) <- cmtk_xform(reg, xyzmatrix(n))
# points outside the registration's domain come back as NaN, exactly as CMTK
# reports them as FAILED
Direction is chosen per call, so one object serves both ways round and the file is parsed
once. invert is per hop — unlike cmtk_xform_inv, which reverses the whole chain — so
it is the only way to express a mixed-direction traversal:
back <- cmtk_xform(reg, pts, invert = TRUE) # same parse, other direction
chain <- cmtk_read(c("A_B.list", "C_B.list")) # A -> B -> C, 2nd stored as C->B
mixed <- cmtk_xform(chain, pts, invert = c(FALSE, TRUE))
Elastix transforms — see Elastix transforms for the full story
elastix_read: read aTransformParametersfile (its initial-transform chain is followed automatically, however deep)elastix_xform/elastix_xform_inv: apply it to points, forwards / backwardselastix_probe_invertible: can it be inverted? Answered without reading the coefficients — ~20x faster than a full read, for labelling many files at onceelastix_affine,elastix_kinds,elastix_grid_size,elastix_grid_spacing,elastix_grid_origin: properties
Elastix itself does not need to be installed — no shelling out to transformix:
xf <- elastix_read("TransformParameters.FixedFANC.txt")
xyzmatrix(n) <- elastix_xform(xf, xyzmatrix(n))
# NB the opposite convention to CMTK: points outside the control-point grid come back
# *unchanged*, which is what Elastix does. Pass out_of_bounds = "nan" to see the boundary.
back <- elastix_xform_inv(xf, xyzmatrix(n)) # Elastix itself cannot invert at all
As with CMTK, direction is chosen per call — elastix_xform(xf, pts, invert = TRUE) — so a
transform and its inverse share one parse. That matters when the warp is tens of megabytes.
Function reference¶
Per-function documentation is generated from the package's roxygen docs and published by R-universe:
nat.fastcore reference on R-universe
From R, the usual ?geodesic_distances works too.
Differences from the Python bindings
prune_twigs has no mask argument in R (extendr cannot take a Vec<bool>).
Conversely, R exposes several functions that Python keeps internal or folds
into keyword arguments — node_indices, child_to_parent_dists,
all_dists_to_root, dist_to_root, has_cycles, reroot_rewire,
nblast_pairs, synblast_allbyall and smat_auto_limit. See the
capability matrix.