Nothing
#' @noRd
#' @keywords internal
read_surface_coordinates <- function(path) {
ext <- tools::file_ext(path)
if (ext == "gii" || grepl("\\.surf\\.gii$", path)) {
g <- gifti::read_gifti(path)
g$data[[1]]
} else {
cli::cli_abort("Unsupported surface file format: {.file {path}}")
}
}
#' @noRd
#' @keywords internal
compute_distance_matrix <- function(coords,
method = c("euclidean", "geodesic"),
faces = NULL) {
method <- match.arg(method)
if (is.list(coords) && !is.null(coords$lh) && !is.null(coords$rh)) {
coords <- rbind(coords$lh, coords$rh)
}
if (!is.matrix(coords) || ncol(coords) != 3) {
cli::cli_abort("{.arg coords} must be a matrix with 3 columns (x, y, z).")
}
if (method == "geodesic") {
if (is.null(faces)) {
cli::cli_abort("{.arg faces} is required for geodesic distance.")
}
get_surface_distance(coords, faces)
} else {
stats::dist(coords) |> as.matrix()
}
}
#' @noRd
#' @keywords internal
compute_knn <- function(distmat, k) {
n <- nrow(distmat)
k <- min(k, n - 1L)
indices <- matrix(0L, nrow = n, ncol = k)
distances <- matrix(0, nrow = n, ncol = k)
for (i in seq_len(n)) {
d <- distmat[i, ]
d[i] <- Inf
top_k <- order(d)[seq_len(k)]
indices[i, ] <- top_k
distances[i, ] <- d[top_k]
}
list(indices = indices, distances = distances)
}
#' @noRd
#' @keywords internal
validate_data <- function(data, arg = "data") {
if (!is.numeric(data)) {
cli::cli_abort("{.arg {arg}} must be numeric.")
}
if (anyNA(data)) {
cli::cli_abort("{.arg {arg}} must not contain NA values.")
}
invisible(data)
}
#' @noRd
#' @keywords internal
validate_distmat <- function(distmat, n, arg = "distmat") {
if (!is.matrix(distmat)) {
cli::cli_abort("{.arg {arg}} must be a matrix.")
}
if (nrow(distmat) != n || ncol(distmat) != n) {
cli::cli_abort(
"{.arg {arg}} must be {n} x {n}, got {nrow(distmat)} x {ncol(distmat)}."
)
}
invisible(distmat)
}
#' Read vertex/voxel values from a brain map file
#'
#' Reads GIFTI (`.func.gii`) or NIfTI (`.nii.gz`) files and returns the
#' values as a numeric vector. Used internally by [compare_maps()] when
#' file paths are passed instead of numeric vectors.
#'
#' @param path Path to a `.func.gii` (GIFTI) or `.nii.gz` (NIfTI) file.
#'
#' @return A numeric vector of map values.
#' @examples
#' \dontrun{
#' read_brain_map_values("cortical_thickness.func.gii")
#' read_brain_map_values("brain_volume.nii.gz")
#' }
#' @export
read_brain_map_values <- function(path) {
if (grepl("\\.surf\\.gii$", path, ignore.case = TRUE)) {
cli::cli_abort(c(
"{.file {path}} is a surface geometry file, not a data file.",
"i" = "Expected a {.file .func.gii} or {.file .label.gii} file."
))
}
if (grepl("\\.gii$", path, ignore.case = TRUE)) {
gii <- gifti::read_gifti(path)
return(as.numeric(gii$data[[1]]))
}
ext <- tolower(tools::file_ext(path))
if (ext == "gz" || ext == "nii") {
rlang::check_installed("RNifti", reason = "to read NIfTI volume files")
img <- RNifti::readNifti(path)
return(as.numeric(img))
}
cli::cli_abort("Unsupported file format: {.file {path}}")
}
#' @noRd
#' @keywords internal
validate_coords <- function(coords) {
if (!is.list(coords) || is.null(coords$lh) || is.null(coords$rh)) {
cli::cli_abort(paste(
"{.arg coords} must be a list with",
"{.field $lh} and {.field $rh} matrices."
))
}
if (!is.matrix(coords$lh) || ncol(coords$lh) != 3) {
cli::cli_abort("{.field coords$lh} must be a matrix with 3 columns.")
}
if (!is.matrix(coords$rh) || ncol(coords$rh) != 3) {
cli::cli_abort("{.field coords$rh} must be a matrix with 3 columns.")
}
invisible(coords)
}
#' @noRd
#' @keywords internal
validate_parcellation <- function(labels, n) {
if (!is.numeric(labels) && !is.integer(labels)) {
cli::cli_abort("{.arg parcellation} must be an integer or numeric vector.")
}
if (length(labels) != n) {
cli::cli_abort(paste(
"{.arg parcellation} length ({length(labels)})",
"must match data length ({n})."
))
}
invisible(labels)
}
#' @noRd
#' @keywords internal
neuromaps_cache_dir <- function() {
dir <- getOption(
"neuromapr.data_dir",
Sys.getenv("NEUROMAPR_DATA_DIR", unset = "")
)
if (nzchar(dir)) return(dir)
tools::R_user_dir("neuromapr", "cache")
}
#' @noRd
#' @keywords internal
validate_checksum <- function(file, expected) {
if (is.null(expected) || !nzchar(expected)) return(TRUE)
actual <- unname(tools::md5sum(file))
identical(actual, expected)
}
#' @noRd
#' @keywords internal
parse_neuromaps_filename <- function(fname) {
base <- sub("_feature\\..*$", "", fname)
ext <- sub("^.*_feature", "", fname)
pairs <- strsplit(base, "_")[[1]]
result <- list()
for (pair in pairs) {
parts <- strsplit(pair, "-", fixed = TRUE)[[1]]
if (length(parts) == 2) {
result[[parts[1]]] <- parts[2]
}
}
result$ext <- ext
result
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.