--- title: "Getting Started with haze" author: "Tim Schäfer" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Getting Started with haze} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ## Introduction `haze` provides fast smoothing of per-vertex data on triangular meshes, along with utility functions for mesh manipulation and data interpolation. The smoothing is implemented in C++ and supports parallel processing for multiple overlays. ## Smoothing Per-Vertex Data The main workhorse is `pervertexdata.smoothnn()`, which performs nearest-neighbor smoothing using the $k$-ring neighborhood of each vertex. ```{r} library("haze") # Load a FreeSurfer mesh and per-vertex data mesh <- freesurferformats::read.fs.surface( system.file("extdata", "fsaverage_mesh_lh_white", package = "haze", mustWork = TRUE)) thickness <- freesurferformats::read.fs.morph( system.file("extdata", "fsaverage_lh_thickness", package = "haze", mustWork = TRUE)) # Smooth: k=2 neighborhood, 300 iterations smoothed <- pervertexdata.smoothnn(mesh, thickness, num_iter = 300L, k = 2L) ``` ## Re-Using the Mesh Neighborhood When smoothing many datasets on the same mesh, pre-compute the adjacency list once with `mesh.adj()` and then use `pervertexdata.smoothnn.adj()`: ```{r} mesh_adj <- mesh.adj(mesh, k = 1L) ``` This adjacency can be reused: ```{r} data1 <- rnorm(length(mesh_adj), mean = 1.0, sd = 0.1) data2 <- rnorm(length(mesh_adj), mean = 5.0, sd = 0.1) smoothed1 <- pervertexdata.smoothnn.adj(mesh_adj, data1, num_iter = 15L) smoothed2 <- pervertexdata.smoothnn.adj(mesh_adj, data2, num_iter = 15L) ``` Multiple overlays (as a matrix, one per row) are automatically smoothed in parallel: ```{r} pvd <- rbind(data1, data2) options("mc.cores" = 2L) smoothed_pvd <- pervertexdata.smoothnn.adj(mesh_adj, pvd, num_iter = 15L) ``` ## Creating Sub-Meshes Use `submesh.vertex()` to extract a patch of a mesh defined by vertex indices: ```{r} # Extract a sub-mesh of the first 1000 vertices small_mesh <- submesh.vertex(mesh, old_vertex_indices_to_use = 1:1000) ``` ## Working with k-d Trees `find_nv_kdtree()` finds the nearest mesh vertex for given query coordinates: ```{r} query_points <- matrix(c(0, 0, 0, 10, 10, 10), ncol = 3, byrow = TRUE) nearest_vertex_idx <- find_nv_kdtree(query_points, mesh) ``` `nn_interpolate_kdtree()` assigns per-vertex data to query points via nearest-neighbor lookup, while `linear_interpolate_kdtree()` performs linear interpolation — useful for mapping morphometry data between subjects with aligned spherical meshes. ## Mesh Conversion Utilities Convert between FreeSurfer surfaces and `rgl` `tmesh3d` objects using the internal utilities `haze:::fs.surface.to.tmesh3d()` and `haze:::tmesh3d.to.fs.surface()`: ```{r} tmesh <- haze:::fs.surface.to.tmesh3d(mesh) fs_surface <- haze:::tmesh3d.to.fs.surface(tmesh) ``` ## Further Reading - Full API reference: [dfsp-spirit.github.io/haze/reference/](https://dfsp-spirit.github.io/haze/reference/) - Run `example()` in R for interactive demos of any function.