Working with neuroimaging time-series data
The neuroim2
package contains data structures and
functions for reading, accessing, and processing 4-dimensional
neuroimaging data.
Reading a four-dimensional NifTI image with read_vec
Here we read in a 4D image consisting of 5 time points,
library(purrr)
library(ggplot2)
file_name <- system.file("extdata", "global_mask_v4.nii", package="neuroim2")
vec <- read_vec(file_name)
dim(vec)
#> [1] 64 64 25 4
vec
#>
#> DenseNeuroVec (3.13 bytes MB)
#>
#> - Spatial Info ---------------------------
#> | Dimensions : 64 x 64 x 25 (4 timepoints)
#> | Total Voxels : 102,400
#> | Spacing : 3.5 x 3.5 x 3.7
#>
#> - Properties ---------------------------
#> | Origin : 112 x -108 x -46.2
#> | Orientation : Right-to-Left Posterior-to-Anterior Inferior-to-Superior
#>
#> - Statistics ---------------------------
#> Mean +/- SD : 0.288 +/- 0.453
#>
#> Label: /home/runner/work/_temp/Library/neuroim2/extdata/global_mask_v4.nii
Now imagine we have a set of 4d images. We can read them in with
read_vec
. (Here we are just using three versions of the
same file for the example).
file_name <- system.file("extdata", "global_mask_v4.nii", package="neuroim2")
vec <- read_vec(c(file_name, file_name, file_name))
dim(vec)
#> [1] 64 64 25 12
vec2 <- read_vec(rep(file_name, 10))
vec2
#>
#> NeuroVecSeq (10 vectors)
#>
#> += Sequence Info ---------------------------
#> | Length : 10
#> | Total Time : 40 points
#>
#> += Spatial Info ---------------------------
#> | Dimensions : 64 x 64 x 25
#> | Spacing : 3.5 x 3.5 x 3.7
#> | Origin : 112 x -108 x -46.2
#> | Orientation : Right-to-Left Posterior-to-Anterior Inferior-to-Superior
#>
#> += Vector Details --------------------------
#> 1. DenseNeuroVec (4 timepoints)
#> 2. DenseNeuroVec (4 timepoints)
#> 3. DenseNeuroVec (4 timepoints)
#> 4. DenseNeuroVec (4 timepoints)
#> 5. DenseNeuroVec (4 timepoints)
#> 6. DenseNeuroVec (4 timepoints)
#> 7. DenseNeuroVec (4 timepoints)
#> 8. DenseNeuroVec (4 timepoints)
#> 9. DenseNeuroVec (4 timepoints)
#> 10. DenseNeuroVec (4 timepoints)
To extract a subset of volumes we can use the sub_vector
function:
vec_1_6 <- sub_vector(vec, 1:6)
dim(vec_1_6)
#> [1] 64 64 25 6
vec_1_6
#>
#> NeuroVecSeq (2 vectors)
#>
#> += Sequence Info ---------------------------
#> | Length : 2
#> | Total Time : 6 points
#>
#> += Spatial Info ---------------------------
#> | Dimensions : 64 x 64 x 25
#> | Spacing : 3.5 x 3.5 x 3.7
#> | Origin : 112 x -108 x -46.2
#> | Orientation : Right-to-Left Posterior-to-Anterior Inferior-to-Superior
#>
#> += Vector Details --------------------------
#> 1. DenseNeuroVec (4 timepoints)
#> 2. DenseNeuroVec (2 timepoints)
Extracting time-series data using the series
and
series_roi
functions
To get the time-series at voxel (1,1,1) we can use the
series
function:
series(vec_1_6, 1,1,1)
#> [1] 0 0 0 0 0 0
We can extract a 4d region of interest with the
series_roi
as follows:
file_name <- system.file("extdata", "global_mask_v4.nii", package="neuroim2")
vol <- read_vol(file_name)
roi <- spherical_roi(vol, c(12,12,12), radius=8)
rvec1 <- series_roi(vec, roi)
## or alternatively as a pipeline
rvec2 <- read_vol(file_name) %>% spherical_roi(c(12,12,12), radius=8) %>% series_roi(vec,.)
rvec2
#>
#> === ROIVec Object ===
#>
#> - Structure
#> Points: 49
#> Features: 3 (147 total)
#> Memory: 12.7 Kb
#>
#> - Spatial Properties
#> Parent Space: 64 x 64 x 25 x 12
#> Centroid: [13.0, 13.0, 13.0 mm]
#>
#> - Value Properties
#> Range: [0.00, 0.00]
#>
#> ======================================
#>
#> Access Methods:
#> . Get Points: coords(object)
#> . Get Values: as.matrix(object)
#> . Subset: object[1:10, ]
## we can extract the ROI values with the `values` method.
assertthat::assert_that(all(values(rvec1) == values(rvec2)))
#> [1] TRUE
assertthat::assert_that(all(coords(rvec1) == coords(rvec2)))
#> [1] TRUE
We can also extract an ROI using 1d indices:
r1 <- series_roi(vec, 1:100)
r1
#>
#> === ROIVec Object ===
#>
#> - Structure
#> Points: 100
#> Features: 3 (300 total)
#> Memory: 17.5 Kb
#>
#> - Spatial Properties
#> Parent Space: 64 x 64 x 25 x 12
#> Centroid: [27.5, 1.4, 1.0 mm]
#>
#> - Value Properties
#> Range: [0.00, 0.00]
#>
#> ======================================
#>
#> Access Methods:
#> . Get Points: coords(object)
#> . Get Values: as.matrix(object)
#> . Subset: object[1:10, ]
Or we can extract a plain matrix using the series
function:
We can also use coordinate indexing using voxel coordinates. First we load a binary mask with the same spatial dimensions as our NeuroVec:
mask <- read_vol(system.file("extdata", "global_mask_v4.nii", package="neuroim2"))
Now we convert indices to voxels and extract a matrix of values at the specified locations:
vox <- index_to_grid(mask, 1:100)
r3 <- series(vec, vox)
dim(r3)
#> [1] 12 100
And the same using series_roi
:
r4 <- series_roi(vec,vox)
r4
#>
#> === ROIVec Object ===
#>
#> - Structure
#> Points: 100
#> Features: 3 (300 total)
#> Memory: 18.7 Kb
#>
#> - Spatial Properties
#> Parent Space: 64 x 64 x 25 x 12
#> Centroid: [27.5, 1.4, 1.0 mm]
#>
#> - Value Properties
#> Range: [0.00, 0.00]
#>
#> ======================================
#>
#> Access Methods:
#> . Get Points: coords(object)
#> . Get Values: as.matrix(object)
#> . Subset: object[1:10, ]