Skip to contents

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:

    sparsevol <- SparseNeuroVol(sphere, space(vol),indices=indices(sphere))
    sum(sparsevol) == sum(sphere)
#> [1] TRUE
    all(dim(sparsevol) == dim(vol))
#> [1] TRUE

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 lists 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.

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:


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.


pset <- patch_set(vol, dims=c(3,3,1), mask=as.logical(vol))
length(pset)
#> [1] 29532
ret <- pset %>% purrr::map(~ mean(.))