The NiftiArray
package is under development please check back later!
The goal of NiftiArray
is to allow for memory efficient fast random
access of NIfTI objects. NiftiArray
is an R package that allows for
convenient and memory-efficient containers for on-disk representation of
NIfTI objects. We allow for DelayedArray
extensions and support all
operations supported by DelayedArray objects. These operations can be
either delayed or block-processed.
You can find a package vignette here.
You can install the development version of NiftiArray
from
GitHub with:
# install.packages('remotes')
remotes::install_github("muschellij2/NiftiArray")
We are working to get a stable version on Neuroconductor.
Here we use the example image from RNifti
. We use the
writeNiftiArray
function to create a NiftiArray
object:
library(NiftiArray)
nii_fname = system.file("extdata", "example.nii.gz", package = "RNifti")
res = writeNiftiArray(nii_fname)
class(res)
#> [1] "NiftiArray"
#> attr(,"package")
#> [1] "NiftiArray"
dim(res)
#> [1] 96 96 60
res
#> <96 x 96 x 60> NiftiArray object of type "integer":
#> ,,1
#> [,1] [,2] [,3] [,4] ... [,93] [,94] [,95] [,96]
#> [1,] 0 0 0 0 . 0 0 0 0
#> [2,] 0 0 0 0 . 0 0 0 0
#> ... . . . . . . . . .
#> [95,] 0 0 0 0 . 0 0 0 0
#> [96,] 0 0 0 0 . 0 0 0 0
#>
#> ...
#>
#> ,,60
#> [,1] [,2] [,3] [,4] ... [,93] [,94] [,95] [,96]
#> [1,] 0 0 0 0 . 0 0 0 0
#> [2,] 0 0 0 0 . 0 0 0 0
#> ... . . . . . . . . .
#> [95,] 0 0 0 0 . 0 0 0 0
#> [96,] 0 0 0 0 . 0 0 0 0
We can see the file on disk that was written out:
res@seed@filepath
#> [1] "/private/var/folders/sq/x3htb34928bfn79jk3qksqg56zmf39/T/Rtmp0WocfN/file1585a6fe4f86b.h5"
We see that the object is a low-memory DelayedArray
:
object.size(res)
#> 8912 bytes
You can also simply use the NiftiArray
function of the NIfTI filename
to create the array:
res = NiftiArray(nii_fname)
We see the header information is encoded in the seed
slot of the
object, which can be accessed using the nifti_header
function:
nifti_header(res)
#> NIfTI-1 header
#> sizeof_hdr: 348
#> dim_info: 0
#> dim: 3 96 96 60 1 1 1 1
#> intent_p1: 0
#> intent_p2: 0
#> intent_p3: 0
#> intent_code: 0
#> datatype: 8
#> bitpix: 32
#> slice_start: 0
#> pixdim: -1.0 2.5 2.5 2.5 0.0 0.0 0.0 0.0
#> vox_offset: 352
#> scl_slope: 0
#> scl_inter: 0
#> slice_end: 0
#> slice_code: 0
#> xyzt_units: 10
#> cal_max: 2503
#> cal_min: 0
#> slice_duration: 0
#> toffset: 0
#> descrip: TractoR NIfTI writer v3.0.0
#> aux_file:
#> qform_code: 2
#> sform_code: 2
#> quatern_b: 0
#> quatern_c: 1
#> quatern_d: 0
#> qoffset_x: 122.0339
#> qoffset_y: -95.18523
#> qoffset_z: -55.03814
#> srow_x: -2.5000 0.0000 0.0000 122.0339
#> srow_y: 0.00000 2.50000 0.00000 -95.18523
#> srow_z: 0.00000 0.00000 2.50000 -55.03814
#> intent_name:
#> magic: n+1
mat = as(res, "NiftiMatrix")
mat
#> <552960 x 1> NiftiMatrix object of type "integer":
#> [,1]
#> [1,] 0
#> [2,] 0
#> [3,] 0
#> [4,] 0
#> [5,] 0
#> ... .
#> [552956,] 0
#> [552957,] 0
#> [552958,] 0
#> [552959,] 0
#> [552960,] 0
Now that the image is a matrix, we can bind the columns together,
mat = DelayedArray::acbind(mat, mat, mat, mat)
testthat::expect_is(mat, "DelayedMatrix")
object.size(mat)
#> 34568 bytes
Now that we have the data in a DelayedMatrix
class, we can use the
package DelayedMatrixStats
package that calls the matrixStats
package for quick operations:
vec_result = DelayedMatrixStats::rowMedians(mat)
head(vec_result)
#> [1] 0 0 0 0 0 0
Turning the output back into a NiftiArray
, we have to pass in the
header
argument, passing in the correct header information. We can
either create the NiftiArray
output by creating a matrix, then the
NiftiMatrix
, then the NiftiArray
.
res_mat = matrix(vec_result, ncol = 1)
res_mat = as(res_mat, "NiftiMatrix")
hdr = nifti_header(res)
res_mat = writeNiftiArray(res_mat, header = hdr)
class(res_mat)
#> [1] "NiftiMatrix"
#> attr(,"package")
#> [1] "NiftiArray"
res_arr = as(res_mat, "NiftiArray")
Or we can create an array and then making the NiftiArray
:
arr = array(vec_result, dim = dim(res) )
hdr = nifti_header(res)
res_arr = writeNiftiArray(arr, header = hdr)
res_arr
#> <96 x 96 x 60> NiftiArray object of type "double":
#> ,,1
#> [,1] [,2] [,3] ... [,95] [,96]
#> [1,] 0 0 0 . 0 0
#> [2,] 0 0 0 . 0 0
#> ... . . . . . .
#> [95,] 0 0 0 . 0 0
#> [96,] 0 0 0 . 0 0
#>
#> ...
#>
#> ,,60
#> [,1] [,2] [,3] ... [,95] [,96]
#> [1,] 0 0 0 . 0 0
#> [2,] 0 0 0 . 0 0
#> ... . . . . . .
#> [95,] 0 0 0 . 0 0
#> [96,] 0 0 0 . 0 0
nifti_header(res_arr)
#> NIfTI-1 header
#> sizeof_hdr: 348
#> dim_info: 0
#> dim: 3 96 96 60 1 1 1 1
#> intent_p1: 0
#> intent_p2: 0
#> intent_p3: 0
#> intent_code: 0
#> datatype: 8
#> bitpix: 32
#> slice_start: 0
#> pixdim: -1.0 2.5 2.5 2.5 0.0 0.0 0.0 0.0
#> vox_offset: 352
#> scl_slope: 0
#> scl_inter: 0
#> slice_end: 0
#> slice_code: 0
#> xyzt_units: 10
#> cal_max: 2503
#> cal_min: 0
#> slice_duration: 0
#> toffset: 0
#> descrip: TractoR NIfTI writer v3.0.0
#> aux_file:
#> qform_code: 2
#> sform_code: 2
#> quatern_b: 0
#> quatern_c: 1
#> quatern_d: 0
#> qoffset_x: 122.0339
#> qoffset_y: -95.18523
#> qoffset_z: -55.03814
#> srow_x: -2.5000 0.0000 0.0000 122.0339
#> srow_y: 0.00000 2.50000 0.00000 -95.18523
#> srow_z: 0.00000 0.00000 2.50000 -55.03814
#> intent_name:
#> magic: n+1
We can return a niftiImage
from the NiftiArray
object, as follows:
nii = as(res_arr, "niftiImage")
nii
#> Image array of mode "double" (4.2 Mb)
#> - 96 x 96 x 60 voxels
#> - 2.5 x 2.5 x 2.5 mm per voxel
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.