test_that("A brain volume for a single subject can be loaded", {
testthat::skip_on_cran(); # skip: leads to memory errors ('cannot allocate vector of size XX MB') on CRAN.
skip_if(tests_running_on_cran_under_macos(), message = "Skipping on CRAN under MacOS, required test data cannot be downloaded.");
fsbrain::download_optional_data();
subjects_dir = fsbrain::get_optional_data_filepath("subjects_dir");
skip_if_not(dir.exists(subjects_dir), message="Test data missing.");
subject_id = "subject1";
brain = subject.volume(subjects_dir, subject_id, 'brain');
brain2 = subject.volume(subjects_dir, subject_id, 'brain', format = 'mgz');
expect_equal(dim(brain), c(256, 256, 256));
expect_equal(dim(brain2), c(256, 256, 256));
# Extract a single slice (2D image) from the volume
slice = vol.slice(brain, 128);
expect_equal(dim(slice), c(256, 256));
# Extract several slices (2D images) from the volume
slice = vol.slice(brain, c(128, 128));
expect_equal(dim(slice), c(2, 256, 256));
# Load the slice into image magick (need to adjust color range)
#img = magick::image_read(grDevices::as.raster(slice / 255));
# error handling
testthat::expect_error(subject.volume(subjects_dir, subject_id, 'brain', format = "nosuchformat")); # invalid format
})
test_that("Brain volume CRS voxels are rendered at the correct surface space RAS coordinates", {
testthat::skip_on_cran();
skip_if(tests_running_on_cran_under_macos(), message = "Skipping on CRAN under MacOS, required test data cannot be downloaded.");
# This test shows that the vol.vox.from.crs() function and the vox2ras_tkr() functions work correctly.
# In combination, they allow to plot the voxels from a brain volume (which have no coorindates associated with them,
# -- just indices) at coordinates in surface RAS space that lead to a proper super-position of the brain surfaces and
# the brain volume of a subject.
# In order for this to work, the volume has to be a FreeSurfer conformed volume.
skip_if_not(box.can.run.all.tests(), "This test requires X11.");
fsbrain::download_optional_data();
subjects_dir = fsbrain::get_optional_data_filepath("subjects_dir");
skip_if_not(dir.exists(subjects_dir), message="Test data missing.");
brain = subject.volume(subjects_dir, 'subject1', 'brain', with_header = TRUE);
# Retrieve coloredmeshes (no displaying needed) so we can render the surface and set transparent style if needed
cm = vis.subject.morph.native(subjects_dir, 'subject1', 'thickness', views=NULL);
vis.coloredmeshes(cm, style = 'default'); # try with style = 'semitransparent' if required, but be warned: it will have bad performance. (Later spheres3d calls draw into this.)
# ----- Draw a red dot at surface RAS origin -----
# The voxel at the origin of surface RAS coordinate system. Note that this is NOT expected to be in the
# center of the brain surface (because the brain surface is not centered at 0.0, 0.0, 0.0, see the min/max vertex coords along the axes).
fs_crs = c(128, 128, 128);
surface_ras_coords = (vox2ras_tkr() %*% vol.vox.from.crs(fs_crs, add_affine=TRUE))[1:3]; # switch to 1-based R indices with affine column, matmult, then strip affine column from result.
rgl::spheres3d(surface_ras_coords, r = 5, color = "#ff0000"); # adds to the active surface plot.
# ----- Draw a set of 8 green spheres at the outer corners of the 256x256x256 volume (in surface RAS space) -----
fs_boundary_crs = matrix(c(0, 0, 0, 0, 0, 255, 0, 255, 255, 0, 255, 0, 255, 255, 255, 255, 0, 0, 255, 255, 0, 255, 0, 255), ncol=3, byrow=TRUE);
boundary_crs_aff = vol.vox.from.crs(fs_boundary_crs, add_affine=TRUE); # switch to 1-based R indices, add affine column
for(row_idx in seq_len(nrow(boundary_crs_aff))) {
surface_ras = (vox2ras_tkr() %*% boundary_crs_aff[row_idx,])[1:3];
rgl::spheres3d(surface_ras, r = 5, color = "#00ff00");
}
# Compute the bounding box of the brain from the volume data, plot blue spheres at border.
bbox = vol.boundary.box(brain$data);
bbox_R_aff = cbind(bbox$edge_coords, 1);
for(row_idx in seq_len(nrow(bbox_R_aff))) {
surface_ras = (vox2ras_tkr() %*% bbox_R_aff[row_idx,])[1:3];
rgl::spheres3d(surface_ras, r = 5, color = "#0000ff");
}
# That's it, now look at the plot.
# It shows that the brain surface lies within the volume boundaries, and the bounding box from the volume fits.
expect_equal(1L, 1L); # empty tests will be skipped
# error handling
expect_error(vol.vox.from.crs(fs_crs = "dunno")); # fs_crs must be numeric
})
test_that("The tkr vox2ras can be retrieved", {
r2v = ras2vox_tkr();
expect_true(is.matrix(r2v));
})
test_that("Voxel transform can be computed", {
# with vector
fs_crs = c(0L, 0L, 0L);
r_ind_eucli = vol.vox.from.crs(fs_crs);
r_ind_homog = vol.vox.from.crs(fs_crs, add_affine = TRUE);
testthat::expect_true(is.vector(r_ind_eucli));
testthat::expect_true(is.vector(r_ind_homog));
# with matrix
fs_crs_matrix = matrix(seq(6L), ncol = 3L, byrow = TRUE);
r_ind_eucli_mat = vol.vox.from.crs(fs_crs_matrix);
r_ind_homog_mat = vol.vox.from.crs(fs_crs_matrix, add_affine = TRUE);
testthat::expect_true(is.matrix(r_ind_eucli_mat));
testthat::expect_true(is.matrix(r_ind_homog_mat));
})
test_that("The loaded brain volume is in the correct orientation and the fs CRS to R CRS transformation works", {
testthat::skip_on_cran(); # skip: leads to memory errors ('cannot allocate vector of size XX MB') on CRAN.
skip_if(tests_running_on_cran_under_macos(), message = "Skipping on CRAN under MacOS, required test data cannot be downloaded.");
fsbrain::download_optional_data();
subjects_dir = fsbrain::get_optional_data_filepath("subjects_dir");
skip_if_not(dir.exists(subjects_dir), message="Test data missing.");
brain = subject.volume(subjects_dir, 'subject1', 'brain', with_header = TRUE);
# Get voxel intensity data on the OS command line, based
# on the FreeSUrfer (zero-based) CRS voxel indices:
# `mri_info --voxel 127 100 100 ~/.local/fsbrain/subjects_dir/subject1/mri/brain.mgz` # Adapt path for your OS, you can get it by running this in R: `fsbrain::get_optional_data_filepath("subjects_dir/subject1/mri/brain.mgz")`.
# The result is: 106.
fs_voxel_crs = c(127,100,100);
expected_intensity_value = 106;
# Check that we get the expected result:
our_crs = vol.vox.from.crs(fs_voxel_crs, add_affine = FALSE); # Transform to 1-based R indices.
expect_equal(brain$data[our_crs[1], our_crs[2], our_crs[3]], expected_intensity_value); # Check the intensity value.
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.