--- title: "Regions of Interest" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Regions of Interest} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, echo = FALSE, message = FALSE} knitr::opts_chunk$set(collapse = T, comment = "#>") library(assertthat) library(purrr) library(neuroim2) options(mc.cores=1) ``` Regions of interest =================== ## Creating a spherical ROI In **neuroim2** there is basic support for creating regions of interest (ROI). To create a spherical ROI around a central point, we need an existing object of type `NeuroVol` or `NeuroSpace`. To create a spherical region of interest with a 5mm radius around a central voxel at i=20, j=20, k=20, we first read in an image. ```{r} library(neuroim2) file_name <- system.file("extdata", "global_mask2.nii.gz", package="neuroim2") vol <- read_vol(file_name) ``` Next, we create a spherical ROI centered around voxel coordinates [20,20,20] with a 5mm radius, filling all values in the ROI with 100. ```{r} sphere <- spherical_roi(vol, c(20,20,20), radius=5, fill=100, use_cpp=FALSE) ``` ```{r, echo=FALSE} sphere ``` ## Creating a Spherical ROI around a real-valued coordinate To create a spherical ROI centered around a real coordinate in millimeters, we need to first convert the real-valued coordinates to a voxel-based coordinate. Suppose our real-world coordinate is at -50, -28, 10 in coordinate space. ```{r} rpoint <- c(-34,-28,10) ``` Because the function `spherical_roi` takes a coordinate in *voxel units*, we need to convert the real-world coordinate (i.e. in millimeter units) to voxel coordinates. ```{r} vox <- coord_to_grid(vol, rpoint) sphere <- spherical_roi(vol, vox, radius=10, fill=1) dim(coords(sphere)) ``` Now we convert back to real-world coordinates ```{r} coords <- index_to_coord(vol, indices(sphere)) center_of_mass <- colMeans(coords) center_of_mass ``` ## Converting an ROI to a SparseNeuroVol We may want to convert a region of interest to a NeuroVol instance. But we don't want to store every value in a dense array. Here we can make use of the `SparseNeuroVol` class which only stores non-zero values my using a `Matrix::sparseVector` under the hood. ```{r} sphere <- spherical_roi(vol, c(50,10,10), radius=10, fill=1) sphere ``` Now we construct a `SparseNeuroVol` and fill it with the values stored in the ROI: ```{r} sparsevol <- SparseNeuroVol(sphere, space(vol),indices=indices(sphere)) sum(sparsevol) == sum(sphere) all(dim(sparsevol) == dim(vol)) ``` ## Carrying out simple "searchlight" ROI analyses The so-called roving "searchlight" is often used to perform multivariate statistical analyses in a local neighborhood of each voxel of an image. Several functions in `neuroim2` can be used to carry out searchlight analyses. These functions produces `list`s of the `ROIVol` instances that encapsulate the local neighborhood around each voxel. Here, we compute the mean value in an exhaustive set of spherical searchlights in an image volume. ```{r} library(purrr) ## generate a list of searchlight ROIs slist <- searchlight(vol, eager=TRUE, radius=8) ## compute the mean value in each searchlight ROI. ret <- slist %>% purrr::map(~ mean(vol[coords(.)])) ``` We can also use a "randomized searchlight", which samples voxels without replacement until all voxels have been included in at least one searchlight. ```{r} ret <- vol %>% random_searchlight(radius=8) %>% purrr::map(~ mean(vol[coords(.)])) ``` Another related method involves using a "parcellation" or clustering to define successive regions of interest for an analysis. Here we show how to do this in a similar way as above. First we must define a 'clustering' over the voxel space: ```{r} grid <- index_to_coord(vol, which(vol > 0)) kres <- kmeans(grid, centers=50, iter.max=500) ``` Now we create a `ClusteredNeuroVol` and map the `mean` function over all clusters: ```{r} kvol <- ClusteredNeuroVol(vol, kres$cluster) ret <- vol %>% clustered_searchlight(cvol=kvol) %>% purrr::map(~ mean(vol[coords(.)])) ``` ## Working with image patches Another type of ROI analysis, similar to the 'searchlight', involves working with sets of square or cuboid image "patches". The `patch_set` function can be used to generate a set of equally-sized patches that span the image space (or some mask covering the space). The patches are guaranteed to be of equal size. This means that at edges, 'patches' will be padded out with the value at the image extremes. Here we create a patch set consistting of 3 by 3 by 1 square patches that span the image. ```{r} pset <- patch_set(vol, dims=c(3,3,1)) length(pset) ret <- pset %>% purrr::map(~ mean(.)) ``` Now we limit patches so that the set of patch centers are within a mask. ```{r} pset <- patch_set(vol, dims=c(3,3,1), mask=as.logical(vol)) length(pset) ret <- pset %>% purrr::map(~ mean(.)) ```