Title: | Your Advanced 3D Brain Visualization |
---|---|
Description: | A fast, interactive cross-platform, and easy to share 'WebGL'-based 3D brain viewer that visualizes 'FreeSurfer' and/or 'AFNI/SUMA' surfaces. The viewer widget can be either standalone or embedded into 'R-shiny' applications. The standalone version only require a web browser with 'WebGL2' support (for example, 'Chrome', 'Firefox', 'Safari'), and can be inserted into any websites. The 'R-shiny' support allows the 3D viewer to be dynamically generated from reactive user inputs. Please check the publication by Wang, Magnotti, Zhang, and Beauchamp (2023, <doi:10.1523/ENEURO.0328-23.2023>) for electrode localization. This viewer has been fully adopted by 'RAVE' <https://openwetware.org/wiki/RAVE>, an interactive toolbox to analyze 'iEEG' data by Magnotti, Wang, and Beauchamp (2020, <doi:10.1016/j.neuroimage.2020.117341>). Please check 'citation("threeBrain")' for details. |
Authors: | Zhengjia Wang [aut, cre, cph], John Magnotti [ctb, res], Xiang Zhang [ctb, res], Brian Metzger [res], Elizabeth Nesbitt [res], Meng Li [ths], Michael Beauchamp [ths, ctb, dtc] |
Maintainer: | Zhengjia Wang <[email protected]> |
License: | MPL-2.0 |
Version: | 1.2.0.9003 |
Built: | 2024-12-20 15:23:03 UTC |
Source: | https://github.com/dipterix/threeBrain |
R6 Class - Abstract Class of Geometries
Zhengjia Wang
This is mainly used when you want to upload group data only
Shiny Proxy for Viewer
brain_proxy(outputId, session = shiny::getDefaultReactiveDomain())
brain_proxy(outputId, session = shiny::getDefaultReactiveDomain())
outputId |
shiny output ID |
session |
shiny session, default is current session (see |
R6
class ViewerProxy
Setup Package, Install Environment
brain_setup(continued = FALSE, show_example = TRUE, ...)
brain_setup(continued = FALSE, show_example = TRUE, ...)
continued |
logical, there are two phases of setting up environment. You probably need to restart R session after the first phase and continue setting up. |
show_example |
whether to show example of 'N27' subject at the end. |
... |
ignored |
Zhengjia Wang
Calculate rotation matrix from non-zero vectors
calculate_rotation(vec_from, vec_to)
calculate_rotation(vec_from, vec_to)
vec_from |
original vector, length of 3 |
vec_to |
vector after rotation, length of 3 |
A four-by-four transform matrix
Function to check whether 'FreeSurfer' folder has everything we need
check_freesurfer_path( fs_subject_folder, autoinstall_template = FALSE, return_path = FALSE, check_volume = FALSE, check_surface = FALSE )
check_freesurfer_path( fs_subject_folder, autoinstall_template = FALSE, return_path = FALSE, check_volume = FALSE, check_surface = FALSE )
fs_subject_folder |
character, path to 'fs' project directory or 'RAVE' subject directory |
autoinstall_template |
logical, whether 'N27' brain should be installed if missing |
return_path |
logical, whether to return 'FreeSurfer' path |
check_volume |
logical, whether to check volume data |
check_surface |
logical, whether to check surface data (not implemented yet) |
logical whether the directory is valid or, if return_path
is true,
return 'FreeSurfer' path
'FreeSurfer'
wayReproduces conform algorithm used by 'FreeSurfer'
to conform
'NIfTI'
and 'MGH'
images.
conform_volume(x, save_to, dim = c(256, 256, 256))
conform_volume(x, save_to, dim = c(256, 256, 256))
x |
path to the image file |
save_to |
path where the conformed image will be saved, must ends with
|
dim |
positive integers of length three, the conformed dimension;
by default 'FreeSurfer' conform images to |
Nothing; the result will be save to save_to
Create a geometry group containing multiple geometries
create_group(name, position = c(0, 0, 0), layer = 1)
create_group(name, position = c(0, 0, 0), layer = 1)
name |
string, name of the geometry |
position |
x,y,z location of the group |
layer |
layer of the group. reserved |
A geometry group is a container of multiple geometries. The geometries within the same group share the same shift and rotations (see example 1). In ECoG/iEEG world, you might have 'MRI', 'CT', 'FreeSurfer' that have different orientations. For example, if you want to align MRI to FreeSurfer, Instead of calculating the position of each geometries, you can just put all MRI components into a group, and then set transform of this group, making the group aligned to FreeSurfer.
GeomGroup also can be used to store large data. To generate 3D viewer, 'threeBrain' needs to dynamically serialize data into JSON format, which can be read by browsers. However, a FreeSurfer brain might be ~30 MB. This is a very large size and might take ~5 seconds to serialize. To solve this problem, GeomGroup supports cache in its 'set_group_data' method. This method supports caching static serialized data into a JSON file, and allows the files to be loaded as static data objects. By "static", I mean the data is not supposed to be dynamic, and it should be "read-only". In JavaScript code, I also optimized such that you don't need to load these large datasets repeatedly. And this allows you to load multiple subjects' brain in a short time.
a GeomGroup instance
Zhengjia Wang
# Example 1: relative position # create group g = create_group('Group A') # create two spheres at 10,0,0, but s2 is relative to group A s1 = geom_sphere('Sphere 1', radius = 2, position = c(10,0,0)) s2 = geom_sphere('Sphere 2', radius = 2, position = c(10,0,0), group = g) # set transform (rotation) g$set_transform(matrix(c( 0,1,0,0, 1,0,0,0, 0,0,1,0, 0,0,0,1 ), byrow = TRUE, ncol = 4)) # global position for s2 is 0,10,0 if( interactive() ) { threejs_brain(s1, s2) } # Example 2: cache ## Not run: # download N27 brain # Make sure you have N27 brain downloaded to `default_template_directory()` # download_N27() template_dir <- default_template_directory() dat = freesurferformats::read.fs.surface( file.path(template_dir, 'N27/surf/lh.pial') ) vertex = dat$vertices[,1:3] face = dat$faces[,1:3] # 1. dynamically serialize mesh = geom_freemesh('lh', vertex = vertex, face = face, layer = 1) # 2. cache # Create group, all geometries in this group are relatively positioned tmp_file = tempfile() mesh = geom_freemesh('Left Hemisphere cached', vertex = vertex, face = face, cache_file = tmp_file) ## End(Not run)
# Example 1: relative position # create group g = create_group('Group A') # create two spheres at 10,0,0, but s2 is relative to group A s1 = geom_sphere('Sphere 1', radius = 2, position = c(10,0,0)) s2 = geom_sphere('Sphere 2', radius = 2, position = c(10,0,0), group = g) # set transform (rotation) g$set_transform(matrix(c( 0,1,0,0, 1,0,0,0, 0,0,1,0, 0,0,0,1 ), byrow = TRUE, ncol = 4)) # global position for s2 is 0,10,0 if( interactive() ) { threejs_brain(s1, s2) } # Example 2: cache ## Not run: # download N27 brain # Make sure you have N27 brain downloaded to `default_template_directory()` # download_N27() template_dir <- default_template_directory() dat = freesurferformats::read.fs.surface( file.path(template_dir, 'N27/surf/lh.pial') ) vertex = dat$vertices[,1:3] face = dat$faces[,1:3] # 1. dynamically serialize mesh = geom_freemesh('lh', vertex = vertex, face = face, layer = 1) # 2. cache # Create group, all geometries in this group are relatively positioned tmp_file = tempfile() mesh = geom_freemesh('Left Hemisphere cached', vertex = vertex, face = face, cache_file = tmp_file) ## End(Not run)
Calculate cross-product of two vectors in '3D'
cross_prod(x, y)
cross_prod(x, y)
x , y
|
3-dimensional vectors |
A '3D' vector that is the cross-product of x
and y
R6 Class - Generate Data Cube Geometry
Zhengjia Wang
R6 Class - Generate Data Cube Geometry via 3D Volume Texture
Zhengjia Wang
Default Directory to Store Template Brain
default_template_directory(check = FALSE)
default_template_directory(check = FALSE)
check |
logical, check if the folder is missing, is so, create one. This option ensures the folder is always created. |
When threeBrain.template_dir
is not set or invalid, the
function checks 'RAVE' (R Analysis and Visualization for 'iEEG',
https://openwetware.org/wiki/RAVE) folder at home directory. If
this folder is missing, then returns results from
R_user_dir('threeBrain', 'data')
. To override the default behavior,
use options(threeBrain.template_dir=...)
.
A directory path where template brain is stored at; see also
download_N27
default_template_directory()
default_template_directory()
R6 Class - Generate Geometry from Vertices and Face Indices
Read 'FreeSurfer' surface and volume files
freesurfer_brain( fs_subject_folder, subject_name, additional_surfaces = NULL, aligned_ct = NULL, use_cache = TRUE, use_141 = getOption("threeBrain.use141", TRUE) ) freesurfer_brain2( fs_subject_folder, subject_name, volume_types = "t1", surface_types = "pial", curvature = "sulc", atlas_types = c("aparc+aseg", "aparc.a2009s+aseg", "aparc.DKTatlas+aseg"), ct_path = NULL, use_cache = TRUE, use_141 = getOption("threeBrain.use141", TRUE), ... )
freesurfer_brain( fs_subject_folder, subject_name, additional_surfaces = NULL, aligned_ct = NULL, use_cache = TRUE, use_141 = getOption("threeBrain.use141", TRUE) ) freesurfer_brain2( fs_subject_folder, subject_name, volume_types = "t1", surface_types = "pial", curvature = "sulc", atlas_types = c("aparc+aseg", "aparc.a2009s+aseg", "aparc.DKTatlas+aseg"), ct_path = NULL, use_cache = TRUE, use_141 = getOption("threeBrain.use141", TRUE), ... )
fs_subject_folder |
character, 'FreeSurfer' subject folder, or 'RAVE' subject folder |
subject_name |
character, subject code to display with only letters and digits |
additional_surfaces |
character array, additional surface types to load, such as 'white', 'smoothwm' |
aligned_ct |
character, path to 'ct_aligned_mri.nii.gz', used for electrode localization |
use_cache |
logical, whether to use cached 'json' files or from raw 'FreeSurfer' files |
use_141 |
logical, whether to use standard 141 brain for surface file, default is |
volume_types |
volume types, right now only support T1 image |
surface_types |
surface types to load |
curvature |
curvature data. Only support |
atlas_types |
atlas types to be loaded, choices are |
ct_path |
an aligned CT file in 'Nifti' format |
... |
ignored |
This function is under FreeSurfer license.
1. Volumes:
3D viewer uses 'mri/T1.mgz' from 'FreeSurfer' to show the
volume information. 'T1.mgz' results from step 1 to 5 in 'FreeSurfer'
command 'recon-all -autorecon1', which aligns the original 'DICOM' image to 'RAS' coordinate
system, resamples to volume with 256x256x256
voxels (tri-linear by default,
check https://surfer.nmr.mgh.harvard.edu/fswiki/recon-all
for more information).
2. Surface: There are two options for surface files. The first choice is using 'std.141' brain generated by 'AFNI/SUMA'. This surface file re-calculates vertices from standard 141 space, which averages the "surface" of 141 subjects. If you want to map surface electrodes across different subjects, you might want to consider this case as it's especially designed for surface mapping. However, you'll need 'AFNI/SUMA' installed to generate the surface file. The details can be found via https://openwetware.org/wiki/Beauchamp:CorticalSurfaceHCP, and the 'AFNI/SUMA' command related is 'SurfToSurf'. Please generate the files to '[FREESURFER SUBJECT DIR]/SUMA/'. The file name follows the convention of 'std.141.[lr]h.[SURFACE TYPE].[POSTFIX]', where 'lh' means left hemisphere and 'rh' means right hemisphere; 'SURFACE TYPE' can be 'pial', 'white', 'smoothwm', and 'POSTFIX' can be 'asc', 'gii'. If multiple files for the same surface type exists, the search order will be 'asc > gii'. The other option is to use mesh files directly from 'FreeSurfer' output located at '[FREESURFER SUBJECT DIR]/surf'. If you want to use these surface, make sure they are converted to 'asc' or 'gii' format.
3. Electrode registration and transforms This package provides two ways to map electrodes to standard space. For surface electrodes, if standard 141 brain is provided, then the first option is to snap electrodes to the nearest vertices in subject space. The key is the vertex number matches across different subjects, hence the location of corresponding vertices at template brain are the mapped electrode coordinates. If standard 141 brain is missing, or the electrode type is 'stereo EEG', then the second option is volume mapping. The idea is to map electrodes to 'MNI305' brain. The details can be found at https://surfer.nmr.mgh.harvard.edu/fswiki/CoordinateSystems. To perform volume mapping, we need 'FreeSurfer' folder 'mri/transforms'. Currently, only linear 'Talairach' transform matrix is supported (located at 'talairach.xfm').
4. Coordinates The 3D viewer in this package uses the center of volume as the origin (0, 0, 0).
Zhengjia Wang
## Not run: # Please run `download_N27()` if `N27` is not at `default_template_directory()` # Import from `FreeSurfer` subject folder brain = threeBrain::freesurfer_brain( fs_subject_folder = file.path(default_template_directory(), 'N27'), subject_name = 'N27', additional_surfaces = c('white', 'smoothwm') ) # Visualize. Alternatively, you can use brain$plot(...) plot( brain ) ## End(Not run)
## Not run: # Please run `download_N27()` if `N27` is not at `default_template_directory()` # Import from `FreeSurfer` subject folder brain = threeBrain::freesurfer_brain( fs_subject_folder = file.path(default_template_directory(), 'N27'), subject_name = 'N27', additional_surfaces = c('white', 'smoothwm') ) # Visualize. Alternatively, you can use brain$plot(...) plot( brain ) ## End(Not run)
Query the 'FreeSurfer' labels
freesurfer_lut
freesurfer_lut
An object of class list
of length 3.
The 'FreeSurfer' atlases use
https://surfer.nmr.mgh.harvard.edu/fswiki/FsTutorial/AnatomicalROI/FreeSurferColorLUT
look-up table to query indexes. The 'threeBrain' electrode localization
also uses this table to export the 'FSLabel'
from electrode. If
volume type is set to 'aparc_aseg'
, then please also use this
table to filter.
freesurfer_lut$from_key(0:10) freesurfer_lut$get_key("ctx-lh-supramarginal")
freesurfer_lut$from_key(0:10) freesurfer_lut$get_key("ctx-lh-supramarginal")
Alternative to 'Matlab' version of 'pial-outer-smoothed'
,
use this function along with fill_surface
.
generate_smooth_envelope( surface_path, save_as = NULL, inflate = 3, verbose = TRUE, save_format = c("auto", "bin", "asc", "vtk", "ply", "off", "obj", "gii", "mz3", "byu") )
generate_smooth_envelope( surface_path, save_as = NULL, inflate = 3, verbose = TRUE, save_format = c("auto", "bin", "asc", "vtk", "ply", "off", "obj", "gii", "mz3", "byu") )
surface_path |
path to |
save_as |
save final envelope to path, or |
inflate |
number of |
verbose |
whether to verbose the progress; default is true |
save_format |
format of saved file when |
A 3-dimensional mesh that contains vertices and face indices,
the result is also saved to save_as
is specified.
if(interactive() && file.exists(file.path(default_template_directory(), "N27"))) { library(threeBrain) fs_path <- file.path(default_template_directory(), "N27") # lh.pial-outer-smoothed lh_pial <- file.path(fs_path, "surf", "lh.pial") save_as <- file.path(fs_path, "surf", "lh.pial-outer-smoothed") generate_smooth_envelope(lh_pial, save_as) # rh.pial-outer-smoothed rh_pial <- file.path(fs_path, "surf", "rh.pial") save_as <- file.path(fs_path, "surf", "rh.pial-outer-smoothed") generate_smooth_envelope(rh_pial, save_as) brain <- threeBrain( path = fs_path, subject_code = "N27", surface_types = 'pial-outer-smoothed' ) brain$plot(controllers = list( "Surface Type" = 'pial-outer-smoothed' )) }
if(interactive() && file.exists(file.path(default_template_directory(), "N27"))) { library(threeBrain) fs_path <- file.path(default_template_directory(), "N27") # lh.pial-outer-smoothed lh_pial <- file.path(fs_path, "surf", "lh.pial") save_as <- file.path(fs_path, "surf", "lh.pial-outer-smoothed") generate_smooth_envelope(lh_pial, save_as) # rh.pial-outer-smoothed rh_pial <- file.path(fs_path, "surf", "rh.pial") save_as <- file.path(fs_path, "surf", "rh.pial-outer-smoothed") generate_smooth_envelope(rh_pial, save_as) brain <- threeBrain( path = fs_path, subject_code = "N27", surface_types = 'pial-outer-smoothed' ) brain$plot(controllers = list( "Surface Type" = 'pial-outer-smoothed' )) }
Superseded by volume_to_surf
. Please do not use this function.
generate_subcortical_surface( atlas, index, save_prefix = NULL, label = NULL, IJK2RAS = NULL, grow = 1, remesh = TRUE, smooth = TRUE, smooth_delta = 3, ... )
generate_subcortical_surface( atlas, index, save_prefix = NULL, label = NULL, IJK2RAS = NULL, grow = 1, remesh = TRUE, smooth = TRUE, smooth_delta = 3, ... )
atlas |
path to imaging 'parcellation', can be |
index |
'parcellation' index, see 'FreeSurfer' look-up table |
save_prefix |
parent folder to save the resulting surface |
label |
character label or name of the 'sub-cortical' structure, usually automatically derived from |
IJK2RAS |
an 'Affine' matrix from 'voxel' index to |
grow |
amount to grow (dilate) before generating mesh |
remesh , smooth , smooth_delta , ...
|
passed to |
A surface mesh, containing 'atlas' index, label, surface nodes and face indices.
Creates any mesh geometry given vertices and face indices
geom_freemesh( name, vertex = NULL, face = NULL, position = c(0, 0, 0), layer = 1, cache_file = NULL, group = NULL )
geom_freemesh( name, vertex = NULL, face = NULL, position = c(0, 0, 0), layer = 1, cache_file = NULL, group = NULL )
name |
unique string in a scene to tell apart from different objects |
vertex |
position of each vertices (3 columns) |
face |
face indices indicating which 3 vertices to be linked (3 columns) |
position |
x,y,z location of the geometry |
layer |
visibility of the geometry, used when there are multiple cameras 1 is visible for all cameras |
cache_file |
cache vertex and face data into group |
group |
a GeomGroup object, if null, then the group will be generated automatically |
When generating a free mesh internally, a group must be specified,
therefore if group is NULL
here, then a group will be generated.
However, it's always recommended to pass a group to the free mesh.
Zhengjia Wang
## Not run: # Make sure you have N27 brain downloaded to `default_template_directory()` # threeBrain::download_N27() n27_dir = file.path(default_template_directory(), "N27") surf_type = 'pial' # Locate mesh files lh = read_fs_asc(file.path(n27_dir, sprintf('surf/lh.%s.asc', surf_type))) rh = read_fs_asc(file.path(n27_dir, sprintf('surf/rh.%s.asc', surf_type))) # Create groups group = create_group(name = sprintf('Surface - %s (N27)', surf_type)) # create mesh lh_mesh = geom_freemesh( name = sprintf('FreeSurfer Left Hemisphere - %s (N27)', surf_type), vertex = lh$vertices[,1:3], face = lh$faces[,1:3], group = group ) rh_mesh = geom_freemesh( name = sprintf('FreeSurfer Right Hemisphere - %s (N27)', surf_type), vertex = rh$vertices[,1:3], face = rh$faces[,1:3], group = group ) # Render if( interactive() ) { threejs_brain(lh_mesh, rh_mesh) } ## End(Not run)
## Not run: # Make sure you have N27 brain downloaded to `default_template_directory()` # threeBrain::download_N27() n27_dir = file.path(default_template_directory(), "N27") surf_type = 'pial' # Locate mesh files lh = read_fs_asc(file.path(n27_dir, sprintf('surf/lh.%s.asc', surf_type))) rh = read_fs_asc(file.path(n27_dir, sprintf('surf/rh.%s.asc', surf_type))) # Create groups group = create_group(name = sprintf('Surface - %s (N27)', surf_type)) # create mesh lh_mesh = geom_freemesh( name = sprintf('FreeSurfer Left Hemisphere - %s (N27)', surf_type), vertex = lh$vertices[,1:3], face = lh$faces[,1:3], group = group ) rh_mesh = geom_freemesh( name = sprintf('FreeSurfer Right Hemisphere - %s (N27)', surf_type), vertex = rh$vertices[,1:3], face = rh$faces[,1:3], group = group ) # Render if( interactive() ) { threejs_brain(lh_mesh, rh_mesh) } ## End(Not run)
Create sphere geometry
geom_sphere( name, radius, position = c(0, 0, 0), layer = 1, group = NULL, value = NULL, time_stamp = NULL )
geom_sphere( name, radius, position = c(0, 0, 0), layer = 1, group = NULL, value = NULL, time_stamp = NULL )
name |
unique string in a scene to tell apart from different objects |
radius |
size of sphere |
position |
x,y,z location of the sphere |
layer |
visibility of the geometry, used when there are multiple cameras 1 is visible for all cameras |
group |
a GeomGroup object |
value , time_stamp
|
color of the sphere, used for animation/color rendering |
Zhengjia Wang
# Create a sphere with animation g = lapply(1:10, function(ii){ v = rep(ii, 10) v[1:ii] = 1:ii geom_sphere(paste0('s', ii), ii, value = v, position = c(11 * ii, 0,0), time_stamp = (1:10)/10) }) if( interactive() ) { threejs_brain(.list = g) }
# Create a sphere with animation g = lapply(1:10, function(ii){ v = rep(ii, 10) v[1:ii] = 1:ii geom_sphere(paste0('s', ii), ii, value = v, position = c(11 * ii, 0,0), time_stamp = (1:10)/10) }) if( interactive() ) { threejs_brain(.list = g) }
R6 Class - Generate Group of Geometries
Zhengjia Wang
Function to read digest header
get_digest_header(file, key, if_error = NULL, .list = NULL)
get_digest_header(file, key, if_error = NULL, .list = NULL)
file |
file path to a 'JSON' file |
key |
character, key to extract |
if_error |
value to return if key not found or read error occurs |
.list |
alternative list to supply if file is missing |
Get 'voxel' to world matrix
get_ijk2ras(x, type = c("scanner", "tkr"))
get_ijk2ras(x, type = c("scanner", "tkr"))
x |
path to imaging files |
type |
world space type; choices are |
A four by four matrix
Import from 'FreeSurfer' and create 'JSON' cache for 3D viewer
import_from_freesurfer(fs_path, subject_name, quiet = FALSE)
import_from_freesurfer(fs_path, subject_name, quiet = FALSE)
fs_path |
'FreeSurfer' subject directory |
subject_name |
subject code |
quiet |
whether to suppress message or not |
None.
Import 'T1-MRI', surface files, curvature/'sulcus', atlas, and
'Talairach' transform matrix into 'json' format. These functions are not
intended to be called directly, use import_from_freesurfer
instead.
import_fs( subject_name, fs_path, quiet = FALSE, dtype = c("T1", "surface", "curv", "atlas_volume", "atlas_surface", "xform"), sub_type = NULL, hemisphere = c("l", "r"), ... ) import_suma( subject_name, fs_path, quiet = FALSE, dtype = c("T1", "surface", "curv", "atlas_volume", "atlas_surface", "xform"), sub_type = NULL, hemisphere = c("l", "r"), ... )
import_fs( subject_name, fs_path, quiet = FALSE, dtype = c("T1", "surface", "curv", "atlas_volume", "atlas_surface", "xform"), sub_type = NULL, hemisphere = c("l", "r"), ... ) import_suma( subject_name, fs_path, quiet = FALSE, dtype = c("T1", "surface", "curv", "atlas_volume", "atlas_surface", "xform"), sub_type = NULL, hemisphere = c("l", "r"), ... )
subject_name |
character, subject code |
fs_path |
path to 'FreeSurfer' folder |
quiet , ...
|
passed from or to other methods. |
dtype |
data type to import, choices are |
sub_type |
detailed files to import. |
hemisphere |
which hemisphere to import, ignored when |
logical, TRUE
if the file is or has been cached, or
FALSE
if the file is missing.
R6 Class - Generate Line Segments
Zhengjia Wang
List all built-in and user-customized electrode prototypes. User paths will be searched first, if multiple prototype configuration files are found for the same type.
list_electrode_prototypes() load_prototype(type)
list_electrode_prototypes() load_prototype(type)
type |
electrode type, character |
list_electrode_prototypes
returns a named list, names are
the prototype types and values are the prototype configuration paths;
load_prototype
returns the prototype instance if type
exists,
or throw an error.
availables <- list_electrode_prototypes() if( "sEEG-16" %in% names(availables) ) { proto <- load_prototype( "sEEG-16" ) print(proto, details = FALSE) }
availables <- list_electrode_prototypes() if( "sEEG-16" %in% names(availables) ) { proto <- load_prototype( "sEEG-16" ) print(proto, details = FALSE) }
If 'RAVE' has been installed, please use 'RAVE' modules. This function is purely for demonstration purposes.
localization_module( subject_code, fs_path, ct_path = NULL, surfaces = "pial", use_141 = TRUE, shiny_options = list(launch.browser = TRUE), save_path = tempfile(pattern = "electrode", fileext = ".csv"), ..., control_presets = NULL, side_display = FALSE, controllers = list() )
localization_module( subject_code, fs_path, ct_path = NULL, surfaces = "pial", use_141 = TRUE, shiny_options = list(launch.browser = TRUE), save_path = tempfile(pattern = "electrode", fileext = ".csv"), ..., control_presets = NULL, side_display = FALSE, controllers = list() )
subject_code |
subject code |
fs_path |
the subject's 'FreeSurfer' path |
ct_path |
the file path of 'CT' scans that have already been aligned to 'T1'; must be in 'NIFTI' format |
surfaces |
which surfaces to load |
use_141 |
whether to try 'SUMA' standard 141 surface; default is true |
shiny_options |
shiny application options; see |
save_path |
a temporary file where the electrode table should be cached; this file will be used to keep track of changes in case the application is crashed or shutdown |
... |
other parameters to pass into |
control_presets , side_display , controllers
|
passed to
|
A list of 'ui'
elements, 'server'
function, and
a stand-alone 'app'
# This example require N27 template brain to be installed # see `?download_N27` for details # using N27 to localize fs_path <- file.path(default_template_directory(), "N27") if(interactive() && dir.exists(fs_path)){ module <- localization_module("N27", fs_path) print(module$app) }
# This example require N27 template brain to be installed # see `?download_N27` for details # using N27 to localize fs_path <- file.path(default_template_directory(), "N27") if(interactive() && dir.exists(fs_path)){ module <- localization_module("N27", fs_path) print(module$app) }
Create Multi-subject Template
merge_brain( ..., .list = NULL, template_surface_types = NULL, template_subject = unname(getOption("threeBrain.template_subject", "N27")), template_dir = default_template_directory() )
merge_brain( ..., .list = NULL, template_surface_types = NULL, template_subject = unname(getOption("threeBrain.template_subject", "N27")), template_dir = default_template_directory() )
... , .list
|
|
template_surface_types |
which template surface types to load, default is auto-guess |
template_subject |
character, subject code to be treated as template, default is 'N27' |
template_dir |
the parent directory where template subject is stored in |
Zhengjia Wang
Create or load new electrode prototype from existing configurations
new_electrode_prototype(base_prototype, modifier = NULL)
new_electrode_prototype(base_prototype, modifier = NULL)
base_prototype |
base prototype, this can be a string of prototype type
(see |
modifier |
internally used |
An electrode prototype instance
available_prototypes <- list_electrode_prototypes() if("Precision33x31" %in% names(available_prototypes)) { # Load by type name new_electrode_prototype("Precision33x31") # load by path path <- available_prototypes[["Precision33x31"]] new_electrode_prototype(path) # load by json string json <- readLines(path) new_electrode_prototype(json) }
available_prototypes <- list_electrode_prototypes() if("Precision33x31" %in% names(available_prototypes)) { # Load by type name new_electrode_prototype("Precision33x31") # load by path path <- available_prototypes[["Precision33x31"]] new_electrode_prototype(path) # load by json string json <- readLines(path) new_electrode_prototype(json) }
Plot slices of volume
plot_slices( volume, overlays = NULL, transform = NULL, positions = NULL, zoom = 1, pixel_width = 0.5, col = c("black", "white"), normalize = NULL, zclip = NULL, overlay_alpha = 0.3, zlim = normalize, main = "", title_position = c("left", "top"), fun = NULL, nc = NA, which = NULL, ... )
plot_slices( volume, overlays = NULL, transform = NULL, positions = NULL, zoom = 1, pixel_width = 0.5, col = c("black", "white"), normalize = NULL, zclip = NULL, overlay_alpha = 0.3, zlim = normalize, main = "", title_position = c("left", "top"), fun = NULL, nc = NA, which = NULL, ... )
volume |
path to volume (underlay) |
overlays |
images to overlay on top of the underlay, can be either
a vector of paths to the overlay volume images, or a sequence of named lists.
Each list item has |
transform |
rotation of the volume in scanner |
positions |
vector of length 3 or matrix of 3 columns, the |
zoom |
zoom-in radio, default is 1 |
pixel_width |
output image pixel resolution; default is |
col |
color palette, can be a sequence of colors |
normalize |
range for volume data to be normalized; either |
zclip |
clip image densities; if specified, values outside of this range will be clipped into this range |
overlay_alpha |
transparency of the overlay; default is 0.3 |
zlim |
image plot value range, default is identical to |
main |
image titles |
title_position |
title position; choices are |
fun |
function with two arguments that will be executed after each image is drawn; can be used to draw cross-hairs or annotate each image |
nc |
number of "columns" in the plot when there are too many positions,
must be positive integer; default is |
which |
which plane to plot; default is |
... |
additional arguments passing into |
Nothing
Read 'FreeSurfer' ascii file
read_fs_asc(file)
read_fs_asc(file)
file |
file location |
a list of vertices and face indices
Read FreeSurfer Annotations
read_fs_labels(path, vertex_number)
read_fs_labels(path, vertex_number)
path |
label path |
vertex_number |
force to reset vertex number if raw file is incorrect |
Read 'FreeSurfer' m3z file
read_fs_m3z(filename)
read_fs_m3z(filename)
filename |
file location, usually located at 'mri/transforms/talairach.m3z' |
An 'm3z' file is a 'gzip' binary file containing a dense vector field that describes a 3D registration between two volumes/images. This implementation follows the 'Matlab' implementation from the 'FreeSurfer'. This function is released under the 'FreeSurfer' license: https://surfer.nmr.mgh.harvard.edu/fswiki/FreeSurferSoftwareLicense.
registration data
Read 'FreeSurfer' 'mgz/mgh' file
read_fs_mgh_mgz(filename)
read_fs_mgh_mgz(filename)
filename |
file location |
list contains coordinate transforms and volume data
The function 'read_gii2' is a dynamic wrapper of Python 'nibabel' loader. If no Python is detected, it will switch to 'gifti::readgii'.
read_gii2(path)
read_gii2(path)
path |
'Gifti' file path |
An R function acting as safe wrapper for nibabel.load
.
The function 'read_mgz' is a dynamic wrapper of Python 'nibabel' loader. If no Python is detected, it will switch to built-in function 'read_fs_mgh_mgz', which has limited features.
read_mgz(path)
read_mgz(path)
path |
'mgz/mgh' file path |
An R function acting as safe wrapper for nibabel.load
.
'MGH'
or 'Nifti'
formatsRead volume file in 'MGH'
or 'Nifti'
formats
read_volume(file, format = c("auto", "mgh", "nii"), header_only = FALSE)
read_volume(file, format = c("auto", "mgh", "nii"), header_only = FALSE)
file |
file path |
format |
the file format |
header_only |
whether only read headers; default is false |
A list of volume data and transform matrices; if
header_only=TRUE
, then volume data will be substituted by the
header.
Shiny Renderer for threeBrain Widgets
expr |
R expression that calls three_brain function or Brain object |
env |
environment of expression to be evaluated |
quoted |
is expr quoted? Default is false. |
Zhengjia Wang
Function to reshape data to 'RAS' order
reorient_volume(volume, Torig)
reorient_volume(volume, Torig)
volume |
3-mode tensor (voxels), usually from 'mgz', 'nii', or 'BRIK' files |
Torig |
a |
Reshaped tensor with dimensions corresponding to 'R', 'A', and 'S'
Save threeBrain widgets to local file system
save_brain(widget, path, title = "3D Viewer", as_zip = FALSE, ...)
save_brain(widget, path, title = "3D Viewer", as_zip = FALSE, ...)
widget |
generated from function 'threejs_brain' |
path |
path to save the brain widget |
title |
widget title. |
as_zip |
whether to create zip file "compressed.zip". |
... |
ignored, used for backward compatibility |
Zhengjia Wang
'sEEG'
shaft geometry prototypeIntended for creating/editing geometry prototype, please see
load_prototype
to load existing prototype
seeg_prototype( type, center_position, contact_widths, diameter = 1, channel_order = seq_along(center_position), fix_contact = 1, overall_length = 200, description = NULL, dry_run = FALSE, default_interpolation = NULL, viewer_options = NULL, overwrite = FALSE )
seeg_prototype( type, center_position, contact_widths, diameter = 1, channel_order = seq_along(center_position), fix_contact = 1, overall_length = 200, description = NULL, dry_run = FALSE, default_interpolation = NULL, viewer_options = NULL, overwrite = FALSE )
type |
type string and unique identifier of the prototype |
center_position |
numerical vector, contact center positions |
contact_widths |
numerical vector or length of one, width or widths of the contacts |
diameter |
probe diameter |
channel_order |
the channel order of the contacts; default is a sequence along the number |
fix_contact |
|
overall_length |
probe length, default is |
description |
prototype description |
dry_run |
whether not to save the prototype configurations |
default_interpolation |
default interpolation string for electrode localization |
viewer_options |
list of viewer options; this should be a list of key-value pairs where the keys are the controller names and values are the corresponding values when users switch to localizing the electrode group |
overwrite |
whether to overwrite existing configuration file; default is false, which throws a warning when duplicated |
A electrode shaft geometry prototype; the configuration file is saved to 'RAVE' 3rd-party repository.
probe_head <- 2 n_contacts <- 12 width <- 2.41 contact_spacing <- 5 overall_length <- 400 diameter <- 1.12 contacts <- probe_head + width / 2 + 0:(n_contacts-1) * contact_spacing proto <- seeg_prototype( type = "AdTech-sEEG-SD12R-SP05X-000", description = c( "AdTech sEEG - 12 contacts", "Contact length : 2.41 mm", "Central spacing : 5 mm", "Tip size : 2 mm", "Diameter : 1.12 mm" ), center_position = contacts, contact_widths = width, diameter = diameter, overall_length = overall_length, dry_run = TRUE ) print(proto, details = FALSE)
probe_head <- 2 n_contacts <- 12 width <- 2.41 contact_spacing <- 5 overall_length <- 400 diameter <- 1.12 contacts <- probe_head + width / 2 + 0:(n_contacts-1) * contact_spacing proto <- seeg_prototype( type = "AdTech-sEEG-SD12R-SP05X-000", description = c( "AdTech sEEG - 12 contacts", "Contact length : 2.41 mm", "Central spacing : 5 mm", "Tip size : 2 mm", "Diameter : 1.12 mm" ), center_position = contacts, contact_widths = width, diameter = diameter, overall_length = overall_length, dry_run = TRUE ) print(proto, details = FALSE)
R6 Class - Generate Sphere Geometry
Zhengjia Wang
R6 Class - Generate Sphere Geometry
Zhengjia Wang
Download and Manage Template Subjects
download_template_subject( subject_code = "N27", url, template_dir = default_template_directory() ) download_N27(make_default = FALSE, ...) set_default_template( subject_code, view = TRUE, template_dir = default_template_directory() ) threebrain_finalize_installation( upgrade = c("ask", "always", "never", "data-only", "config-only"), async = TRUE ) available_templates()
download_template_subject( subject_code = "N27", url, template_dir = default_template_directory() ) download_N27(make_default = FALSE, ...) set_default_template( subject_code, view = TRUE, template_dir = default_template_directory() ) threebrain_finalize_installation( upgrade = c("ask", "always", "never", "data-only", "config-only"), async = TRUE ) available_templates()
subject_code |
character with only letters and numbers (Important); default is 'N27' |
url |
zip file address; must be specified if |
template_dir |
parent directory where subject's 'FreeSurfer' folder should be stored |
make_default |
logical, whether to make 'N27' default subject |
... |
more to pass to |
view |
whether to view the subject |
upgrade |
whether to check and download 'N27' brain interactively. Choices are 'ask', 'always', and 'never' |
async |
whether to run the job in parallel to others; default is true |
To view electrodes implanted in multiple subjects, it's highly
recommended to view them in a template space The detail mapping method
is discussed in function freesurfer_brain
.
To map to a template space, one idea is to find someone whose brain is
normal. In our case, the choice is subject 'N27', also known as 'Colin 27'.
function download_N27
provides a simple and easy way to download a
partial version from the Internet.
If you have any other ideas about template brain, you can use function
set_default_template(subject_code, template_dir)
to redirect to
your choice. If your template brain is a 'Zip' file on the Internet, we
provide function download_template_subject
to automatically install it.
Zhengjia Wang
Create a brain object
threeBrain( path, subject_code, surface_types = c("pial", "smoothwm", "inflated", "sphere.reg"), atlas_types, ..., template_subject = unname(getOption("threeBrain.template_subject", "N27")), backward_compatible = getOption("threeBrain.compatible", FALSE) )
threeBrain( path, subject_code, surface_types = c("pial", "smoothwm", "inflated", "sphere.reg"), atlas_types, ..., template_subject = unname(getOption("threeBrain.template_subject", "N27")), backward_compatible = getOption("threeBrain.compatible", FALSE) )
path |
path to 'FreeSurfer' directory, or 'RAVE' subject directory containing 'FreeSurfer' files, or simply a 'RAVE' subject |
subject_code |
subject code, characters |
surface_types |
surface types to load; default is |
atlas_types |
brain atlas to load; default is |
... |
reserved for future use |
template_subject |
template subject to refer to; used for group template mapping |
backward_compatible |
whether to support old format; default is false |
Create a Threejs Brain and View it in Browsers
threejs_brain( ..., .list = list(), width = NULL, height = NULL, background = "#FFFFFF", cex = 1, timestamp = TRUE, title = "", side_canvas = FALSE, side_zoom = 1, side_width = 250, side_shift = c(0, 0), side_display = TRUE, control_panel = TRUE, control_presets = NULL, control_display = TRUE, camera_center = c(0, 0, 0), camera_pos = c(500, 0, 0), start_zoom = 1, symmetric = 0, default_colormap = "Value", palettes = NULL, value_ranges = NULL, value_alias = NULL, show_inactive_electrodes = TRUE, surface_colormap = system.file("palettes", "surface", "ContinuousSample.json", package = "threeBrain"), voxel_colormap = system.file("palettes", "datacube2", "FreeSurferColorLUT.json", package = "threeBrain"), videos = list(), widget_id = "threebrain_data", tmp_dirname = NULL, debug = FALSE, enable_cache = FALSE, token = NULL, controllers = list(), browser_external = TRUE, global_data = list(), global_files = list(), qrcode = NULL, custom_javascript = NULL, show_modal = "auto", embed = FALSE )
threejs_brain( ..., .list = list(), width = NULL, height = NULL, background = "#FFFFFF", cex = 1, timestamp = TRUE, title = "", side_canvas = FALSE, side_zoom = 1, side_width = 250, side_shift = c(0, 0), side_display = TRUE, control_panel = TRUE, control_presets = NULL, control_display = TRUE, camera_center = c(0, 0, 0), camera_pos = c(500, 0, 0), start_zoom = 1, symmetric = 0, default_colormap = "Value", palettes = NULL, value_ranges = NULL, value_alias = NULL, show_inactive_electrodes = TRUE, surface_colormap = system.file("palettes", "surface", "ContinuousSample.json", package = "threeBrain"), voxel_colormap = system.file("palettes", "datacube2", "FreeSurferColorLUT.json", package = "threeBrain"), videos = list(), widget_id = "threebrain_data", tmp_dirname = NULL, debug = FALSE, enable_cache = FALSE, token = NULL, controllers = list(), browser_external = TRUE, global_data = list(), global_files = list(), qrcode = NULL, custom_javascript = NULL, show_modal = "auto", embed = FALSE )
... , .list
|
geometries inherit from AbstractGeom |
width , height
|
positive integers. Width and height of the widget. By default width='100%', and height varies. |
background |
character, background color such as |
cex |
positive number, relative text magnification level |
timestamp |
logical, whether to show time-stamp at the beginning |
title |
viewer title |
side_canvas |
logical, enable side cameras to view objects from fixed perspective |
side_zoom |
numerical, if side camera is enabled, zoom-in level, from 1 to 5 |
side_width |
positive integer, side panel size in pixels |
side_shift |
integer of length two, side panel shift in pixels ('CSS style': top, left) |
side_display |
logical, show/hide side panels at beginning |
control_panel |
logical, enable control panels for the widget |
control_presets |
characters, presets to be shown in control panels |
control_display |
logical, whether to expand/collapse control UI at the beginning |
camera_center |
numerical, length of three, XYZ position where camera should focus at |
camera_pos |
XYZ position of camera itself, default (0, 0, 500) |
start_zoom |
numerical, positive number indicating camera zoom level |
symmetric |
numerical, default 0, color center will be mapped to this value |
default_colormap |
character, which color map name to display at startup |
palettes |
named list, names corresponds to color-map names if you want to change color palettes |
value_ranges |
named list, similar to |
value_alias |
named list, legend title for corresponding variable |
show_inactive_electrodes |
logical, whether to show electrodes with no values |
surface_colormap |
a color map or its path generated by |
voxel_colormap |
a color map or its path generated by |
videos |
named list, names corresponds to color-map names, and items are generated from |
widget_id |
character, internally used as unique identifiers for widgets; only use it when you have multiple widgets in one website |
tmp_dirname |
character path, internally used, where to store temporary files |
debug |
logical, internally used for debugging |
enable_cache |
whether to enable cache, useful when rendering the viewers repeatedly in shiny applications |
token |
unique character, internally used to identify widgets in 'JavaScript' |
controllers |
list to override the settings, for example |
browser_external |
logical, use system default browser (default) or built-in one. |
global_data , global_files
|
internally use, mainly to store orientation matrices and files. |
qrcode |
'URL' to show in the 'QR' code; can be a character string or a named list of |
custom_javascript |
customized temporary 'JavaScript' code that runs after ready state; available 'JavaScript' variables are:
|
show_modal |
logical or |
embed |
whether to try embedding the viewer in current run-time; default is false (will launch default web browser); set to true if running in |
Zhengjia Wang
if( interactive() ) { library(threeBrain) # Please use `download_N27` to download N27 Collins template brain n27_path <- file.path(default_template_directory(), "N27") if( dir.exists(n27_path) ) { brain <- threeBrain(path = n27_path, subject_code = "N27", surface_types = c('pial', 'smoothwm')) print(brain) brain$plot( background = "#000000", controllers = list( 'Voxel Type' = 'aparc_aseg', 'Surface Type' = 'smoothwm', 'Blend Factor' = 1, 'Right Opacity' = 0.3, 'Overlay Sagittal' = TRUE ), show_modal = TRUE ) } }
if( interactive() ) { library(threeBrain) # Please use `download_N27` to download N27 Collins template brain n27_path <- file.path(default_template_directory(), "N27") if( dir.exists(n27_path) ) { brain <- threeBrain(path = n27_path, subject_code = "N27", surface_types = c('pial', 'smoothwm')) print(brain) brain$plot( background = "#000000", controllers = list( 'Voxel Type' = 'aparc_aseg', 'Surface Type' = 'smoothwm', 'Blend Factor' = 1, 'Right Opacity' = 0.3, 'Overlay Sagittal' = TRUE ), show_modal = TRUE ) } }
Shiny Output for threeBrain Widgets
outputId |
unique identifier for the widget |
width , height
|
width and height of the widget. By default width="100 and height="500px". |
reportSize |
whether to report widget size in shiny
|
Zhengjia Wang
R6 Class - Generate Tube Geometry
Zhengjia Wang
Add video content to the viewer
video_content( path, duration = Inf, time_start = 0, asp_ratio = 16/9, local = TRUE )
video_content( path, duration = Inf, time_start = 0, asp_ratio = 16/9, local = TRUE )
path |
local file path or 'URL' |
duration |
duration of the video |
time_start |
start time relative to the stimuli onset |
asp_ratio |
aspect ratio; default is |
local |
used only when |
The video path can be either local file path or a 'URL' from websites. When path is from the internet, there are two options: download the video before generating the viewer, or directly use the 'URL'.
If download happens before a viewer is generated (local=TRUE
), then
the video content is local. The viewer will be self-contained. However,
the distribution will contain the video, and the archive size might be large.
If raw 'URL' is used (local=FALSE
), then viewer is not self-contained
as the video link might break anytime. The 'screenshot' and 'record' function
might be limited if the 'URL' has different domain than yours. However,
the distribution will not contain the video, hence smaller. This works in the
scenarios when it is preferred not to share video files or they are
licensed, or simply distribution is limited. Besides, this method is slightly
faster than the local alternatives.
'nii'
or 'mgz'
volume filesGenerate surface file from 'nii'
or 'mgz'
volume files
volume_to_surf( volume, save_to = NA, lambda = 0.2, degree = 2, threshold_lb = 0.5, threshold_ub = NA, format = "auto" )
volume_to_surf( volume, save_to = NA, lambda = 0.2, degree = 2, threshold_lb = 0.5, threshold_ub = NA, format = "auto" )
volume |
path to the volume file, or object from |
save_to |
where to save the surface file; default is |
lambda |
|
degree |
|
threshold_lb |
lower threshold of the volume (to create mask); default is |
threshold_ub |
upper threshold of the volume; default is |
format |
The format of the file if
|
Triangle 'rgl'
mesh (vertex positions in native 'RAS'
). If save_to
is a valid path, then the mesh will be saved to this location.
read_volume
, vcg_isosurface
,
vcg_smooth_implicit
library(threeBrain) N27_path <- file.path(default_template_directory(), "N27") if(dir.exists(N27_path)) { aseg <- file.path(N27_path, "mri", "aparc+aseg.mgz") # generate surface for left-hemisphere insula mesh <- volume_to_surf(aseg, threshold_lb = 1034, threshold_ub = 1036) if(interactive()) { ravetools::rgl_view({ ravetools::rgl_call("shade3d", mesh, color = "yellow") }) } }
library(threeBrain) N27_path <- file.path(default_template_directory(), "N27") if(dir.exists(N27_path)) { aseg <- file.path(N27_path, "mri", "aparc+aseg.mgz") # generate surface for left-hemisphere insula mesh <- volume_to_surf(aseg, threshold_lb = 1034, threshold_ub = 1036) if(interactive()) { ravetools::rgl_view({ ravetools::rgl_call("shade3d", mesh, color = "yellow") }) } }
Color maps for volume or surface data
create_colormap( gtype = c("surface", "volume"), dtype = c("continuous", "discrete"), key, color, value, alpha = FALSE, con = NULL, auto_rescale = FALSE, ... ) save_colormap(cmap, con) freeserfer_colormap(con) load_colormap(con)
create_colormap( gtype = c("surface", "volume"), dtype = c("continuous", "discrete"), key, color, value, alpha = FALSE, con = NULL, auto_rescale = FALSE, ... ) save_colormap(cmap, con) freeserfer_colormap(con) load_colormap(con)
gtype |
geometry type, choices are |
dtype |
data type, |
key |
non-negative integer vector corresponding to color values; its length must exceed 1; see 'Details' |
color |
characters, corresponding to color strings for each key |
value |
actual value for each key |
alpha |
whether to respect transparency |
con |
a file path to write results to or to read from. The
file path can be passed as |
auto_rescale |
automatically scale the color according to image values; only valid for continuous color maps |
... |
used by continuous color maps, passed to
|
cmap |
color map object |
Internal 'JavaScript' shader implementation uses integer color key
s to
connect color palettes and corresponding values. The keys must be
non-negative.
Zero key is a special color key reserved by system. Please avoid using it for valid values.
A list of color map information
# Creates a symmetric continuous colormap with 3 keys # The color range is -10 to 10 # The colors are 'blue','white','red' for these keys pal <- create_colormap( gtype = "volume", dtype = "continuous", key = c(1,2,3), value = c(-10,0,10), color = c('blue','white','red')) print( pal ) # ---------------- Get colormap key from a value ------------ # returns key index starting from pal$get_key( -10 ) # nearest value pal$get_key( 2 ) # set threshold, key is now 0 (no color) pal$get_key( 2, max_delta = 1 ) # ---------------- Save and load ---------------- f <- tempfile( fileext = '.json' ) save_colormap( pal, f ) cat(readLines(f), sep = '\n') load_colormap(f)
# Creates a symmetric continuous colormap with 3 keys # The color range is -10 to 10 # The colors are 'blue','white','red' for these keys pal <- create_colormap( gtype = "volume", dtype = "continuous", key = c(1,2,3), value = c(-10,0,10), color = c('blue','white','red')) print( pal ) # ---------------- Get colormap key from a value ------------ # returns key index starting from pal$get_key( -10 ) # nearest value pal$get_key( 2 ) # set threshold, key is now 0 (no color) pal$get_key( 2, max_delta = 1 ) # ---------------- Save and load ---------------- f <- tempfile( fileext = '.json' ) save_colormap( pal, f ) cat(readLines(f), sep = '\n') load_colormap(f)
Generate volume data from 'MNI' coordinates
add_voxel_cube( brain, name, cube, size = c(256, 256, 256), trans_mat = NULL, trans_space_from = c("model", "scannerRAS"), color_format = c("RGBAFormat", "RedFormat") ) add_nifti( brain, name, path, trans_mat = NULL, color_format = c("RGBAFormat", "RedFormat"), trans_space_from = c("model", "scannerRAS") ) create_voxel_cube( mni_ras, value, colormap, keys = colormap$get_key(value), dimension = c(256, 256, 256) )
add_voxel_cube( brain, name, cube, size = c(256, 256, 256), trans_mat = NULL, trans_space_from = c("model", "scannerRAS"), color_format = c("RGBAFormat", "RedFormat") ) add_nifti( brain, name, path, trans_mat = NULL, color_format = c("RGBAFormat", "RedFormat"), trans_space_from = c("model", "scannerRAS") ) create_voxel_cube( mni_ras, value, colormap, keys = colormap$get_key(value), dimension = c(256, 256, 256) )
brain |
a 'threeBrain' brain object generated from |
name |
the name of voxel cube, only letters, digits and |
cube |
a 3-mode array; see the following example |
size |
the actual size of the volume, usually dot multiplication of the dimension and voxel size |
trans_mat |
the transform matrix of the volume. For |
trans_space_from |
where does |
color_format |
color format for the internal texture. Default is 4-channel |
path |
'Nifti' data path |
mni_ras |
'MNI' 'RAS' coordinates, should be a |
value |
data values (length |
colormap |
a color map generated from |
keys |
integer color-keys generated from a color map with length of |
dimension |
volume dimension; default is a |
create_voxel_cube
returns a list of cube data and other informations;
add_voxel_cube
returns the brain
object
# requires N27 brain to be installed # use `download_N27()` to download template Collins brain # sample MNI coords tbl <- read.csv(system.file( 'sample_data/example_cube.csv', package = 'threeBrain' )) head(tbl) # load colormap cmap <- load_colormap(system.file( 'palettes/datacube2/Mixed.json', package = 'threeBrain' )) x <- create_voxel_cube( mni_ras = tbl[, c('x', 'y', 'z')], keys = tbl$key, dimension = c(128, 128, 128) ) n27_path <- file.path(default_template_directory(), "N27") if( interactive() && dir.exists(n27_path) ) { brain <- merge_brain() # or add_voxel_cube(brain, 'example', x$cube) x$add_to_brain(brain, 'example') brain$plot(controllers = list( "Voxel Type" = 'example', 'Right Opacity' = 0.3, 'Left Opacity' = 0.3, 'Background Color' = '#000000' ), voxel_colormap = cmap) }
# requires N27 brain to be installed # use `download_N27()` to download template Collins brain # sample MNI coords tbl <- read.csv(system.file( 'sample_data/example_cube.csv', package = 'threeBrain' )) head(tbl) # load colormap cmap <- load_colormap(system.file( 'palettes/datacube2/Mixed.json', package = 'threeBrain' )) x <- create_voxel_cube( mni_ras = tbl[, c('x', 'y', 'z')], keys = tbl$key, dimension = c(128, 128, 128) ) n27_path <- file.path(default_template_directory(), "N27") if( interactive() && dir.exists(n27_path) ) { brain <- merge_brain() # or add_voxel_cube(brain, 'example', x$cube) x$add_to_brain(brain, 'example') brain$plot(controllers = list( "Voxel Type" = 'example', 'Right Opacity' = 0.3, 'Left Opacity' = 0.3, 'Background Color' = '#000000' ), voxel_colormap = cmap) }