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.
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.
sphere <- spherical_roi(vol, c(20,20,20), radius=5, fill=100, use_cpp=FALSE)
#>
#> ROIVol Object
#>
#> Properties:
#> Dimensions: 11 x 3
#> ROI Points: 11
#> Value Range: [100.00, 100.00]
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.
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.
vox <- coord_to_grid(vol, rpoint)
sphere <- spherical_roi(vol, vox, radius=10, fill=1)
dim(coords(sphere))
#> [1] 85 3
Now we convert back to real-world coordinates
coords <- index_to_coord(vol, indices(sphere))
center_of_mass <- colMeans(coords)
center_of_mass
#> [1] -36.75 -22.75 14.80
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.
sphere <- spherical_roi(vol, c(50,10,10), radius=10, fill=1)
sphere
#>
#> ROIVol Object
#>
#> Properties:
#> Dimensions: 85 x 3
#> ROI Points: 85
#> Value Range: [1.00, 1.00]
Now we construct a SparseNeuroVol
and fill it with the
values stored in the ROI:
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.
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.
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:
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:
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.
pset <- patch_set(vol, dims=c(3,3,1))
length(pset)
#> [1] 102400
ret <- pset %>% purrr::map(~ mean(.))
Now we limit patches so that the set of patch centers are within a mask.