| Title: | File IO for Intracranial Electroencephalography |
|---|---|
| Description: | Integrated toolbox supporting common file formats used for intracranial Electroencephalography (iEEG) and deep-brain stimulation (DBS) study. |
| Authors: | Zhengjia Wang [aut, cre] (ORCID: <https://orcid.org/0000-0001-5629-1116>) |
| Maintainer: | Zhengjia Wang <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.0 |
| Built: | 2026-05-31 02:52:02 UTC |
| Source: | https://github.com/dipterix/ieegio |
ieegio surfaceConvert other surface formats to ieegio surface
as_ieegio_surface(x, ...) ## Default S3 method: as_ieegio_surface( x, vertices = x, faces = NULL, face_start = NA, transform = NULL, vertex_colors = NULL, annotation_labels = NULL, annotation_values = NULL, measurements = NULL, time_series_slice_duration = NULL, time_series_value = NULL, name = NULL, ... ) ## S3 method for class 'character' as_ieegio_surface(x, ...) ## S3 method for class 'ieegio_surface' as_ieegio_surface(x, ...) ## S3 method for class 'mesh3d' as_ieegio_surface(x, ...) ## S3 method for class 'fs.surface' as_ieegio_surface(x, ...)as_ieegio_surface(x, ...) ## Default S3 method: as_ieegio_surface( x, vertices = x, faces = NULL, face_start = NA, transform = NULL, vertex_colors = NULL, annotation_labels = NULL, annotation_values = NULL, measurements = NULL, time_series_slice_duration = NULL, time_series_value = NULL, name = NULL, ... ) ## S3 method for class 'character' as_ieegio_surface(x, ...) ## S3 method for class 'ieegio_surface' as_ieegio_surface(x, ...) ## S3 method for class 'mesh3d' as_ieegio_surface(x, ...) ## S3 method for class 'fs.surface' as_ieegio_surface(x, ...)
x |
R object or file path |
... |
passed to default method |
vertices |
|
faces |
(optional) face index, either zero or one-indexed
( |
face_start |
(optional) either 0 or 1, indicating whether
|
transform |
(optional) a 4 by 4 matrix indicating the vertex position to
scanner |
vertex_colors |
(optional) integer or color (hex) vector indicating the vertex colors |
annotation_labels |
(optional) a data frame containing at the following
columns. Though optional,
|
annotation_values |
(optional) an integer table where each column is a vector of annotation key (for example, 'FreeSurfer' segmentation key) and each row corresponds to a vertex node |
measurements |
(optional) a numeric table where each column represents
a variable (for example, curvature) and each row corresponds to a
vertex node. Unlike annotations, which is for discrete node values,
|
time_series_slice_duration |
(optional) a numeric vector indicating
the duration of each slice; default is |
time_series_value |
(optional) a numeric matrix ( |
name |
(optional) name of the geometry |
An ieeg_surface object; see read_surface or
'Examples'.
# ---- Simple usage # vertices only dodecahedron_vert <- matrix( ncol = 3, byrow = TRUE, c(-0.62, -0.62, -0.62, 0.62, -0.62, -0.62, -0.62, 0.62, -0.62, 0.62, 0.62, -0.62, -0.62, -0.62, 0.62, 0.62, -0.62, 0.62, -0.62, 0.62, 0.62, 0.62, 0.62, 0.62, 0.00, -0.38, 1.00, 0.00, 0.38, 1.00, 0.00, -0.38, -1.00, 0.00, 0.38, -1.00, -0.38, 1.00, 0.00, 0.38, 1.00, 0.00, -0.38, -1.00, 0.00, 0.38, -1.00, 0.00, 1.00, 0.00, -0.38, 1.00, 0.00, 0.38, -1.00, 0.00, -0.38, -1.00, 0.00, 0.38) ) point_cloud <- as_ieegio_surface(dodecahedron_vert) plot(point_cloud, col = "red") # with face index dodecahedron_face <- matrix( ncol = 3L, byrow = TRUE, c(1, 11, 2, 1, 2, 16, 1, 16, 15, 1, 15, 5, 1, 5, 20, 1, 20, 19, 1, 19, 3, 1, 3, 12, 1, 12, 11, 2, 11, 12, 2, 12, 4, 2, 4, 17, 2, 17, 18, 2, 18, 6, 2, 6, 16, 3, 13, 14, 3, 14, 4, 3, 4, 12, 3, 19, 20, 3, 20, 7, 3, 7, 13, 4, 14, 8, 4, 8, 18, 4, 18, 17, 5, 9, 10, 5, 10, 7, 5, 7, 20, 5, 15, 16, 5, 16, 6, 5, 6, 9, 6, 18, 8, 6, 8, 10, 6, 10, 9, 7, 10, 8, 7, 8, 14, 7, 14, 13) ) mesh <- as_ieegio_surface(dodecahedron_vert, faces = dodecahedron_face) plot(mesh) # with vertex colors mesh <- as_ieegio_surface(dodecahedron_vert, faces = dodecahedron_face, vertex_colors = sample(20)) plot(mesh, name = "color") # with annotations mesh <- as_ieegio_surface( dodecahedron_vert, faces = dodecahedron_face, annotation_labels = data.frame( Key = 1:3, Label = c("A", "B", "C"), Color = c("red", "green", "blue") ), annotation_values = data.frame( MyVariable = c(rep(1, 7), rep(2, 7), rep(3, 6)) ) ) plot(mesh, name = "annotations") # with measurements mesh <- as_ieegio_surface( dodecahedron_vert, faces = dodecahedron_face, measurements = data.frame( MyVariable = dodecahedron_vert[, 1] ) ) plot(mesh, name = "measurements", col = c("blue", "gray", "red"))# ---- Simple usage # vertices only dodecahedron_vert <- matrix( ncol = 3, byrow = TRUE, c(-0.62, -0.62, -0.62, 0.62, -0.62, -0.62, -0.62, 0.62, -0.62, 0.62, 0.62, -0.62, -0.62, -0.62, 0.62, 0.62, -0.62, 0.62, -0.62, 0.62, 0.62, 0.62, 0.62, 0.62, 0.00, -0.38, 1.00, 0.00, 0.38, 1.00, 0.00, -0.38, -1.00, 0.00, 0.38, -1.00, -0.38, 1.00, 0.00, 0.38, 1.00, 0.00, -0.38, -1.00, 0.00, 0.38, -1.00, 0.00, 1.00, 0.00, -0.38, 1.00, 0.00, 0.38, -1.00, 0.00, -0.38, -1.00, 0.00, 0.38) ) point_cloud <- as_ieegio_surface(dodecahedron_vert) plot(point_cloud, col = "red") # with face index dodecahedron_face <- matrix( ncol = 3L, byrow = TRUE, c(1, 11, 2, 1, 2, 16, 1, 16, 15, 1, 15, 5, 1, 5, 20, 1, 20, 19, 1, 19, 3, 1, 3, 12, 1, 12, 11, 2, 11, 12, 2, 12, 4, 2, 4, 17, 2, 17, 18, 2, 18, 6, 2, 6, 16, 3, 13, 14, 3, 14, 4, 3, 4, 12, 3, 19, 20, 3, 20, 7, 3, 7, 13, 4, 14, 8, 4, 8, 18, 4, 18, 17, 5, 9, 10, 5, 10, 7, 5, 7, 20, 5, 15, 16, 5, 16, 6, 5, 6, 9, 6, 18, 8, 6, 8, 10, 6, 10, 9, 7, 10, 8, 7, 8, 14, 7, 14, 13) ) mesh <- as_ieegio_surface(dodecahedron_vert, faces = dodecahedron_face) plot(mesh) # with vertex colors mesh <- as_ieegio_surface(dodecahedron_vert, faces = dodecahedron_face, vertex_colors = sample(20)) plot(mesh, name = "color") # with annotations mesh <- as_ieegio_surface( dodecahedron_vert, faces = dodecahedron_face, annotation_labels = data.frame( Key = 1:3, Label = c("A", "B", "C"), Color = c("red", "green", "blue") ), annotation_values = data.frame( MyVariable = c(rep(1, 7), rep(2, 7), rep(3, 6)) ) ) plot(mesh, name = "annotations") # with measurements mesh <- as_ieegio_surface( dodecahedron_vert, faces = dodecahedron_face, measurements = data.frame( MyVariable = dodecahedron_vert[, 1] ) ) plot(mesh, name = "measurements", col = c("blue", "gray", "red"))
Generic function to convert various objects into ieegio_transforms.
as_ieegio_transform(x, ...) ## S3 method for class ''NULL'' as_ieegio_transform(x, space_from = "", space_to = "", ...) ## S3 method for class 'character' as_ieegio_transform(x, format = c("ants", "flirt"), ...) ## S3 method for class 'matrix' as_ieegio_transform(x, space_from = "", space_to = "", ...) ## S3 method for class 'array' as_ieegio_transform(x, space_from = "", space_to = "", ...) ## S3 method for class 'list' as_ieegio_transform(x, ...) ## S3 method for class 'ieegio_transforms' as_ieegio_transform(x, ...)as_ieegio_transform(x, ...) ## S3 method for class ''NULL'' as_ieegio_transform(x, space_from = "", space_to = "", ...) ## S3 method for class 'character' as_ieegio_transform(x, format = c("ants", "flirt"), ...) ## S3 method for class 'matrix' as_ieegio_transform(x, space_from = "", space_to = "", ...) ## S3 method for class 'array' as_ieegio_transform(x, space_from = "", space_to = "", ...) ## S3 method for class 'list' as_ieegio_transform(x, ...) ## S3 method for class 'ieegio_transforms' as_ieegio_transform(x, ...)
x |
object to convert (character path, matrix, array, list, or existing transform) |
... |
additional arguments passed to methods |
space_from |
source space for matrix/array methods. Default |
space_to |
target space for matrix/array methods. Default |
format |
character string specifying the file format for character paths.
Supports |
Methods available:
character: Reads transform from file (uses io_read_ants_transform
or io_read_flirt_transform depending on format)
matrix: Creates transform from matrix
array: Creates transform from 2D array
list: Creates transform chain from list of transforms
ieegio_transforms: Returns input unchanged
An ieegio_transforms object
'ieegio' image volumesConvert array, path, or 'NIfTI' images in other formats to 'ieegio'
image volume instance
as_ieegio_volume(x, ...) ## S3 method for class 'character' as_ieegio_volume(x, ...) ## S3 method for class 'ieegio_volume' as_ieegio_volume(x, ...) ## S3 method for class 'array' as_ieegio_volume(x, vox2ras = NULL, as_color = is.character(x), ...) ## S3 method for class 'niftiImage' as_ieegio_volume(x, ...) ## S3 method for class 'nifti' as_ieegio_volume(x, ...) ## S3 method for class 'ants.core.ants_image.ANTsImage' as_ieegio_volume(x, ...)as_ieegio_volume(x, ...) ## S3 method for class 'character' as_ieegio_volume(x, ...) ## S3 method for class 'ieegio_volume' as_ieegio_volume(x, ...) ## S3 method for class 'array' as_ieegio_volume(x, vox2ras = NULL, as_color = is.character(x), ...) ## S3 method for class 'niftiImage' as_ieegio_volume(x, ...) ## S3 method for class 'nifti' as_ieegio_volume(x, ...) ## S3 method for class 'ants.core.ants_image.ANTsImage' as_ieegio_volume(x, ...)
x |
R object such as array, image path, or objects such as
|
... |
passed to other methods |
vox2ras |
a |
as_color |
for converting arrays to volume, whether to treat |
An ieegio volume object; see imaging-volume
shape <- c(50, 50, 50) vox2ras <- matrix( c(-1, 0, 0, 25, 0, 0, 1, -25, 0, -1, 0, 25, 0, 0, 0, 1), nrow = 4, byrow = TRUE ) # continuous x <- array(rnorm(125000), shape) volume <- as_ieegio_volume(x, vox2ras = vox2ras) plot(volume, zoom = 3, pixel_width = 0.5) # color rgb(a) x <- array( sample(c("red","blue", "green", "cyan", "yellow"), 12500, replace = TRUE), shape ) rgb <- as_ieegio_volume(x, vox2ras = vox2ras) plot(rgb, zoom = 3, pixel_width = 0.5) # ---- When RNifti package is not available --------------------------- # Emulate WebAssemply when RNifti is unavailable, using oro.nifti instead old_opt <- options("ieegio.debug.emscripten" = TRUE) on.exit({ options(old_opt) }, add = TRUE) shape <- c(50, 50, 50) vox2ras <- matrix( c(-1, 0, 0, 25, 0, 0, 1, -25, 0, -1, 0, 25, 0, 0, 0, 1), nrow = 4, byrow = TRUE ) # continuous x <- array(rnorm(125000), shape) # In WebAssemply, RNifti is not available, using oro.nifti instead volume <- as_ieegio_volume(x, vox2ras = vox2ras) stopifnot(volume$type[[1]] == "oro") plot(volume, zoom = 3, pixel_width = 0.5) # Cleanup: make sure the options are reset options(old_opt)shape <- c(50, 50, 50) vox2ras <- matrix( c(-1, 0, 0, 25, 0, 0, 1, -25, 0, -1, 0, 25, 0, 0, 0, 1), nrow = 4, byrow = TRUE ) # continuous x <- array(rnorm(125000), shape) volume <- as_ieegio_volume(x, vox2ras = vox2ras) plot(volume, zoom = 3, pixel_width = 0.5) # color rgb(a) x <- array( sample(c("red","blue", "green", "cyan", "yellow"), 12500, replace = TRUE), shape ) rgb <- as_ieegio_volume(x, vox2ras = vox2ras) plot(rgb, zoom = 3, pixel_width = 0.5) # ---- When RNifti package is not available --------------------------- # Emulate WebAssemply when RNifti is unavailable, using oro.nifti instead old_opt <- options("ieegio.debug.emscripten" = TRUE) on.exit({ options(old_opt) }, add = TRUE) shape <- c(50, 50, 50) vox2ras <- matrix( c(-1, 0, 0, 25, 0, 0, 1, -25, 0, -1, 0, 25, 0, 0, 0, 1), nrow = 4, byrow = TRUE ) # continuous x <- array(rnorm(125000), shape) # In WebAssemply, RNifti is not available, using oro.nifti instead volume <- as_ieegio_volume(x, vox2ras = vox2ras) stopifnot(volume$type[[1]] == "oro") plot(volume, zoom = 3, pixel_width = 0.5) # Cleanup: make sure the options are reset options(old_opt)
Internal method to extract header information from a 'NIfTI' file
as_nifti_header(x)as_nifti_header(x)
x |
file path or an R object |
A list containing the file header information
Burn density values along a Catmull-Rom spline trajectory into a numeric
volume. The curve is sampled at sub-voxel resolution and voxels within
thickness of the trajectory are assigned density values.
burn_curve( image, curve, thickness = 1, density = 1, reshape = FALSE, antialias_type = c("reduced", "ignore", "fill", "threshold"), merge = c("mean", "max", "min"), n_samples = NULL, ... )burn_curve( image, curve, thickness = 1, density = 1, reshape = FALSE, antialias_type = c("reduced", "ignore", "fill", "threshold"), merge = c("mean", "max", "min"), n_samples = NULL, ... )
image |
volume providing the coordinate space; see
|
curve |
a |
thickness |
tube radius (half-width) around the curve in world ('RAS')
coordinates (millimeters). Can be a positive scalar or a function of
|
density |
value to burn into voxels within the tube. Can be a numeric
scalar or a function of |
reshape |
whether to reshape the image before burning; identical
semantics to |
antialias_type |
how to handle voxels at the edge of the tube.
One of
|
merge |
how to combine density values when multiple curve samples
illuminate the same voxel. One of |
n_samples |
number of points to sample along the curve. Default
|
... |
passed to |
A numeric ieegio_volume with the same spatial extent as
image (or the reshaped extent). Background voxels contain 0.
When multiple curve samples illuminate the same voxel, values are combined
according to merge.
if (interactive()) { dm <- c(50, 50, 50) image <- as_ieegio_volume( array(0, dm), vox2ras = rbind(cbind(diag(1, 3), -dm / 2), c(0, 0, 0, 1)) ) # Three-point trajectory (Catmull-Rom from matrix) key_pts <- rbind(c(-50, 0, 0), c(0, 20, 2), c(-10, 0, -1)) curve <- ravetools::catmull_rom_3d(key_pts) plot(curve, use_rgl = FALSE) # Constant thickness and density burned <- burn_curve(image, key_pts, thickness = 3, density = 100) plot(burned, zoom = 3, position = c(0, 0, 0), which = "axial") # Varying thickness and density along the curve burned2 <- burn_curve( image, curve, thickness = function(t) 2 + t * 4, density = function(t) 100 * (1 - t) + 100, antialias_type = "reduced" ) plot(burned2, zoom = 3, position = c(0, 0, 0), which = "axial") }if (interactive()) { dm <- c(50, 50, 50) image <- as_ieegio_volume( array(0, dm), vox2ras = rbind(cbind(diag(1, 3), -dm / 2), c(0, 0, 0, 1)) ) # Three-point trajectory (Catmull-Rom from matrix) key_pts <- rbind(c(-50, 0, 0), c(0, 20, 2), c(-10, 0, -1)) curve <- ravetools::catmull_rom_3d(key_pts) plot(curve, use_rgl = FALSE) # Constant thickness and density burned <- burn_curve(image, key_pts, thickness = 3, density = 100) plot(burned, zoom = 3, position = c(0, 0, 0), which = "axial") # Varying thickness and density along the curve burned2 <- burn_curve( image, curve, thickness = function(t) 2 + t * 4, density = function(t) 100 * (1 - t) + 100, antialias_type = "reduced" ) plot(burned2, zoom = 3, position = c(0, 0, 0), which = "axial") }
Burn image at given positions with given color and radius.
burn_volume( image, ras_position, col = "red", radius = 1, reshape = FALSE, alpha = FALSE, blank_underlay = FALSE, ..., preview = NULL )burn_volume( image, ras_position, col = "red", radius = 1, reshape = FALSE, alpha = FALSE, blank_underlay = FALSE, ..., preview = NULL )
image |
volume |
ras_position |
image-defined right-anterior-posterior positions, an
|
col |
vector of integer or characters, color of each contact |
radius |
vector of positive number indicating the burning radius |
reshape |
whether to reshape the image at a different resolution;
default is false; can be |
alpha |
whether to include alpha (transparent) channel. Default is
false for compatibility concerns (legacy software might not support
reading alpha channel). In this case, the background will be black.
If |
blank_underlay |
whether to use blank image or the input
|
... |
passed to |
preview |
indices (integer) of the position to visualize; default is
|
Color image that is burnt; see imaging-volume.
if(interactive()) { dim <- c(6, 6, 6) image <- as_ieegio_volume( array(rnorm(prod(dim)), dim), vox2ras = rbind(cbind(diag(1, 3), -dim / 2), c(0, 0, 0, 1)) ) ras_positions <- rbind(c(1, -1, 1.5), c(-2.25, -1, -0.75)) burned <- burn_volume( image, ras_positions, col = c("red", "green"), radius = 0.5, reshape = c(24, 24, 24) ) plot( burned, position = ras_positions[1, ], zoom = 15, pixel_width = 0.25 ) }if(interactive()) { dim <- c(6, 6, 6) image <- as_ieegio_volume( array(rnorm(prod(dim)), dim), vox2ras = rbind(cbind(diag(1, 3), -dim / 2), c(0, 0, 0, 1)) ) ras_positions <- rbind(c(1, -1, 1.5), c(-2.25, -1, -0.75)) burned <- burn_volume( image, ras_positions, col = c("red", "green"), radius = 0.5, reshape = c(24, 24, 24) ) plot( burned, position = ras_positions[1, ], zoom = 15, pixel_width = 0.25 ) }
'HDF5', 'CSV' are common file formats that can be read into 'Matlab' or 'Python'
convert_fst_to_hdf5(fst_path, hdf5_path, exclude_names = NULL) convert_fst_to_csv(fst_path, csv_path, exclude_names = NULL)convert_fst_to_hdf5(fst_path, hdf5_path, exclude_names = NULL) convert_fst_to_csv(fst_path, csv_path, exclude_names = NULL)
fst_path |
path to 'FST' file |
hdf5_path |
path to 'HDF5' file; if file exists before the conversion, the file will be erased first. Please make sure the files are backed up. |
exclude_names |
table names to exclude |
csv_path |
path to 'CSV' file; if file exists before the conversion, the file will be erased first. Please make sure the files are backed up. |
convert_fst_to_hdf5 will return a list of data saved to 'HDF5';
convert_fst_to_csv returns the normalized 'CSV' path.
Download sample files
ieegio_sample_data(file, test = FALSE, cache_ok = TRUE)ieegio_sample_data(file, test = FALSE, cache_ok = TRUE)
file |
file to download; set to |
test |
test whether the sample file exists instead of downloading them;
default is |
cache_ok |
whether to use cache |
When test is false, returns downloaded file path
(character); when test is true, returns whether the expected
sample exists (logical).
# list available files ieegio_sample_data() # check if file edfPlusD.edf exists ieegio_sample_data("edfPlusD.edf", test = TRUE) ## Not run: ieegio_sample_data("edfPlusD.edf") ## End(Not run)# list available files ieegio_sample_data() # check if file edfPlusD.edf exists ieegio_sample_data("edfPlusD.edf", test = TRUE) ## Not run: ieegio_sample_data("edfPlusD.edf") ## End(Not run)
High-level functions to read and write streamlines, supporting 'TCK',
'TRK', 'TT' (read-only), 'VTK' poly-data (including
legacy '.vtk', 'XML'-based '.vtp', 'HDF5'-based '.vtpb')
read_streamlines(file, ...) write_streamlines( x, con, format = c("auto", "tck", "trk", "vtk", "vtp", "vtpb"), ... ) as_ieegio_streamlines(x, ...) ## Default S3 method: as_ieegio_streamlines(x, vox2ras = NULL, ..., class = NULL)read_streamlines(file, ...) write_streamlines( x, con, format = c("auto", "tck", "trk", "vtk", "vtp", "vtpb"), ... ) as_ieegio_streamlines(x, ...) ## Default S3 method: as_ieegio_streamlines(x, vox2ras = NULL, ..., class = NULL)
file, con
|
path to the streamline data |
... |
passed to low-level functions accordingly |
x |
R object that can be converted into an |
format |
format to write to file, the file extensions must match with the format |
vox2ras |
volume index to 'RAS' coordinate transform matrix;
default is identity matrix and used by |
class |
additional class to be added to the instance |
read_streamlines and as_ieegio_streamlines returns
a streamlines instance.
# toy example curve <- function(t) { x <- sin(4 * t + sample(300, 1) / 100) + t + sample(seq_along(t)) / length(t) / 10 y <- cos(sin(t) + 5 * t) + sample(seq_along(t)) / length(t) / 10 z <- t * 3 cbind(x, y, z) } # 10 lines, each line is represented by nx3 matrix tracts <- lapply(seq(100, 109), function(n) { curve(seq_len(n) / 100) }) # convert to streamline x <- as_ieegio_streamlines(tracts) # Display print(x) plot(x, col = 1:10) if(system.file(package = "r3js") != '') { plot(x, method = "r3js") } # Subset the first line (transformed) coords <- x[[1]]$coords head(coords) # Save different formats tdir <- tempfile() dir.create(tdir, showWarnings = FALSE, recursive = TRUE) write_streamlines(x, file.path(tdir, "sample.tck")) write_streamlines(x, file.path(tdir, "sample.trk")) write_streamlines(x, file.path(tdir, "sample.trk.gz")) ## Not run: # Require Python write_streamlines(x, file.path(tdir, "sample.vtk")) write_streamlines(x, file.path(tdir, "sample.vtp")) write_streamlines(x, file.path(tdir, "sample.vtpb")) ## End(Not run) # Read formats y <- read_streamlines(file.path(tdir, "sample.trk")) # Compare x and y diffs <- mapply( x = as.vector(x), y = as.vector(y), function(x, y) { range(x$coords - y$coords) } ) # Should be floating errors max(abs(diffs)) unlink(tdir, recursive = TRUE)# toy example curve <- function(t) { x <- sin(4 * t + sample(300, 1) / 100) + t + sample(seq_along(t)) / length(t) / 10 y <- cos(sin(t) + 5 * t) + sample(seq_along(t)) / length(t) / 10 z <- t * 3 cbind(x, y, z) } # 10 lines, each line is represented by nx3 matrix tracts <- lapply(seq(100, 109), function(n) { curve(seq_len(n) / 100) }) # convert to streamline x <- as_ieegio_streamlines(tracts) # Display print(x) plot(x, col = 1:10) if(system.file(package = "r3js") != '') { plot(x, method = "r3js") } # Subset the first line (transformed) coords <- x[[1]]$coords head(coords) # Save different formats tdir <- tempfile() dir.create(tdir, showWarnings = FALSE, recursive = TRUE) write_streamlines(x, file.path(tdir, "sample.tck")) write_streamlines(x, file.path(tdir, "sample.trk")) write_streamlines(x, file.path(tdir, "sample.trk.gz")) ## Not run: # Require Python write_streamlines(x, file.path(tdir, "sample.vtk")) write_streamlines(x, file.path(tdir, "sample.vtp")) write_streamlines(x, file.path(tdir, "sample.vtpb")) ## End(Not run) # Read formats y <- read_streamlines(file.path(tdir, "sample.trk")) # Compare x and y diffs <- mapply( x = as.vector(x), y = as.vector(y), function(x, y) { range(x$coords - y$coords) } ) # Should be floating errors max(abs(diffs)) unlink(tdir, recursive = TRUE)
Supports surface geometry, annotation, measurement, and
time-series data.
Please use the high-level function read_surface, which calls
other low-level functions internally.
read_surface(file, format = "auto", type = NULL, ...) write_surface( x, con, format = c("gifti", "freesurfer"), type = c("geometry", "annotations", "measurements", "color", "time_series"), ..., name = 1 ) io_read_fs( file, type = c("geometry", "annotations", "measurements"), format = "auto", name = basename(file), ... ) io_read_gii(file) io_write_gii(x, con, ...)read_surface(file, format = "auto", type = NULL, ...) write_surface( x, con, format = c("gifti", "freesurfer"), type = c("geometry", "annotations", "measurements", "color", "time_series"), ..., name = 1 ) io_read_fs( file, type = c("geometry", "annotations", "measurements"), format = "auto", name = basename(file), ... ) io_read_gii(file) io_write_gii(x, con, ...)
file, con
|
path the file |
format |
format of the file, for |
type |
type of the data; ignored if the file format is 'GIfTI'. For 'FreeSurfer' files, supported types are
|
... |
for |
x |
surface (geometry, annotation, measurement) data |
name |
name of the data; for |
A surface object container for read_surface, and
the file path for write_surface
library(ieegio) # geometry geom_file <- "gifti/GzipBase64/sujet01_Lwhite.surf.gii" # measurements shape_file <- "gifti/GzipBase64/sujet01_Lwhite.shape.gii" # time series ts_file <- "gifti/GzipBase64/fmri_sujet01_Lwhite_projection.time.gii" if(ieegio_sample_data(geom_file, test = TRUE)) { geometry <- read_surface(ieegio_sample_data(geom_file)) print(geometry) measurement <- read_surface(ieegio_sample_data(shape_file)) print(measurement) time_series <- read_surface(ieegio_sample_data(ts_file)) print(time_series) # merge measurement & time_series into geometry merged <- merge(geometry, measurement, time_series) print(merged) # make sure you install `rgl` package plot(merged, name = c("measurements", "Shape001")) plot(merged, name = "time_series", slice_index = c(1, 11, 21, 31)) }library(ieegio) # geometry geom_file <- "gifti/GzipBase64/sujet01_Lwhite.surf.gii" # measurements shape_file <- "gifti/GzipBase64/sujet01_Lwhite.shape.gii" # time series ts_file <- "gifti/GzipBase64/fmri_sujet01_Lwhite_projection.time.gii" if(ieegio_sample_data(geom_file, test = TRUE)) { geometry <- read_surface(ieegio_sample_data(geom_file)) print(geometry) measurement <- read_surface(ieegio_sample_data(shape_file)) print(measurement) time_series <- read_surface(ieegio_sample_data(ts_file)) print(time_series) # merge measurement & time_series into geometry merged <- merge(geometry, measurement, time_series) print(merged) # make sure you install `rgl` package plot(merged, name = c("measurements", "Shape001")) plot(merged, name = "time_series", slice_index = c(1, 11, 21, 31)) }
Read and write volume data ('MRI', 'CT', etc.) in 'NIfTI' or 'MGH' formats.
Please use read_volume and write_volume for high-level
function. These functions
will call other low-level functions internally.
read_volume(file, header_only = FALSE, format = c("auto", "nifti", "mgh"), ...) write_volume(x, con, format = c("auto", "nifti", "mgh"), ...) io_read_mgz(file, header_only = FALSE) io_write_mgz(x, con, ...) ## S3 method for class 'ieegio_volume' io_write_mgz(x, con, ...) ## S3 method for class 'ieegio_mgh' io_write_mgz(x, con, ...) ## S3 method for class 'nifti' io_write_mgz(x, con, ...) ## S3 method for class 'niftiImage' io_write_mgz(x, con, ...) ## S3 method for class 'ants.core.ants_image.ANTsImage' io_write_mgz(x, con, ...) ## S3 method for class 'array' io_write_mgz(x, con, vox2ras = NULL, ...) io_read_nii( file, method = c("rnifti", "oro", "ants"), header_only = FALSE, ... ) io_write_nii(x, con, ...) ## S3 method for class 'ieegio_nifti' io_write_nii(x, con, ...) ## S3 method for class 'ants.core.ants_image.ANTsImage' io_write_nii(x, con, ...) ## S3 method for class 'niftiImage' io_write_nii(x, con, ...) ## S3 method for class 'nifti' io_write_nii(x, con, gzipped = NA, ...) ## S3 method for class 'ieegio_mgh' io_write_nii(x, con, ...) ## S3 method for class 'array' io_write_nii( x, con, vox2ras = NULL, datatype_code = NULL, xyzt_units = c("NIFTI_UNITS_MM", "NIFTI_UNITS_SEC"), intent_code = "NIFTI_INTENT_NONE", ..., gzipped = NA )read_volume(file, header_only = FALSE, format = c("auto", "nifti", "mgh"), ...) write_volume(x, con, format = c("auto", "nifti", "mgh"), ...) io_read_mgz(file, header_only = FALSE) io_write_mgz(x, con, ...) ## S3 method for class 'ieegio_volume' io_write_mgz(x, con, ...) ## S3 method for class 'ieegio_mgh' io_write_mgz(x, con, ...) ## S3 method for class 'nifti' io_write_mgz(x, con, ...) ## S3 method for class 'niftiImage' io_write_mgz(x, con, ...) ## S3 method for class 'ants.core.ants_image.ANTsImage' io_write_mgz(x, con, ...) ## S3 method for class 'array' io_write_mgz(x, con, vox2ras = NULL, ...) io_read_nii( file, method = c("rnifti", "oro", "ants"), header_only = FALSE, ... ) io_write_nii(x, con, ...) ## S3 method for class 'ieegio_nifti' io_write_nii(x, con, ...) ## S3 method for class 'ants.core.ants_image.ANTsImage' io_write_nii(x, con, ...) ## S3 method for class 'niftiImage' io_write_nii(x, con, ...) ## S3 method for class 'nifti' io_write_nii(x, con, gzipped = NA, ...) ## S3 method for class 'ieegio_mgh' io_write_nii(x, con, ...) ## S3 method for class 'array' io_write_nii( x, con, vox2ras = NULL, datatype_code = NULL, xyzt_units = c("NIFTI_UNITS_MM", "NIFTI_UNITS_SEC"), intent_code = "NIFTI_INTENT_NONE", ..., gzipped = NA )
file |
file path to read volume data |
header_only |
whether to read header data only;
default is |
format |
format of the file to be written; choices are |
... |
passed to other methods |
x |
volume data (such as 'NIfTI' image, array, or 'MGH') to be saved |
con |
file path to store image |
vox2ras |
a |
method |
method to read the file; choices are |
gzipped |
for writing |
datatype_code, xyzt_units, intent_code
|
additional flags for 'NIfTI' headers, for advanced users |
format of the file; default is auto-detection, other choices are
'nifti' and 'mgh';
Imaging readers return ieegio_volume objects. The writers
return the file path to where the file is saved to.
library(ieegio) nifti_file <- "brain.demosubject.nii.gz" # Use `ieegio_sample_data(nifti_file)` # to download sample data if( ieegio_sample_data(nifti_file, test = TRUE) ) { # ---- NIfTI examples --------------------------------------------- file <- ieegio_sample_data(nifti_file) # basic read vol <- read_volume(file) # voxel to scanner RAS vol$transforms$vox2ras # to freesurfer surface vol$transforms$vox2ras_tkr # to FSL vol$transforms$vox2fsl plot(vol, position = c(10, 0, 30)) # ---- using other methods -------------------------------------- # default vol <- read_volume(file, method = "rnifti", format = "nifti") vol$header # lazy-load nifti vol2 <- read_volume(file, method = "oro", format = "nifti") vol2$header ## Not run: # requires additional python environment # Using ANTsPyx vol3 <- read_volume(file, method = "ants", format = "nifti") vol3$header ## End(Not run) # ---- write -------------------------------------------------------- # write as NIfTI f <- tempfile(fileext = ".nii.gz") write_volume(vol, f, format = "nifti") # alternative method write_volume(vol$header, f, format = "nifti") # write to mgz/mgh f2 <- tempfile(fileext = ".mgz") write_volume(vol, f, format = "mgh") # clean up unlink(f) unlink(f2) # ---- Special case in WebAsssembly -------------------------------- # oro.nifti backend is always used # Emulate WebAssemply when RNifti is unavailable, using oro.nifti instead old_opt <- options("ieegio.debug.emscripten" = TRUE) on.exit({ options(old_opt) }, add = TRUE) # In WebAssemply, RNifti is not available, using oro.nifti instead vol <- read_volume(file) stopifnot(vol$type[[1]] == "oro") # Cleanup: make sure the options are reset options(old_opt) }library(ieegio) nifti_file <- "brain.demosubject.nii.gz" # Use `ieegio_sample_data(nifti_file)` # to download sample data if( ieegio_sample_data(nifti_file, test = TRUE) ) { # ---- NIfTI examples --------------------------------------------- file <- ieegio_sample_data(nifti_file) # basic read vol <- read_volume(file) # voxel to scanner RAS vol$transforms$vox2ras # to freesurfer surface vol$transforms$vox2ras_tkr # to FSL vol$transforms$vox2fsl plot(vol, position = c(10, 0, 30)) # ---- using other methods -------------------------------------- # default vol <- read_volume(file, method = "rnifti", format = "nifti") vol$header # lazy-load nifti vol2 <- read_volume(file, method = "oro", format = "nifti") vol2$header ## Not run: # requires additional python environment # Using ANTsPyx vol3 <- read_volume(file, method = "ants", format = "nifti") vol3$header ## End(Not run) # ---- write -------------------------------------------------------- # write as NIfTI f <- tempfile(fileext = ".nii.gz") write_volume(vol, f, format = "nifti") # alternative method write_volume(vol$header, f, format = "nifti") # write to mgz/mgh f2 <- tempfile(fileext = ".mgz") write_volume(vol, f, format = "mgh") # clean up unlink(f) unlink(f2) # ---- Special case in WebAsssembly -------------------------------- # oro.nifti backend is always used # Emulate WebAssemply when RNifti is unavailable, using oro.nifti instead old_opt <- options("ieegio.debug.emscripten" = TRUE) on.exit({ options(old_opt) }, add = TRUE) # In WebAssemply, RNifti is not available, using oro.nifti instead vol <- read_volume(file) stopifnot(vol$type[[1]] == "oro") # Cleanup: make sure the options are reset options(old_opt) }
Check whether a 'HDF5' file can be opened for read/write
io_h5_valid(file, mode = c("r", "w"), close_all = FALSE) io_h5_names(file)io_h5_valid(file, mode = c("r", "w"), close_all = FALSE) io_h5_names(file)
file |
path to file |
mode |
|
close_all |
whether to close all connections or just close current
connection; default is false. Set this to |
io_h5_valid returns a logical value indicating whether the
file can be opened. io_h5_names returns a character vector of
dataset names.
x <- array(1:27, c(3,3,3)) f <- tempfile() # No data written to the file, hence invalid io_h5_valid(f, 'r') io_write_h5(x, f, 'dset') io_h5_valid(f, 'w') # Open the file and hold a connection ptr <- hdf5r::H5File$new(filename = f, mode = 'w') # Can read, but cannot write io_h5_valid(f, 'r') # TRUE io_h5_valid(f, 'w') # FALSE # However, this can be reset via `close_all=TRUE` io_h5_valid(f, 'r', close_all = TRUE) io_h5_valid(f, 'w') # TRUE # Now the connection is no longer valid ptr # clean up unlink(f)x <- array(1:27, c(3,3,3)) f <- tempfile() # No data written to the file, hence invalid io_h5_valid(f, 'r') io_write_h5(x, f, 'dset') io_h5_valid(f, 'w') # Open the file and hold a connection ptr <- hdf5r::H5File$new(filename = f, mode = 'w') # Can read, but cannot write io_h5_valid(f, 'r') # TRUE io_h5_valid(f, 'w') # FALSE # However, this can be reset via `close_all=TRUE` io_h5_valid(f, 'r', close_all = TRUE) io_h5_valid(f, 'w') # TRUE # Now the connection is no longer valid ptr # clean up unlink(f)
ANTs transform fileReads spatial transformation files in ANTs (Advanced Normalization Tools)
format, including affine matrices (.mat) and deformation fields
(.h5, .nii.gz).
io_read_ants_transform( file, space_from, space_to, interpretation = c("passive", "active") )io_read_ants_transform( file, space_from, space_to, interpretation = c("passive", "active") )
file |
character string specifying the path to the transform file. Supported formats include:
|
space_from |
character string or |
space_to |
character string or |
interpretation |
character string specifying how to interpret the transform:
|
ANTs transforms operate in LPS (Left-Posterior-Superior) coordinate
convention. The returned transform object automatically sets orientation
to "LPS" for both source and target spaces.
For composite transforms (e.g., .h5 files containing both affine
and deformation components), the function returns a single transform object.
Use as_ieegio_transform with a list to combine multiple transforms.
This function requires the rpyANTs package and a configured Python
environment.
An ieegio_transforms object with:
List containing the transform data (matrix for affine,
ANTsTransform object for deformation)
"affine" or "deformation"
"active" or "passive"
Source space (with "LPS" orientation for ANTs)
Target space (with "LPS" orientation for ANTs)
Spatial dimension (typically 3)
The function can automatically infer space names from BIDS-compliant file names:
from-<source>: Source space identifier
to-<target>: Target space identifier
Example: "sub-01_from-T1w_to-MNI152NLin2009cAsym_mode-image_xfm.h5"
as_ieegio_transform for converting objects to transforms and chaining
transform_orientation for orientation conversion transforms
## Not run: # Read an affine transform xfm <- io_read_ants_transform("sub-01_from-T1w_to-MNI_xfm.mat") # Explicitly specify spaces xfm <- io_read_ants_transform( "transform.h5", space_from = "native", space_to = "MNI152" ) # Read as active (point) transform xfm <- io_read_ants_transform( "transform.mat", interpretation = "active" ) # Chain multiple transforms xfm1 <- io_read_ants_transform("from-T1w_to-T2w_xfm.mat") xfm2 <- io_read_ants_transform("from-T2w_to-MNI_xfm.h5") combined <- as_ieegio_transform(list(xfm1, xfm2)) ## End(Not run)## Not run: # Read an affine transform xfm <- io_read_ants_transform("sub-01_from-T1w_to-MNI_xfm.mat") # Explicitly specify spaces xfm <- io_read_ants_transform( "transform.h5", space_from = "native", space_to = "MNI152" ) # Read as active (point) transform xfm <- io_read_ants_transform( "transform.mat", interpretation = "active" ) # Chain multiple transforms xfm1 <- io_read_ants_transform("from-T1w_to-T2w_xfm.mat") xfm2 <- io_read_ants_transform("from-T2w_to-MNI_xfm.h5") combined <- as_ieegio_transform(list(xfm1, xfm2)) ## End(Not run)
Reads a 4x4 affine transformation matrix from an FSL FLIRT output file. FLIRT matrices operate in FSL scaled-voxel coordinate system and require source and reference images to convert to world (RAS) coordinates.
io_read_flirt_transform(file, space_from, space_to)io_read_flirt_transform(file, space_from, space_to)
file |
character string specifying the path to the FLIRT matrix file. This is a plain text file containing a 4x4 affine matrix. |
space_from |
character string or |
space_to |
character string or |
FLIRT matrices operate in FSL scaled-voxel coordinate system, which is:
Voxel indices multiplied by voxel sizes (pixdim)
X-axis inverted if the image has positive sform determinant
(neurological convention)
The returned transform has "FSL" orientation for both source and
target spaces. To convert to world (RAS) coordinates, use
transform_flirt2ras with the source and/or reference images.
FLIRT matrices are active transforms: they map point coordinates from the source (moving) image space to the reference (fixed) image space.
An ieegio_transforms object with:
List containing the 4x4 FLIRT matrix
"affine"
"active" (FLIRT matrices are point transforms)
Source space (with "FSL" orientation)
Target space (with "FSL" orientation)
3
The function can automatically infer space names from BIDS-compliant file names:
from-<source>: Source space identifier
to-<target>: Target space identifier
transform_flirt2ras for converting to world coordinates
io_read_ants_transform for reading ANTs format transforms
as_ieegio_transform for converting objects to transforms
## Not run: # Read a FLIRT matrix xfm <- io_read_flirt_transform("source_to_reference.mat") # Convert to RAS coordinates (requires source and reference images) xfm_ras <- transform_flirt2ras(xfm, source = "source.nii.gz", reference = "reference.nii.gz") # Explicitly specify spaces xfm <- io_read_flirt_transform( "transform.mat", space_from = "T1w", space_to = "MNI152" ) ## End(Not run)## Not run: # Read a FLIRT matrix xfm <- io_read_flirt_transform("source_to_reference.mat") # Convert to RAS coordinates (requires source and reference images) xfm_ras <- transform_flirt2ras(xfm, source = "source.nii.gz", reference = "reference.nii.gz") # Explicitly specify spaces xfm <- io_read_flirt_transform( "transform.mat", space_from = "T1w", space_to = "MNI152" ) ## End(Not run)
Experimental function; use with caution.
io_read_fstarray_or_h5( fst_path, h5_path, h5_name, fst_need_transpose = FALSE, fst_need_drop = FALSE, ram = FALSE )io_read_fstarray_or_h5( fst_path, h5_path, h5_name, fst_need_transpose = FALSE, fst_need_drop = FALSE, ram = FALSE )
fst_path |
'FST' file cache path |
h5_path |
alternative 'HDF5' file path |
h5_name |
'HDF5' data name |
fst_need_transpose |
does 'FST' data need transpose? |
fst_need_drop |
drop dimensions |
ram |
whether to load to memory directly or perform lazy loading |
RAVE stores data with redundancy. One electrode data
is usually saved with two copies in different formats: 'HDF5' and
'FST', where 'HDF5' is cross-platform and supported by multiple
languages such as Matlab, Python, etc, while 'FST'
format is supported by R only, with super high read/write speed.
load_fst_or_h5 checks whether the presence of 'FST' file,
if failed, then it reads data from persistent 'HDF5' file.
If 'FST' cache file exists, returns LazyFST object,
otherwise returns LazyH5 instance
hdf5r-package
Wrapper for class LazyH5, which load data with
"lazy" mode - only read part of dataset when needed.
io_read_h5(file, name, read_only = TRUE, ram = FALSE, quiet = FALSE)io_read_h5(file, name, read_only = TRUE, ram = FALSE, quiet = FALSE)
file |
'HDF5' file |
name |
|
read_only |
only used if |
ram |
load data to memory immediately, default is false |
quiet |
whether to suppress messages |
If ram is true, then return data as arrays, otherwise return
a LazyH5 instance.
file <- tempfile() x <- array(1:120, dim = c(4,5,6)) # save x to file with name /group/dataset/1 io_write_h5(x, file, '/group/dataset/1', quiet = TRUE) # read data y <- io_read_h5(file, '/group/dataset/1', ram = TRUE) class(y) # array z <- io_read_h5(file, '/group/dataset/1', ram = FALSE) class(z) # LazyH5 dim(z) # clean up unlink(file)file <- tempfile() x <- array(1:120, dim = c(4,5,6)) # save x to file with name /group/dataset/1 io_write_h5(x, file, '/group/dataset/1', quiet = TRUE) # read data y <- io_read_h5(file, '/group/dataset/1', ram = TRUE) class(y) # array z <- io_read_h5(file, '/group/dataset/1', ram = FALSE) class(z) # LazyH5 dim(z) # clean up unlink(file)
Save objects to 'HDF5' file without trivial checks
io_write_h5( x, file, name, chunk = "auto", level = 4, replace = TRUE, new_file = FALSE, ctype = NULL, quiet = FALSE, ... )io_write_h5( x, file, name, chunk = "auto", level = 4, replace = TRUE, new_file = FALSE, ctype = NULL, quiet = FALSE, ... )
x |
an array, a matrix, or a vector |
file |
path to 'HDF5' file |
name |
path/name of the data; for example, |
chunk |
chunk size |
level |
compress level from 0 - no compression to 10 - max compression |
replace |
should data be replaced if exists |
new_file |
should removing the file if old one exists |
ctype |
data type such as "character", "integer", or "numeric". If
set to |
quiet |
whether to suppress messages, default is false |
... |
passed to other |
Absolute path of the file saved
file <- tempfile() x <- array(1:120, dim = 2:5) # save x to file with name /group/dataset/1 io_write_h5(x, file, '/group/dataset/1', chunk = dim(x)) # load data y <- io_read_h5(file, '/group/dataset/1') # read data to memory y[] # clean up unlink(file)file <- tempfile() x <- array(1:120, dim = 2:5) # save x to file with name /group/dataset/1 io_write_h5(x, file, '/group/dataset/1', chunk = dim(x)) # load data y <- io_read_h5(file, '/group/dataset/1') # read data to memory y[] # clean up unlink(file)
'TCK' streamlinesLow-level functions; for high-level functions,
please use read_streamlines or
as_ieegio_streamlines instead.
Low-level functions, supports compressed files; for high-level functions,
please use read_streamlines or
as_ieegio_streamlines instead.
io_read_tck(file) io_write_tck( x, con, datatype = c("Float32LE", "Float32BE", "Float64LE", "Float64BE") ) io_read_trk(file, half_voxel_offset = TRUE) io_write_trk(x, con, half_voxel_offset = NA)io_read_tck(file) io_write_tck( x, con, datatype = c("Float32LE", "Float32BE", "Float64LE", "Float64BE") ) io_read_trk(file, half_voxel_offset = TRUE) io_write_trk(x, con, half_voxel_offset = NA)
file, con
|
file path to the streamline file |
x |
|
datatype |
data storage type to write, default is |
half_voxel_offset |
whether to add 0.5 millimeter shift on each side,
default is |
'TRK' gains popularity due to its ability to store streamline attributes.
However, this file format suffer from ambiguous definition in the initial
'TrackVis' implementation. Typically in a medical image file, there
might exists a 4-by-4 matrix that maps the volume indices to the
corresponding anatomical right-anterior-superior 'RAS' locations.
However, the original definition of 'TRK' does not have this. Since
version 2, 'TRK' introduced such matrix, but it was interpreted
differently. Instead of the volume index space, the source space is conformed
1 millimeter space, with the origin at the first 'voxel' corner instead of
the center. Therefore there is a 0.5 mm shift at each direction, and
half_voxel_offset is designed to offset this shift.
What has made this issue complicated was that some software, such as
'DSI-studio', seemed to ignore that offset when converting from their
own format to the 'TRK' format. If the file is generated in such
way, please set half_voxel_offset=FALSE to turn off the offset
correction. We always recommend that user store data in 'TCK' format.
io_read_tck returns a ieegio streamline object,
io_write_tck returns the connection or file path.
io_read_trk returns an imaging-streamlines
instance.
# run `ieegio_sample_data("streamlines/CNVII_R.tck")` to # download sample data if( ieegio_sample_data("streamlines/CNVII_R.tck", test = TRUE) ) { path <- ieegio_sample_data("streamlines/CNVII_R.tck") # Read streamlines <- io_read_tck(path) plot(streamlines) # write tfile <- tempfile(fileext = ".tck") io_write_tck(streamlines, tfile, datatype = streamlines$header$datatype) # verify two files are identical digest::digest(file = tfile) == digest::digest(file = path) unlink(tfile) } # This example uses sample data, run # `ieegio_sample_data("streamlines/CNVII_R.trk")` to download if( ieegio_sample_data("streamlines/CNVII_R.trk", test = TRUE) ) { path <- ieegio_sample_data("streamlines/CNVII_R.trk") tfile <- tempfile(fileext = ".trk") # read x <- io_read_trk(path) # write io_write_trk(x, tfile) # compare two files file.size(path) == file.size(tfile) src_raw <- readBin(path, "raw", n = file.size(path)) dst_raw <- readBin(tfile, "raw", n = file.size(tfile)) equal_raw <- src_raw == dst_raw # Some reserved information are removed all(equal_raw[-c(945:947)]) unlink(tfile) }# run `ieegio_sample_data("streamlines/CNVII_R.tck")` to # download sample data if( ieegio_sample_data("streamlines/CNVII_R.tck", test = TRUE) ) { path <- ieegio_sample_data("streamlines/CNVII_R.tck") # Read streamlines <- io_read_tck(path) plot(streamlines) # write tfile <- tempfile(fileext = ".tck") io_write_tck(streamlines, tfile, datatype = streamlines$header$datatype) # verify two files are identical digest::digest(file = tfile) == digest::digest(file = path) unlink(tfile) } # This example uses sample data, run # `ieegio_sample_data("streamlines/CNVII_R.trk")` to download if( ieegio_sample_data("streamlines/CNVII_R.trk", test = TRUE) ) { path <- ieegio_sample_data("streamlines/CNVII_R.trk") tfile <- tempfile(fileext = ".trk") # read x <- io_read_trk(path) # write io_write_trk(x, tfile) # compare two files file.size(path) == file.size(tfile) src_raw <- readBin(path, "raw", n = file.size(path)) dst_raw <- readBin(tfile, "raw", n = file.size(tfile)) equal_raw <- src_raw == dst_raw # Some reserved information are removed all(equal_raw[-c(945:947)]) unlink(tfile) }
'TT' streamline fileWriter is not implemented yet. Please save as a 'TCK' file.
io_read_tt(file)io_read_tt(file)
file |
path to the streamline file |
An imaging-streamlines instance.
# This example uses sample data, run # `ieegio_sample_data("streamlines/CNVII_R.trk")` to download if( ieegio_sample_data("streamlines/CNVII_R.tt.gz", test = TRUE) ) { path <- ieegio_sample_data("streamlines/CNVII_R.tt.gz") # read x <- io_read_tt(path) plot(x) }# This example uses sample data, run # `ieegio_sample_data("streamlines/CNVII_R.trk")` to download if( ieegio_sample_data("streamlines/CNVII_R.tt.gz", test = TRUE) ) { path <- ieegio_sample_data("streamlines/CNVII_R.tt.gz") # read x <- io_read_tt(path) plot(x) }
'VTK' formatThis reader uses 'Python' 'vtk' package, supports '.vtk',
'.vtp', '.pvtp', '.vtpb' formats.
io_read_vtk_streamlines(file) io_write_vtk_streamlines(x, con, binary = TRUE)io_read_vtk_streamlines(file) io_write_vtk_streamlines(x, con, binary = TRUE)
file, con
|
file path to the |
x |
An |
binary |
for legacy |
io_read_vtk_streamlines returns an
imaging-streamlines object, while
io_write_vtk_streamlines writes the data to file
# This example shows how to convert tck to vtk # run `ieegio_sample_data("streamlines/CNVII_R.tck")` to # download sample data if( ieegio_sample_data("streamlines/CNVII_R.tck", test = TRUE) ) { path <- ieegio_sample_data("streamlines/CNVII_R.tck") streamlines <- as_ieegio_streamlines(path) # write to vtk tfile <- tempfile(fileext = ".vtk") io_write_vtk_streamlines(streamlines, con = tfile) # read vtk_streamlines <- io_read_vtk_streamlines(tfile) # compare plot(streamlines) plot(vtk_streamlines) # 0 0 range(streamlines[[1]]$coords - vtk_streamlines[[1]]$coords) }# This example shows how to convert tck to vtk # run `ieegio_sample_data("streamlines/CNVII_R.tck")` to # download sample data if( ieegio_sample_data("streamlines/CNVII_R.tck", test = TRUE) ) { path <- ieegio_sample_data("streamlines/CNVII_R.tck") streamlines <- as_ieegio_streamlines(path) # write to vtk tfile <- tempfile(fileext = ".vtk") io_write_vtk_streamlines(streamlines, con = tfile) # read vtk_streamlines <- io_read_vtk_streamlines(tfile) # compare plot(streamlines) plot(vtk_streamlines) # 0 0 range(streamlines[[1]]$coords - vtk_streamlines[[1]]$coords) }
provides low-level hybrid array loading for 'FST' file; used internally
LazyFST$open()to be compatible with LazyH5
LazyFST$open(...)
...ignored
none
LazyFST$close()close the connection
LazyFST$close(..., .remove_file = FALSE)
...ignored
.remove_filewhether to remove the file when garbage collected
none
LazyFST$save()to be compatible with LazyH5
LazyFST$save(...)
...ignored
none
LazyFST$new()constructor
LazyFST$new(file_path, transpose = FALSE, dims = NULL, ...)
file_pathwhere the data is stored
transposewhether to load data transposed
dimsdata dimension, only support 1 or 2 dimensions
...ignored
LazyFST$get_dims()get data dimension
LazyFST$get_dims(...)
...ignored
vector, dimensions
LazyFST$subset()subset data
LazyFST$subset(i = NULL, j = NULL, ..., drop = TRUE)
i, j, ...index along each dimension
dropwhether to apply drop the subset
subset of data
Zhengjia Wang
library(ieegio) # Data to save, 8 MB x <- matrix(rnorm(1000000), ncol = 100) # Save to local disk f <- tempfile() io_write_fst(as.data.frame(x), con = f) # Load via LazyFST dat <- LazyFST$new(file_path = f, dims = c(10000, 100)) # dat < 1 MB # Check whether the data is identical range(dat[] - x) system.time(dat[,1]) system.time(dat[1:100,])library(ieegio) # Data to save, 8 MB x <- matrix(rnorm(1000000), ncol = 100) # Save to local disk f <- tempfile() io_write_fst(as.data.frame(x), con = f) # Load via LazyFST dat <- LazyFST$new(file_path = f, dims = c(10000, 100)) # dat < 1 MB # Check whether the data is identical range(dat[] - x) system.time(dat[,1]) system.time(dat[1:100,])
Provides hybrid data structure for 'HDF5' file. The class is
not intended for direct-use. Please see io_read_h5 and
io_write_h5.
quietwhether to suppress messages
LazyH5$do_finalize()garbage collection method
LazyH5$do_finalize()
none
LazyH5$print()overrides print method
LazyH5$print()
self instance
LazyH5$new()constructor
LazyH5$new(file_path, data_name, read_only = FALSE, quiet = FALSE)
file_pathwhere data is stored in 'HDF5' format
data_namethe data stored in the file
read_onlywhether to open the file in read-only mode. It's highly recommended to set this to be true, otherwise the file connection is exclusive.
quietwhether to suppress messages, default is false
self instance
LazyH5$save()save data to a 'HDF5' file
LazyH5$save( x, chunk = "auto", level = 7, replace = TRUE, new_file = FALSE, force = TRUE, ctype = NULL, size = NULL, ... )
xvector, matrix, or array
chunkchunk size, length should matches with data dimension
levelcompress level, from 1 to 9
replaceif the data exists in the file, replace the file or not
new_fileremove the whole file if exists before writing?
forceif you open the file in read-only mode, then saving
objects to the file will raise error. Use force=TRUE to force
write data
ctypedata type, see mode, usually the data type
of x. Try mode(x) or storage.mode(x) as hints.
sizedeprecated, for compatibility issues
...passed to self open() method
LazyH5$open()open connection
LazyH5$open(new_dataset = FALSE, robj, ...)
new_datasetonly used when the internal pointer is closed, or to write the data
robjdata array to save
...passed to createDataSet in hdf5r package
LazyH5$close()close connection
LazyH5$close(all = TRUE)
allwhether to close all connections associated to the data file. If true, then all connections, including access from other programs, will be closed
LazyH5$subset()subset data
LazyH5$subset(..., drop = FALSE, stream = FALSE, envir = parent.frame())
dropwhether to apply drop the subset
streamwhether to read partial data at a time
envirif i,j,... are expressions, where should the
expression be evaluated
i, j, ...index along each dimension
subset of data
LazyH5$get_dims()get data dimension
LazyH5$get_dims(stay_open = TRUE)
stay_openwhether to leave the connection opened
dimension of the array
LazyH5$get_type()get data type
LazyH5$get_type(stay_open = TRUE)
stay_openwhether to leave the connection opened
data type, currently only character, integer, raw, double, and complex are available, all other types will yield "unknown"
Interfaces to read from or write to files with common formats.
io_read_fst( con, method = c("proxy", "data_table", "data_frame", "header_only"), ..., old_format = FALSE ) io_write_fst(x, con, compress = 50, ...) io_read_ini(con, ...) io_read_json(con, ...) io_write_json( x, con = stdout(), ..., digits = ceiling(-log10(.Machine$double.eps)), pretty = TRUE, serialize = TRUE ) io_read_mat( con, method = c("auto", "R.matlab", "pymatreader", "mat73"), verbose = TRUE, on_convert_error = c("warning", "error", "ignore"), ... ) io_write_mat(x, con, method = c("R.matlab", "scipy"), ...) io_read_yaml(con, ...) io_write_yaml(x, con, ..., sorted = FALSE)io_read_fst( con, method = c("proxy", "data_table", "data_frame", "header_only"), ..., old_format = FALSE ) io_write_fst(x, con, compress = 50, ...) io_read_ini(con, ...) io_read_json(con, ...) io_write_json( x, con = stdout(), ..., digits = ceiling(-log10(.Machine$double.eps)), pretty = TRUE, serialize = TRUE ) io_read_mat( con, method = c("auto", "R.matlab", "pymatreader", "mat73"), verbose = TRUE, on_convert_error = c("warning", "error", "ignore"), ... ) io_write_mat(x, con, method = c("R.matlab", "scipy"), ...) io_read_yaml(con, ...) io_write_yaml(x, con, ..., sorted = FALSE)
con |
connection or file |
method |
method to read table. For
For
|
... |
passed to internal function calls |
old_format |
see |
x |
data to write to disk |
compress |
compress level from 0 to 100; default is 50 |
digits, pretty
|
for writing numeric values to 'json' format |
serialize |
set to |
verbose |
whether to print out the process |
on_convert_error |
for reading |
sorted |
whether to sort the list; default is |
The reader functions returns the data extracted from files, mostly
as R objects, with few exceptions on some 'Matlab' files. When reading a
'Matlab' file requires using 'Python' modules, io_read_mat will
try its best effort to convert 'Python' objects to R. However, such
conversion might fail. In this case, the result might partially contain
'Python' objects with warnings.
# ---- fst ---------------------------------------------------------------- f <- tempfile(fileext = ".fst") x <- data.frame( a = 1:10, b = rnorm(10), c = letters[1:10] ) io_write_fst(x, con = f) # default reads in proxy io_read_fst(f) # load as data.table io_read_fst(f, "data_table") # load as data.frame io_read_fst(f, "data_frame") # get header io_read_fst(f, "header_only") # clean up unlink(f) # ---- json --------------------------------------------------------------- f <- tempfile(fileext = ".json") x <- list(a = 1L, b = 2.3, c = "a", d = 1+1i) # default is serialize io_write_json(x, f) io_read_json(f) cat(readLines(f), sep = "\n") # just values io_write_json(x, f, serialize = FALSE, pretty = FALSE) io_read_json(f) cat(readLines(f), sep = "\n") # clean up unlink(f) # ---- Matlab .mat -------------------------------------------------------- ## Not run: f <- tempfile(fileext = ".mat") x <- list(a = 1L, b = 2.3, c = "a", d = 1+1i) # save as MAT 5.0 io_write_mat(x, f) io_read_mat(f) # require setting up Python environment io_read_mat(f, method = "pymatreader") # MAT 7.3 example sample_data <- ieegio_sample_data("mat_v73.mat") io_read_mat(sample_data) # clean up unlink(f) ## End(Not run) # ---- yaml --------------------------------------------------------------- f <- tempfile(fileext = ".yaml") x <- list(a = 1L, b = 2.3, c = "a") io_write_yaml(x, f) io_read_yaml(f) # clean up unlink(f)# ---- fst ---------------------------------------------------------------- f <- tempfile(fileext = ".fst") x <- data.frame( a = 1:10, b = rnorm(10), c = letters[1:10] ) io_write_fst(x, con = f) # default reads in proxy io_read_fst(f) # load as data.table io_read_fst(f, "data_table") # load as data.frame io_read_fst(f, "data_frame") # get header io_read_fst(f, "header_only") # clean up unlink(f) # ---- json --------------------------------------------------------------- f <- tempfile(fileext = ".json") x <- list(a = 1L, b = 2.3, c = "a", d = 1+1i) # default is serialize io_write_json(x, f) io_read_json(f) cat(readLines(f), sep = "\n") # just values io_write_json(x, f, serialize = FALSE, pretty = FALSE) io_read_json(f) cat(readLines(f), sep = "\n") # clean up unlink(f) # ---- Matlab .mat -------------------------------------------------------- ## Not run: f <- tempfile(fileext = ".mat") x <- list(a = 1L, b = 2.3, c = "a", d = 1+1i) # save as MAT 5.0 io_write_mat(x, f) io_read_mat(f) # require setting up Python environment io_read_mat(f, method = "pymatreader") # MAT 7.3 example sample_data <- ieegio_sample_data("mat_v73.mat") io_read_mat(sample_data) # clean up unlink(f) ## End(Not run) # ---- yaml --------------------------------------------------------------- f <- tempfile(fileext = ".yaml") x <- list(a = 1L, b = 2.3, c = "a") io_write_yaml(x, f) io_read_yaml(f) # clean up unlink(f)
'ieegio' surfacesEither merge surface objects by attributes or merge geometries
## S3 method for class 'ieegio_surface' merge( x, y, ..., merge_type = c("attribute", "geometry"), merge_space = c("model", "world"), transform_index = 1, verbose = TRUE )## S3 method for class 'ieegio_surface' merge( x, y, ..., merge_type = c("attribute", "geometry"), merge_space = c("model", "world"), transform_index = 1, verbose = TRUE )
x, y, ...
|
|
merge_type |
type of merge:
|
merge_space |
space to merge the geometries; only used when
|
transform_index |
which local-to-world transform to use when merging
geometries in the world space; default is the first transform for each
surface object. The transform list can be obtained from
|
verbose |
whether to verbose the messages |
A merged surface object
# Construct example geometry dodecahedron_vert <- matrix( ncol = 3, byrow = TRUE, c(-0.62, -0.62, -0.62, 0.62, -0.62, -0.62, -0.62, 0.62, -0.62, 0.62, 0.62, -0.62, -0.62, -0.62, 0.62, 0.62, -0.62, 0.62, -0.62, 0.62, 0.62, 0.62, 0.62, 0.62, 0.00, -0.38, 1.00, 0.00, 0.38, 1.00, 0.00, -0.38, -1.00, 0.00, 0.38, -1.00, -0.38, 1.00, 0.00, 0.38, 1.00, 0.00, -0.38, -1.00, 0.00, 0.38, -1.00, 0.00, 1.00, 0.00, -0.38, 1.00, 0.00, 0.38, -1.00, 0.00, -0.38, -1.00, 0.00, 0.38) ) dodecahedron_face <- matrix( ncol = 3L, byrow = TRUE, c(1, 11, 2, 1, 2, 16, 1, 16, 15, 1, 15, 5, 1, 5, 20, 1, 20, 19, 1, 19, 3, 1, 3, 12, 1, 12, 11, 2, 11, 12, 2, 12, 4, 2, 4, 17, 2, 17, 18, 2, 18, 6, 2, 6, 16, 3, 13, 14, 3, 14, 4, 3, 4, 12, 3, 19, 20, 3, 20, 7, 3, 7, 13, 4, 14, 8, 4, 8, 18, 4, 18, 17, 5, 9, 10, 5, 10, 7, 5, 7, 20, 5, 15, 16, 5, 16, 6, 5, 6, 9, 6, 18, 8, 6, 8, 10, 6, 10, 9, 7, 10, 8, 7, 8, 14, 7, 14, 13) ) x0 <- as_ieegio_surface(dodecahedron_vert, faces = dodecahedron_face) plot(x0) # ---- merge by attributes ----------------------------------- # point-cloud but with vertex measurements y1 <- as_ieegio_surface( dodecahedron_vert, measurements = data.frame(MyVariable = dodecahedron_vert[, 1]), transform = diag(c(2,1,0.5,1)) ) plot(y1) # the geometry of `y1` will be discarded and only attributes # (in this case, measurements:MyVariable) will be merged to `x` z1 <- merge(x0, y1, merge_type = "attribute") plot(z1) # ---- merge by geometry ---------------------------------------- y2 <- as_ieegio_surface( dodecahedron_vert + 4, faces = dodecahedron_face, transform = diag(c(2, 1, 0.5, 1)) ) plot(y2) # merge directly in model space: transform matrix of `y2` will be ignored z2 <- merge(x0, y2, merge_type = "geometry", merge_space = "model") plot(z2) # merge x, y2 in the world space where transforms will be respected z3 <- merge(x0, y2, merge_type = "geometry", merge_space = "world") plot(z3)# Construct example geometry dodecahedron_vert <- matrix( ncol = 3, byrow = TRUE, c(-0.62, -0.62, -0.62, 0.62, -0.62, -0.62, -0.62, 0.62, -0.62, 0.62, 0.62, -0.62, -0.62, -0.62, 0.62, 0.62, -0.62, 0.62, -0.62, 0.62, 0.62, 0.62, 0.62, 0.62, 0.00, -0.38, 1.00, 0.00, 0.38, 1.00, 0.00, -0.38, -1.00, 0.00, 0.38, -1.00, -0.38, 1.00, 0.00, 0.38, 1.00, 0.00, -0.38, -1.00, 0.00, 0.38, -1.00, 0.00, 1.00, 0.00, -0.38, 1.00, 0.00, 0.38, -1.00, 0.00, -0.38, -1.00, 0.00, 0.38) ) dodecahedron_face <- matrix( ncol = 3L, byrow = TRUE, c(1, 11, 2, 1, 2, 16, 1, 16, 15, 1, 15, 5, 1, 5, 20, 1, 20, 19, 1, 19, 3, 1, 3, 12, 1, 12, 11, 2, 11, 12, 2, 12, 4, 2, 4, 17, 2, 17, 18, 2, 18, 6, 2, 6, 16, 3, 13, 14, 3, 14, 4, 3, 4, 12, 3, 19, 20, 3, 20, 7, 3, 7, 13, 4, 14, 8, 4, 8, 18, 4, 18, 17, 5, 9, 10, 5, 10, 7, 5, 7, 20, 5, 15, 16, 5, 16, 6, 5, 6, 9, 6, 18, 8, 6, 8, 10, 6, 10, 9, 7, 10, 8, 7, 8, 14, 7, 14, 13) ) x0 <- as_ieegio_surface(dodecahedron_vert, faces = dodecahedron_face) plot(x0) # ---- merge by attributes ----------------------------------- # point-cloud but with vertex measurements y1 <- as_ieegio_surface( dodecahedron_vert, measurements = data.frame(MyVariable = dodecahedron_vert[, 1]), transform = diag(c(2,1,0.5,1)) ) plot(y1) # the geometry of `y1` will be discarded and only attributes # (in this case, measurements:MyVariable) will be merged to `x` z1 <- merge(x0, y1, merge_type = "attribute") plot(z1) # ---- merge by geometry ---------------------------------------- y2 <- as_ieegio_surface( dodecahedron_vert + 4, faces = dodecahedron_face, transform = diag(c(2, 1, 0.5, 1)) ) plot(y2) # merge directly in model space: transform matrix of `y2` will be ignored z2 <- merge(x0, y2, merge_type = "geometry", merge_space = "model") plot(z2) # merge x, y2 in the world space where transforms will be respected z3 <- merge(x0, y2, merge_type = "geometry", merge_space = "world") plot(z3)
'ieegio' volumesMerge volume data into base image. The images must be static 3-dimensional volume data. Currently time-series or 4-dimensional data is not supported.
## S3 method for class 'ieegio_volume' merge(x, y, ..., thresholds = 0, reshape = dim(x), na_fill = NA)## S3 method for class 'ieegio_volume' merge(x, y, ..., thresholds = 0, reshape = dim(x), na_fill = NA)
x |
base image to be merged |
y, ...
|
images to be merged into |
thresholds |
numerical threshold for |
reshape |
output shape, default is the dimension of |
na_fill |
how to handle missing values; default is |
Merged volume with dimension reshape.
base_array <- array(0, c(15, 15, 15)) base_array[4:6, 4:6, 4:6] <- runif(27) * 255 # generate a 15x15x15 mask with 1mm spacing vox2ras1 <- diag(1, 4) vox2ras1[1:3, 4] <- -5 x <- as_ieegio_volume(base_array, vox2ras = vox2ras1) # 15x15x15 mask with 0.5mmx1mmx1mm spacing but oblique to `x` vox2ras2 <- matrix( nrow = 4, byrow = TRUE, c( 2, 0.2, -0.1, -3, -0.2, 1, 0.4, -4, 0.3, -0.1, 1, -1, 0, 0, 0, 1 ) ) # vox2ras2[1:3, 4] <- c(-3,-4, -1) base_array[4:6, 4:6, 4:6] <- runif(27) * 255 y <- as_ieegio_volume(base_array, vox2ras = vox2ras2) # merge y into x and up-sample mask to 64^3 volume # set to higher number to get better interpolation quality # Only voxels of y>0 will be merged to x z <- merge(x, y, reshape = c(64, 64, 64), thresholds = 0) # Visualize oldpar <- par(mfrow = c(1, 3), mar = c(0, 0, 2, 0)) zoom <- 10 crosshair_ras <- c(0, 0, 0) pixel_width <- 2 plot(x, zoom = zoom, position = crosshair_ras, pixel_width = pixel_width, main = "Original - underlay") plot(y, zoom = zoom, position = crosshair_ras, pixel_width = pixel_width, main = "Original - overlay") plot( z, zoom = zoom, position = crosshair_ras, pixel_width = pixel_width, main = "Merged & up-sampled") # reset graphical state par(oldpar)base_array <- array(0, c(15, 15, 15)) base_array[4:6, 4:6, 4:6] <- runif(27) * 255 # generate a 15x15x15 mask with 1mm spacing vox2ras1 <- diag(1, 4) vox2ras1[1:3, 4] <- -5 x <- as_ieegio_volume(base_array, vox2ras = vox2ras1) # 15x15x15 mask with 0.5mmx1mmx1mm spacing but oblique to `x` vox2ras2 <- matrix( nrow = 4, byrow = TRUE, c( 2, 0.2, -0.1, -3, -0.2, 1, 0.4, -4, 0.3, -0.1, 1, -1, 0, 0, 0, 1 ) ) # vox2ras2[1:3, 4] <- c(-3,-4, -1) base_array[4:6, 4:6, 4:6] <- runif(27) * 255 y <- as_ieegio_volume(base_array, vox2ras = vox2ras2) # merge y into x and up-sample mask to 64^3 volume # set to higher number to get better interpolation quality # Only voxels of y>0 will be merged to x z <- merge(x, y, reshape = c(64, 64, 64), thresholds = 0) # Visualize oldpar <- par(mfrow = c(1, 3), mar = c(0, 0, 2, 0)) zoom <- 10 crosshair_ras <- c(0, 0, 0) pixel_width <- 2 plot(x, zoom = zoom, position = crosshair_ras, pixel_width = pixel_width, main = "Original - underlay") plot(y, zoom = zoom, position = crosshair_ras, pixel_width = pixel_width, main = "Original - overlay") plot( z, zoom = zoom, position = crosshair_ras, pixel_width = pixel_width, main = "Merged & up-sampled") # reset graphical state par(oldpar)
Creates an object representing a coordinate space/reference frame used in medical imaging. The orientation defines the anatomical meaning of the coordinate axes.
new_space(name = "", orientation = ORIENTATION_CODES, dimension = 3, ...)new_space(name = "", orientation = ORIENTATION_CODES, dimension = 3, ...)
name |
character string identifying the coordinate space (e.g.,
|
orientation |
character string specifying the axis orientation convention. Common orientations in brain imaging:
|
dimension |
integer dimension of the space (typically 3 for 3D imaging) |
... |
additional attributes to attach to the space object |
Orientation codes use three letters to define the positive direction of the x, y, and z axes respectively:
First letter (x-axis): Left or Right
Second letter (y-axis): Anterior or Posterior
Third letter (z-axis): Superior or Inferior
For example, "RAS" means: +x points Right, +y points Anterior
(toward face), +z points Superior (toward top of head).
An S3 object of class "ieegio_space" with attributes
orientation and dimension
# FreeSurfer/NIfTI convention scanner_space <- new_space("scanner", orientation = "RAS") print(scanner_space) # DICOM/ANTs convention mni_space <- new_space("MNI152NLin2009cAsym", orientation = "LPS", dimension = 3) format(mni_space)# FreeSurfer/NIfTI convention scanner_space <- new_space("scanner", orientation = "RAS") print(scanner_space) # DICOM/ANTs convention mni_space <- new_space("MNI152NLin2009cAsym", orientation = "LPS", dimension = 3) format(mni_space)
NWBHDF5IO file containerClass definition for 'PyNWB' container; use read_nwb
for construction function.
openedWhether the container is opened.
NWBHDF5IO$new()Initialize the class
NWBHDF5IO$new(path = NULL, mode = c("r", "w", "r+", "a", "w-", "x"), ...)
pathPath to a '.nwb' file
modeMode for opening the file
...Other parameters passed to nwb$NWBHDF5IO
NWBHDF5IO$get_handler()Get internal file handler. Please make sure you close the handler correctly.
NWBHDF5IO$get_handler()
File handler, i.e. 'PyNWB' NWBHDF5IO instance.
NWBHDF5IO$open()Open the connections, must be used together with $close method.
For high-level method, see $with
NWBHDF5IO$open()
container itself
# low-level method to open NWB file, for safer methods, see # `container$with()` below container$open() data <- container$read() # process data... # Make sure the container is closed! container$close()
NWBHDF5IO$close()Close the connections (low-level method, see 'with' method below)
NWBHDF5IO$close(close_links = TRUE)
close_linksWhether to close all files linked to from this file; default is true
Nothing
NWBHDF5IO$close_linked_files()Close all opened, linked-to files. 'MacOS' and 'Linux'
automatically release the linked-to file after the linking file is
closed, but 'Windows' does not, which prevents the linked-to
file from being deleted or truncated. Use this method to close all
opened, linked-to files.
NWBHDF5IO$close_linked_files()
Nothing
NWBHDF5IO$read()Read the 'NWB' file from the 'IO' source. Please use along with
'$with' method
NWBHDF5IO$read()
'NWBFile' container
NWBHDF5IO$with()Safe wrapper for reading and handling 'NWB' file. See class examples.
NWBHDF5IO$with(expr, quoted = FALSE, envir = parent.frame())
exprR expression to evaluate
quotedWhether expr is quoted; default is false
envirenvironment for expr to evaluate; default is the
parent frame (see parent.frame)
Whatever results generated by expr
container$with({
data <- container$read()
# process data
})
NWBHDF5IO$clone()The objects of this class are cloneable with this method.
NWBHDF5IO$clone(deep = FALSE)
deepWhether to make a deep clone.
## Not run: # Running this example requires a .nwb file library(rnwb) container <- NWBHDF5IO$new(path = file) container$with({ data <- container$read() electrode_table <- data$electrodes[convert = TRUE] }) print(electrode_table) ## End(Not run) ## ------------------------------------------------ ## Method `NWBHDF5IO$open()` ## ------------------------------------------------ ## Not run: # low-level method to open NWB file, for safer methods, see # `container$with()` below container$open() data <- container$read() # process data... # Make sure the container is closed! container$close() ## End(Not run) ## ------------------------------------------------ ## Method `NWBHDF5IO$with()` ## ------------------------------------------------ ## Not run: container$with({ data <- container$read() # process data }) ## End(Not run)## Not run: # Running this example requires a .nwb file library(rnwb) container <- NWBHDF5IO$new(path = file) container$with({ data <- container$read() electrode_table <- data$electrodes[convert = TRUE] }) print(electrode_table) ## End(Not run) ## ------------------------------------------------ ## Method `NWBHDF5IO$open()` ## ------------------------------------------------ ## Not run: # low-level method to open NWB file, for safer methods, see # `container$with()` below container$open() data <- container$read() # process data... # Make sure the container is closed! container$close() ## End(Not run) ## ------------------------------------------------ ## Method `NWBHDF5IO$with()` ## ------------------------------------------------ ## Not run: container$with({ data <- container$read() # process data }) ## End(Not run)
Plot '3D' surface objects
## S3 method for class 'ieegio_surface' plot( x, method = c("auto", "base", "r3js", "rgl_basic", "rgl_full"), transform = 1L, name = "auto", vlim = NULL, col = c("black", "white"), slice_index = NULL, ... )## S3 method for class 'ieegio_surface' plot( x, method = c("auto", "base", "r3js", "rgl_basic", "rgl_full"), transform = 1L, name = "auto", vlim = NULL, col = c("black", "white"), slice_index = NULL, ... )
x |
|
method |
plot method; |
transform |
which transform to use, can be a 4-by-4 matrix; if
the surface contains transform matrix, then this argument can be
an integer index of the transform embedded, or the target
(transformed) space name; print |
name |
attribute and name used for colors, options can be |
vlim |
when plotting with continuous data ( |
col |
color or colors to form the color palette when value data is
continuous; when |
slice_index |
when plotting the |
... |
ignored |
library(ieegio) # geometry geom_file <- "gifti/GzipBase64/sujet01_Lwhite.surf.gii" # measurements shape_file <- "gifti/GzipBase64/sujet01_Lwhite.shape.gii" # time series ts_file <- "gifti/GzipBase64/fmri_sujet01_Lwhite_projection.time.gii" if (ieegio_sample_data(geom_file, test = TRUE)) { geometry <- read_surface(ieegio_sample_data(geom_file)) geometry$geometry$transforms[[1]] <- diag(c(1, -1, -1, 1)) measurement <- read_surface(ieegio_sample_data(shape_file)) time_series <- read_surface(ieegio_sample_data(ts_file)) ts_demean <- apply( time_series$time_series$value, MARGIN = 1L, FUN = function(x) { x - mean(x) } ) time_series$time_series$value <- t(ts_demean) # merge measurement & time_series into geometry (optional) merged <- merge(geometry, measurement, time_series) print(merged) # ---- plot method/style ------------------------------------ plot(merged) # ---- plot data -------------------------------------------- ## Measurements or annotations # the first column of `measurements` plot(merged, name = "measurements") # equivalent to plot(merged, name = list("measurements", 1L)) # equivalent to measurement_names <- names(merged$measurements$data_table) plot(merged, name = list("measurements", measurement_names[[1]])) ## Time-series # automatically select 4 slices, trim the color palette # from -25 to 25 plot(merged, name = "time_series", vlim = c(-25, 25), slice_index = 1L) plot( merged, name = "time_series", vlim = c(-25, 25), slice_index = seq(1, 128, by = 11), col = c("#053061", "#2166ac", "#4393c3", "#92c5de", "#d1e5f0", "#ffffff", "#fddbc7", "#f4a582", "#d6604d", "#b2182b", "#67001f"), method = "base", eye = c(1000, 0, 0), up = c(0, 0, 1), side = "front", mesh_clipping = 0.3, ambient_intensity = 0.7 ) }library(ieegio) # geometry geom_file <- "gifti/GzipBase64/sujet01_Lwhite.surf.gii" # measurements shape_file <- "gifti/GzipBase64/sujet01_Lwhite.shape.gii" # time series ts_file <- "gifti/GzipBase64/fmri_sujet01_Lwhite_projection.time.gii" if (ieegio_sample_data(geom_file, test = TRUE)) { geometry <- read_surface(ieegio_sample_data(geom_file)) geometry$geometry$transforms[[1]] <- diag(c(1, -1, -1, 1)) measurement <- read_surface(ieegio_sample_data(shape_file)) time_series <- read_surface(ieegio_sample_data(ts_file)) ts_demean <- apply( time_series$time_series$value, MARGIN = 1L, FUN = function(x) { x - mean(x) } ) time_series$time_series$value <- t(ts_demean) # merge measurement & time_series into geometry (optional) merged <- merge(geometry, measurement, time_series) print(merged) # ---- plot method/style ------------------------------------ plot(merged) # ---- plot data -------------------------------------------- ## Measurements or annotations # the first column of `measurements` plot(merged, name = "measurements") # equivalent to plot(merged, name = list("measurements", 1L)) # equivalent to measurement_names <- names(merged$measurements$data_table) plot(merged, name = list("measurements", measurement_names[[1]])) ## Time-series # automatically select 4 slices, trim the color palette # from -25 to 25 plot(merged, name = "time_series", vlim = c(-25, 25), slice_index = 1L) plot( merged, name = "time_series", vlim = c(-25, 25), slice_index = seq(1, 128, by = 11), col = c("#053061", "#2166ac", "#4393c3", "#92c5de", "#d1e5f0", "#ffffff", "#fddbc7", "#f4a582", "#d6604d", "#b2182b", "#67001f"), method = "base", eye = c(1000, 0, 0), up = c(0, 0, 1), side = "front", mesh_clipping = 0.3, ambient_intensity = 0.7 ) }
Plot '3D' volume in anatomical slices
## S3 method for class 'ieegio_volume' plot( x, position = c(0, 0, 0), center_position = FALSE, which = c("coronal", "axial", "sagittal"), slice_index = 1L, transform = "vox2ras", zoom = 1, pixel_width = max(zoom/2, 1), col = c("black", "white"), alpha = NA, crosshair_gap = 4, crosshair_lty = 2, crosshair_col = "#00FF00A0", label_col = crosshair_col, continuous = TRUE, vlim = NULL, add = FALSE, main = "", axes = FALSE, background = col[[1]], foreground = col[[length(col)]], ..., .xdata = x$data )## S3 method for class 'ieegio_volume' plot( x, position = c(0, 0, 0), center_position = FALSE, which = c("coronal", "axial", "sagittal"), slice_index = 1L, transform = "vox2ras", zoom = 1, pixel_width = max(zoom/2, 1), col = c("black", "white"), alpha = NA, crosshair_gap = 4, crosshair_lty = 2, crosshair_col = "#00FF00A0", label_col = crosshair_col, continuous = TRUE, vlim = NULL, add = FALSE, main = "", axes = FALSE, background = col[[1]], foreground = col[[length(col)]], ..., .xdata = x$data )
x |
|
position |
position in |
center_position |
whether to center canvas at |
which |
which slice to plot; choices are |
slice_index |
length of 1: if |
transform |
which transform to apply, can be a 4-by-4 matrix,
an integer or name indicating the matrix in |
zoom |
zoom-in level |
pixel_width |
pixel size, ranging from |
col |
color palette for continuous |
alpha |
opacity value if the image is to be displayed with transparency |
crosshair_gap |
the cross-hair gap in milliliter |
crosshair_lty |
the cross-hair line type |
crosshair_col |
the cross-hair color; set to |
label_col |
the color of anatomical axis labels (i.e. |
continuous |
reserved |
vlim |
the range limit of the data; default is computed from range of
|
add |
whether to add the plot to existing underlay;
default is |
main, ...
|
passed to |
axes |
whether to draw axes; default is |
background, foreground
|
background and foreground colors; default is
the first and last elements of |
.xdata |
default is |
library(ieegio) nifti_file <- "nifti/rnifti_example.nii.gz" nifti_rgbfile <- "nifti/rnifti_example_rgb.nii.gz" # Use # `ieegio_sample_data(nifti_file)` # and # `ieegio_sample_data(nifti_rgbfile)` # to download sample data if( ieegio_sample_data(nifti_file, test = TRUE) && ieegio_sample_data(nifti_rgbfile, test = TRUE) ) { # ---- NIfTI examples --------------------------------------------- underlay_path <- ieegio_sample_data(nifti_file) overlay_path <- ieegio_sample_data(nifti_rgbfile) # basic read underlay <- read_volume(underlay_path) overlay <- read_volume(overlay_path) par(mfrow = c(1, 3), mar = c(0, 0, 3.1, 0)) ras_position <- c(50, -10, 15) ras_str <- paste(sprintf("%.0f", ras_position), collapse = ",") for(which in c("coronal", "axial", "sagittal")) { plot(x = underlay, position = ras_position, crosshair_gap = 10, crosshair_lty = 2, zoom = 3, which = which, main = sprintf("%s T1RAS=[%s]", which, ras_str)) plot(x = overlay, position = ras_position, crosshair_gap = 10, label_col = NA, add = TRUE, alpha = 0.9, zoom = 5, which = which) } }library(ieegio) nifti_file <- "nifti/rnifti_example.nii.gz" nifti_rgbfile <- "nifti/rnifti_example_rgb.nii.gz" # Use # `ieegio_sample_data(nifti_file)` # and # `ieegio_sample_data(nifti_rgbfile)` # to download sample data if( ieegio_sample_data(nifti_file, test = TRUE) && ieegio_sample_data(nifti_rgbfile, test = TRUE) ) { # ---- NIfTI examples --------------------------------------------- underlay_path <- ieegio_sample_data(nifti_file) overlay_path <- ieegio_sample_data(nifti_rgbfile) # basic read underlay <- read_volume(underlay_path) overlay <- read_volume(overlay_path) par(mfrow = c(1, 3), mar = c(0, 0, 3.1, 0)) ras_position <- c(50, -10, 15) ras_str <- paste(sprintf("%.0f", ras_position), collapse = ",") for(which in c("coronal", "axial", "sagittal")) { plot(x = underlay, position = ras_position, crosshair_gap = 10, crosshair_lty = 2, zoom = 3, which = which, main = sprintf("%s T1RAS=[%s]", which, ras_str)) plot(x = overlay, position = ras_position, crosshair_gap = 10, label_col = NA, add = TRUE, alpha = 0.9, zoom = 5, which = which) } }
'NWB' via 'pynwb'
Install 'NWB' via 'pynwb'
install_pynwb(python_ver = "auto", verbose = TRUE) pynwb_module(force = FALSE, error_if_missing = TRUE)install_pynwb(python_ver = "auto", verbose = TRUE) pynwb_module(force = FALSE, error_if_missing = TRUE)
python_ver |
'Python' version, see |
verbose |
whether to print the installation messages |
force |
whether to force-reload the module |
error_if_missing |
whether to raise errors when the module fails to load; default is true |
A 'Python' module pynwb.
Read 'BCI2000' data file
read_bci2000( file, extract_path = getOption("ieegio.extract_path", NULL), header_only = FALSE, cache_ok = TRUE, verbose = TRUE )read_bci2000( file, extract_path = getOption("ieegio.extract_path", NULL), header_only = FALSE, cache_ok = TRUE, verbose = TRUE )
file |
file path to the data file |
extract_path |
location to where the extracted information is to be stored |
header_only |
whether to only load header data |
cache_ok |
whether existing cache should be reused; default is
|
verbose |
whether to print processing messages; default is |
A cached object that is readily to be loaded to memory; see
SignalDataCache for class definition.
if( ieegio_sample_data("bci2k.dat", test = TRUE) ) { file <- ieegio_sample_data("bci2k.dat") x <- read_bci2000(file) print(x) channel <- x$get_channel(1) plot( channel$time, channel$value, type = "l", main = channel$info$Label, xlab = "Time", ylab = channel$info$Unit ) }if( ieegio_sample_data("bci2k.dat", test = TRUE) ) { file <- ieegio_sample_data("bci2k.dat") x <- read_bci2000(file) print(x) channel <- x$get_channel(1) plot( channel$time, channel$value, type = "l", main = channel$info$Label, xlab = "Time", ylab = channel$info$Unit ) }
Read 'BrainVision' data
read_brainvis( file, extract_path = getOption("ieegio.extract_path", NULL), header_only = FALSE, cache_ok = TRUE, verbose = TRUE )read_brainvis( file, extract_path = getOption("ieegio.extract_path", NULL), header_only = FALSE, cache_ok = TRUE, verbose = TRUE )
file |
file path to the data file |
extract_path |
location to where the extracted information is to be stored |
header_only |
whether to only load header data |
cache_ok |
whether existing cache should be reused; default is
|
verbose |
whether to print processing messages; default is |
A cached object that is readily to be loaded to memory; see
SignalDataCache for class definition.
if( ieegio_sample_data("brainvis.dat", test = TRUE) ) { # ensure the header and marker files are downloaded as well ieegio_sample_data("brainvis.vhdr") ieegio_sample_data("brainvis.dat") file <- ieegio_sample_data("brainvis.vmrk") x <- read_brainvis(file) print(x) x$get_header() x$get_channel_table() x$get_annotations() channel <- x$get_channel(10) plot( channel$time, channel$value, type = "l", main = channel$info$Label, xlab = "Time", ylab = channel$info$Unit ) }if( ieegio_sample_data("brainvis.dat", test = TRUE) ) { # ensure the header and marker files are downloaded as well ieegio_sample_data("brainvis.vhdr") ieegio_sample_data("brainvis.dat") file <- ieegio_sample_data("brainvis.vmrk") x <- read_brainvis(file) print(x) x$get_header() x$get_channel_table() x$get_annotations() channel <- x$get_channel(10) plot( channel$time, channel$value, type = "l", main = channel$info$Label, xlab = "Time", ylab = channel$info$Unit ) }
Read 'EDF' or 'BDF' data file
read_edf( con, extract_path = getOption("ieegio.extract_path", NULL), header_only = FALSE, cache_ok = TRUE, begin = 0, end = Inf, convert = TRUE, verbose = TRUE )read_edf( con, extract_path = getOption("ieegio.extract_path", NULL), header_only = FALSE, cache_ok = TRUE, begin = 0, end = Inf, convert = TRUE, verbose = TRUE )
con |
file or connection to the data file |
extract_path |
location to where the extracted information is to be stored |
header_only |
whether to only load header data |
cache_ok |
whether existing cache should be reused; default is
|
begin, end
|
begin and end of the data to read |
convert |
whether to convert digital numbers to analog signals; default
is |
verbose |
whether to print processing messages; default is |
A cached object that is readily to be loaded to memory; see
SignalDataCache for class definition.
# ---- EDF/BDF(+) --------------------------------------------------------- # Run `ieegio_sample_data("edfPlusD.edf")` to download sample data # Tun example if the sample data exists if(ieegio_sample_data("edfPlusD.edf", test = TRUE)) { edf_path <- ieegio_sample_data("edfPlusD.edf") data <- read_edf(edf_path) data$get_header() data$get_annotations() data$get_channel_table() channel <- data$get_channel(1) plot( channel$time, channel$value, type = "l", main = channel$info$Label, xlab = "Time", ylab = channel$info$Unit ) }# ---- EDF/BDF(+) --------------------------------------------------------- # Run `ieegio_sample_data("edfPlusD.edf")` to download sample data # Tun example if the sample data exists if(ieegio_sample_data("edfPlusD.edf", test = TRUE)) { edf_path <- ieegio_sample_data("edfPlusD.edf") data <- read_edf(edf_path) data$get_header() data$get_annotations() data$get_channel_table() channel <- data$get_channel(1) plot( channel$time, channel$value, type = "l", main = channel$info$Label, xlab = "Time", ylab = channel$info$Unit ) }
Read ('BlackRock') 'NEV' 'NSx' data
read_nsx( file, extract_path = getOption("ieegio.extract_path", NULL), header_only = FALSE, cache_ok = TRUE, include_waveform = FALSE, verbose = TRUE )read_nsx( file, extract_path = getOption("ieegio.extract_path", NULL), header_only = FALSE, cache_ok = TRUE, include_waveform = FALSE, verbose = TRUE )
file |
file path to the data file |
extract_path |
location to where the extracted information is to be stored |
header_only |
whether to only load header data |
cache_ok |
whether existing cache should be reused; default is
|
include_waveform |
whether to include 'waveform' data (usually for
online spike sorting); default is |
verbose |
whether to print processing messages; default is |
A cached object that is readily to be loaded to memory; see
SignalDataCache for class definition.
Life cycle: experimental.
Read "Neurodata Without Borders" ('NWB' format) file. Unlike other readers
read_nwb returns low-level 'Python' class handler via pynwb
module.
read_nwb(file, mode = c("r", "w", "r+", "a", "w-", "x"), ...)read_nwb(file, mode = c("r", "w", "r+", "a", "w-", "x"), ...)
file |
path to 'NWB' file |
mode |
file open mode; default is |
... |
passed to |
A NWBHDF5IO instance
if(ieegio_sample_data("nwb_sample.nwb", test = TRUE)) { file <- ieegio_sample_data("nwb_sample.nwb") # Create NWBIO container container <- read_nwb(file) # Open connection container$open() # read meta data data <- container$read() data # get `test_timeseries` data ts_data <- data$get_acquisition("test_timeseries") ts_data # read timeseries data into memory ts_arr <- ts_data$data[] ts_arr # Convert Python array to R # using `rpymat::py_to_r(ts_arr)` or as.numeric(ts_arr) # Make sure you close the connection container$close() } # Requires setting up Python environment # run `ieegio::install_pynwb()` to set up environment first ## Not run: # Replicating tutorial # https://pynwb.readthedocs.io/en/stable/tutorials/general/plot_file.html library(rpymat) # Load Python module pynwb <- import("pynwb") uuid <- import("uuid") datetime <- import("datetime") np <- import("numpy") tz <- import("dateutil.tz") # 2018L is 2018 as integer session_start_time <- datetime$datetime( 2018L, 4L, 25L, 2L, 30L, 3L, tzinfo=tz$gettz("US/Pacific")) # ---- Create NWB file object ------------------------ nwbfile <- pynwb$NWBFile( session_description="Mouse exploring a closed field", identifier=py_str(uuid$uuid4()), session_start_time=session_start_time, session_id="session_4321", experimenter=py_list(c("Baggins, Frodo")), lab="Bag End Laboratory", institution="University of Middle Earth at the Shire", experiment_description="Thank you Bilbo Baggins.", keywords=py_list(c("behavior", "exploration")) ) # ---- Add subject ------------------------------------ subject <- pynwb$file$Subject( subject_id="001", age="P90D", description="mouse 5", species="Mus musculus", sex="M" ) nwbfile$subject <- subject nwbfile # ---- Add TimeSeries ------------------------------------ data <- seq(100, 190, by = 10) time_series_with_rate <- pynwb$TimeSeries( name="test_timeseries", description="an example time series", data=data, unit="m", starting_time=0.0, rate=1.0 ) time_series_with_rate nwbfile$add_acquisition(time_series_with_rate) # ---- New Spatial positions ------------------------------------ position_data <- cbind( seq(0, 10, length.out = 50), seq(0, 9, length.out = 50) ) position_timestamps = seq(0, 49) / 200 spatial_series_obj = pynwb$behavior$SpatialSeries( name="SpatialSeries", description="(x,y) position in open field", data=position_data, timestamps=position_timestamps, reference_frame="(0,0) is bottom left corner", ) spatial_series_obj position_obj = pynwb$behavior$Position( spatial_series=spatial_series_obj) position_obj # ---- Behavior Processing Module ------------------------------ behavior_module <- nwbfile$create_processing_module( name="behavior", description="processed behavioral data" ) behavior_module$add(position_obj) nwbfile$processing$behavior # omit some process # ---- Write --------------------------------------------------- f <- normalizePath(tempfile(fileext = ".nwb"), winslash = "/", mustWork = FALSE) io <- pynwb$NWBHDF5IO(f, mode = "w") io$write(nwbfile) io$close() ## End(Not run)if(ieegio_sample_data("nwb_sample.nwb", test = TRUE)) { file <- ieegio_sample_data("nwb_sample.nwb") # Create NWBIO container container <- read_nwb(file) # Open connection container$open() # read meta data data <- container$read() data # get `test_timeseries` data ts_data <- data$get_acquisition("test_timeseries") ts_data # read timeseries data into memory ts_arr <- ts_data$data[] ts_arr # Convert Python array to R # using `rpymat::py_to_r(ts_arr)` or as.numeric(ts_arr) # Make sure you close the connection container$close() } # Requires setting up Python environment # run `ieegio::install_pynwb()` to set up environment first ## Not run: # Replicating tutorial # https://pynwb.readthedocs.io/en/stable/tutorials/general/plot_file.html library(rpymat) # Load Python module pynwb <- import("pynwb") uuid <- import("uuid") datetime <- import("datetime") np <- import("numpy") tz <- import("dateutil.tz") # 2018L is 2018 as integer session_start_time <- datetime$datetime( 2018L, 4L, 25L, 2L, 30L, 3L, tzinfo=tz$gettz("US/Pacific")) # ---- Create NWB file object ------------------------ nwbfile <- pynwb$NWBFile( session_description="Mouse exploring a closed field", identifier=py_str(uuid$uuid4()), session_start_time=session_start_time, session_id="session_4321", experimenter=py_list(c("Baggins, Frodo")), lab="Bag End Laboratory", institution="University of Middle Earth at the Shire", experiment_description="Thank you Bilbo Baggins.", keywords=py_list(c("behavior", "exploration")) ) # ---- Add subject ------------------------------------ subject <- pynwb$file$Subject( subject_id="001", age="P90D", description="mouse 5", species="Mus musculus", sex="M" ) nwbfile$subject <- subject nwbfile # ---- Add TimeSeries ------------------------------------ data <- seq(100, 190, by = 10) time_series_with_rate <- pynwb$TimeSeries( name="test_timeseries", description="an example time series", data=data, unit="m", starting_time=0.0, rate=1.0 ) time_series_with_rate nwbfile$add_acquisition(time_series_with_rate) # ---- New Spatial positions ------------------------------------ position_data <- cbind( seq(0, 10, length.out = 50), seq(0, 9, length.out = 50) ) position_timestamps = seq(0, 49) / 200 spatial_series_obj = pynwb$behavior$SpatialSeries( name="SpatialSeries", description="(x,y) position in open field", data=position_data, timestamps=position_timestamps, reference_frame="(0,0) is bottom left corner", ) spatial_series_obj position_obj = pynwb$behavior$Position( spatial_series=spatial_series_obj) position_obj # ---- Behavior Processing Module ------------------------------ behavior_module <- nwbfile$create_processing_module( name="behavior", description="processed behavioral data" ) behavior_module$add(position_obj) nwbfile$processing$behavior # omit some process # ---- Write --------------------------------------------------- f <- normalizePath(tempfile(fileext = ".nwb"), winslash = "/", mustWork = FALSE) io <- pynwb$NWBHDF5IO(f, mode = "w") io$write(nwbfile) io$close() ## End(Not run)
Using nearest-neighbor.
resample_volume(x, new_dim, na_fill = NA)resample_volume(x, new_dim, na_fill = NA)
x |
image volume |
new_dim |
new dimension |
na_fill |
value to fill if missing |
A new volume with desired shape
# ---- Toy example ---------------------------- dm <- c(6, 6, 6) arr <- array(seq_len(prod(dm)) + 0.5, dm) orig <- as_ieegio_volume( arr, vox2ras = cbind(diag(1, nrow = 4, ncol = 3), c(-dm / 2, 1))) # resample downsampled <- resample_volume(orig, new_dim = c(3, 3, 3)) dim(downsampled) # up-sample on coronal upsampled <- resample_volume(orig, new_dim = c(20, 20, 24)) dim(upsampled) par(mfrow = c(2, 2), mar = c(0, 0, 2.1, 0.1)) plot(orig, pixel_width = 0.5, zoom = 20, main = "Original") plot(downsampled, pixel_width = 0.5, zoom = 20, main = "Down-sampled") plot(upsampled, pixel_width = 0.5, zoom = 20, main = "Super-sampled") plot( orig, main = "Overlay super-sample (diff)", col = c("black", "white"), pixel_width = 0.5, zoom = 20 ) plot( upsampled, add = TRUE, col = c("white", "black"), pixel_width = 0.5, zoom = 20, alpha = 0.5 ) # ---- Real example --------------------------- nifti_file <- "brain.demosubject.nii.gz" if( ieegio_sample_data(nifti_file, test = TRUE) ) { orig <- read_volume(ieegio_sample_data(nifti_file)) dim(orig) # resample downsampled <- resample_volume(orig, new_dim = c(30, 30, 30)) dim(downsampled) # up-sample on coronal upsampled <- resample_volume(orig, new_dim = c(300, 300, 64)) dim(upsampled) par(mfrow = c(2, 2), mar = c(0, 0, 2.1, 0.1)) plot(orig, main = "Original") plot(downsampled, main = "Down-sampled") plot(upsampled, main = "Super-sampled") plot( orig, main = "Overlay super-sample", col = c("black", "white"), zoom = 2, vlim = c(0, 255) ) plot( upsampled, add = TRUE, col = c("white", "black"), zoom = 2, alpha = 0.5, vlim = c(0, 255) ) }# ---- Toy example ---------------------------- dm <- c(6, 6, 6) arr <- array(seq_len(prod(dm)) + 0.5, dm) orig <- as_ieegio_volume( arr, vox2ras = cbind(diag(1, nrow = 4, ncol = 3), c(-dm / 2, 1))) # resample downsampled <- resample_volume(orig, new_dim = c(3, 3, 3)) dim(downsampled) # up-sample on coronal upsampled <- resample_volume(orig, new_dim = c(20, 20, 24)) dim(upsampled) par(mfrow = c(2, 2), mar = c(0, 0, 2.1, 0.1)) plot(orig, pixel_width = 0.5, zoom = 20, main = "Original") plot(downsampled, pixel_width = 0.5, zoom = 20, main = "Down-sampled") plot(upsampled, pixel_width = 0.5, zoom = 20, main = "Super-sampled") plot( orig, main = "Overlay super-sample (diff)", col = c("black", "white"), pixel_width = 0.5, zoom = 20 ) plot( upsampled, add = TRUE, col = c("white", "black"), pixel_width = 0.5, zoom = 20, alpha = 0.5 ) # ---- Real example --------------------------- nifti_file <- "brain.demosubject.nii.gz" if( ieegio_sample_data(nifti_file, test = TRUE) ) { orig <- read_volume(ieegio_sample_data(nifti_file)) dim(orig) # resample downsampled <- resample_volume(orig, new_dim = c(30, 30, 30)) dim(downsampled) # up-sample on coronal upsampled <- resample_volume(orig, new_dim = c(300, 300, 64)) dim(upsampled) par(mfrow = c(2, 2), mar = c(0, 0, 2.1, 0.1)) plot(orig, main = "Original") plot(downsampled, main = "Down-sampled") plot(upsampled, main = "Super-sampled") plot( orig, main = "Overlay super-sample", col = c("black", "white"), zoom = 2, vlim = c(0, 255) ) plot( upsampled, add = TRUE, col = c("white", "black"), zoom = 2, alpha = 0.5, vlim = c(0, 255) ) }
This class is an internal abstract class
FileCache$get_header()Get header information, often small list object
FileCache$get_header(...)
...passed to child methods
FileCache$get_annotations()Get annotation information, often a large table
FileCache$get_annotations(...)
...passed to child methods
FileCache$get_channel_table()Get channel table
FileCache$get_channel_table(...)
...passed to child methods
FileCache$get_channel()Get channel data
FileCache$get_channel(x, ...)
xchannel order or label
...passed to child methods
Channel signal with time-stamps inheriting class
'ieegio_get_channel'
FileCache$delete()Delete file cache
FileCache$delete(...)
...passed to child methods
Transforms surface vertex positions from one coordinate space or orientation to another, optionally applying an additional custom transform.
surface_to_surface(surface, space_from = "", space_to = "", transform = NULL)surface_to_surface(surface, space_from = "", space_to = "", transform = NULL)
surface |
an |
space_from |
source coordinate space; either an |
space_to |
target coordinate space; either an |
transform |
optional 4x4 affine transformation matrix or
|
The function handles orientation changes (e.g., "RAS" to "LPS")
and optional custom transforms. It creates a transform chain consisting of:
an affine (orientation alignment from source), the custom transform, and
a post-affine (final orientation alignment to target).
If the provided transform has a "passive" interpretation, it is
automatically converted to an "active" interpretation before
being applied to the vertex coordinates.
A transformed ieegio_surface object with updated vertex
positions and transform metadata
as_ieegio_surface for creating surface objects,
new_space for defining coordinate spaces,
transform_orientation for orientation transforms,
volume_to_surface for creating surfaces from volumes
library(ieegio) # geometry geom_file <- "gifti/GzipBase64/sujet01_Lwhite.surf.gii" if(ieegio_sample_data(geom_file, test = TRUE)) { surf_ras <- read_surface(ieegio_sample_data(geom_file)) plot(surf_ras) # ---- Change axis orientation ------------------ # convert from RAS orientation to LPS surf_lps <- surface_to_surface( surf_ras, space_from = new_space("", orientation = "RAS"), space_to = new_space("", orientation = "LPS") ) plot(surf_lps) # validate lps_verts <- diag(c(-1, -1, 1, 1)) %*% surf_ras$geometry$vertices range(surf_lps$geometry$vertices - lps_verts) # ---- Apply transforms ------------------ transform <- matrix( byrow = TRUE, nrow = 4, c( 0.5, 0, 0.3, 1, 0, -1, 0.2, 2, 0, 0.7, -0.5, 4, 0, 0, 0, 1 ) ) surf_stretch <- surface_to_surface(surf_ras, transform = transform) plot(surf_stretch) # validate stretch_verts <- transform %*% surf_ras$geometry$vertices range(surf_stretch$geometry$vertices - stretch_verts) }library(ieegio) # geometry geom_file <- "gifti/GzipBase64/sujet01_Lwhite.surf.gii" if(ieegio_sample_data(geom_file, test = TRUE)) { surf_ras <- read_surface(ieegio_sample_data(geom_file)) plot(surf_ras) # ---- Change axis orientation ------------------ # convert from RAS orientation to LPS surf_lps <- surface_to_surface( surf_ras, space_from = new_space("", orientation = "RAS"), space_to = new_space("", orientation = "LPS") ) plot(surf_lps) # validate lps_verts <- diag(c(-1, -1, 1, 1)) %*% surf_ras$geometry$vertices range(surf_lps$geometry$vertices - lps_verts) # ---- Apply transforms ------------------ transform <- matrix( byrow = TRUE, nrow = 4, c( 0.5, 0, 0.3, 1, 0, -1, 0.2, 2, 0, 0.7, -0.5, 4, 0, 0, 0, 1 ) ) surf_stretch <- surface_to_surface(surf_ras, transform = transform) plot(surf_stretch) # validate stretch_verts <- transform %*% surf_ras$geometry$vertices range(surf_stretch$geometry$vertices - stretch_verts) }
Converts an FSL FLIRT matrix from FSL scaled-voxel coordinates to world (RAS) coordinates. Allows partial conversion by specifying only source, only reference, or both images.
transform_flirt2ras(transform, source = NULL, reference = NULL)transform_flirt2ras(transform, source = NULL, reference = NULL)
transform |
an |
source |
source (moving) image used in FLIRT registration. Can be:
|
reference |
reference (fixed) image used in FLIRT registration. Can be:
|
FSL FLIRT matrices operate in a scaled-voxel coordinate system that depends on the image geometry. The conversion to world coordinates uses:
world_transform = ref_vox2ras %*% ref_fsl2vox %*% flirt %*% src_vox2fsl %*% src_ras2vox
Where:
src_ras2vox: Inverse of source image's voxel-to-RAS matrix
src_vox2fsl: Source voxel-to-FSL coordinate transform
flirt: The original FLIRT matrix
ref_fsl2vox: Inverse of reference voxel-to-FSL transform
ref_vox2ras: Reference image's voxel-to-RAS matrix
The FSL coordinate system uses scaled voxels with possible X-axis flip
depending on the image's sform determinant sign.
An ieegio_transforms object with updated orientations:
Both images provided: RAS -> RAS transform
Source only: RAS -> FSL transform (source side converted)
Reference only: FSL -> RAS transform (reference side converted)
Neither: FSL -> FSL transform (unchanged)
io_read_flirt_transform for reading FLIRT matrices
transform_orientation for general orientation transforms
## Not run: # Read FLIRT matrix xfm <- io_read_flirt_transform("source_to_reference.mat") # Full conversion to RAS coordinates xfm_ras <- transform_flirt2ras(xfm, source = "source.nii.gz", reference = "reference.nii.gz") # Partial conversion (reference side only) xfm_partial <- transform_flirt2ras(xfm, reference = "reference.nii.gz") # Using ieegio_volume objects src_vol <- read_volume("source.nii.gz", header_only = TRUE) ref_vol <- read_volume("reference.nii.gz", header_only = TRUE) xfm_ras <- transform_flirt2ras(xfm, source = src_vol, reference = ref_vol) ## End(Not run)## Not run: # Read FLIRT matrix xfm <- io_read_flirt_transform("source_to_reference.mat") # Full conversion to RAS coordinates xfm_ras <- transform_flirt2ras(xfm, source = "source.nii.gz", reference = "reference.nii.gz") # Partial conversion (reference side only) xfm_partial <- transform_flirt2ras(xfm, reference = "reference.nii.gz") # Using ieegio_volume objects src_vol <- read_volume("source.nii.gz", header_only = TRUE) ref_vol <- read_volume("reference.nii.gz", header_only = TRUE) xfm_ras <- transform_flirt2ras(xfm, source = src_vol, reference = ref_vol) ## End(Not run)
Generates an affine transformation to convert coordinates or coordinate
frames between different anatomical orientation conventions (e.g., RAS to LPS).
Supports all 48 possible 3D orientations including axis permutations, plus
FSL scaled-voxel coordinates (which require an image for conversion).
transform_orientation( space_from, orientation_from, orientation_to, interpretation = c("active", "passive"), image = NULL )transform_orientation( space_from, orientation_from, orientation_to, interpretation = c("active", "passive"), image = NULL )
space_from |
either an |
orientation_from |
character string specifying the source orientation
(e.g., |
orientation_to |
character string specifying the target orientation.
Must be one of the 48 valid orientation codes plus |
interpretation |
character string specifying transform interpretation:
|
image |
optional image for FSL coordinate conversion. Required when
either |
The function creates orthogonal transformations (rotations and reflections) to convert between different anatomical coordinate conventions. For active transforms, the matrix can be directly applied to homogeneous point coordinates. For passive transforms, the matrix transforms coordinate axes/frames instead.
Common orientation codes (first 8):
RAS, LAS, LPS, RPS, LPI, RPI, LAI, RAI (standard axis order)
Extended orientations (40 more) include axis permutations like:
PIR, AIL, SAR, etc. (permuted axes)
FSL Coordinates:
When "FSL" orientation is involved, an image is required for conversion
because FSL coordinates are image-dependent (scaled voxels with possible X-flip).
Three scenarios are supported:
FSL -> FSL: Identity transform (no image needed)
FSL -> RAS/other: Uses vox2ras %*% fsl2vox from image
RAS/other -> FSL: Uses vox2fsl %*% ras2vox from image
The relationship between active and passive interpretations:
passive_matrix = t(active_matrix) for orthogonal transforms.
An ieegio_transforms object containing a 4x4 affine
transformation matrix
# Active transform: convert point coordinates from RAS to LPS trans <- transform_orientation(orientation_from = "RAS", orientation_to = "LPS", interpretation = "active") trans$data[[1]] # diag(-1, -1, 1, 1) # Apply to a point point_ras <- c(10, 20, 30, 1) point_lps <- trans$data[[1]] %*% point_ras # Using a space object space <- new_space("scanner", orientation = "RAS") trans <- transform_orientation(space_from = space, orientation_to = "LPS") # Passive transform: transform coordinate axes trans_passive <- transform_orientation(orientation_from = "RAS", orientation_to = "LPS", interpretation = "passive") # With axis permutation trans <- transform_orientation(orientation_from = "RAS", orientation_to = "PIR") ## Not run: # FSL to RAS conversion (requires image) trans_fsl2ras <- transform_orientation(orientation_from = "FSL", orientation_to = "RAS", image = "brain.nii.gz") ## End(Not run)# Active transform: convert point coordinates from RAS to LPS trans <- transform_orientation(orientation_from = "RAS", orientation_to = "LPS", interpretation = "active") trans$data[[1]] # diag(-1, -1, 1, 1) # Apply to a point point_ras <- c(10, 20, 30, 1) point_lps <- trans$data[[1]] %*% point_ras # Using a space object space <- new_space("scanner", orientation = "RAS") trans <- transform_orientation(space_from = space, orientation_to = "LPS") # Passive transform: transform coordinate axes trans_passive <- transform_orientation(orientation_from = "RAS", orientation_to = "LPS", interpretation = "passive") # With axis permutation trans <- transform_orientation(orientation_from = "RAS", orientation_to = "PIR") ## Not run: # FSL to RAS conversion (requires image) trans_fsl2ras <- transform_orientation(orientation_from = "FSL", orientation_to = "RAS", image = "brain.nii.gz") ## End(Not run)
Create smooth surface from volume mask or data
volume_to_surface( volume, lambda = 0.2, degree = 2, threshold_lb = 0.5, threshold_ub = NA, ... )volume_to_surface( volume, lambda = 0.2, degree = 2, threshold_lb = 0.5, threshold_ub = NA, ... )
volume |
volume object or path to the NIfTI volume files, see
|
lambda, degree
|
smooth parameters; see
|
threshold_lb, threshold_ub
|
threshold of volume, see
|
... |
passed to |
A as_ieegio_surface object; the surface is
transformed into anatomical space defined by the volume.
# toy example; in practice, use tha path to the volume volume <- array(0, dim = rep(30, 3)) volume[11:20, 11:20, 3:28] <- 1 volume[3:28, 11:20, 11:20] <- 1 volume[11:20, 3:28, 11:20] <- 1 vox2ras <- diag(1, 4) surf <- volume_to_surface(volume, vox2ras = vox2ras) if(interactive()) { plot(surf) }# toy example; in practice, use tha path to the volume volume <- array(0, dim = rep(30, 3)) volume[11:20, 11:20, 3:28] <- 1 volume[3:28, 11:20, 11:20] <- 1 volume[11:20, 3:28, 11:20] <- 1 vox2ras <- diag(1, 4) surf <- volume_to_surface(volume, vox2ras = vox2ras) if(interactive()) { plot(surf) }
Currently supports continuous 'EDF+' format with annotations
as_edf_channel( x, channel_num, sample_rate, label = sprintf("Ch%d", channel_num), physical_min = NA, physical_max = NA, is_annotation = NA, transducer_type = "", unit = "uV", filter = "", comment = "" ) write_edf( channels, con, patient_id = "anomymous", recording_id = NULL, record_duration = NA, physical_min = NA, physical_max = NA, start_time = Sys.time() )as_edf_channel( x, channel_num, sample_rate, label = sprintf("Ch%d", channel_num), physical_min = NA, physical_max = NA, is_annotation = NA, transducer_type = "", unit = "uV", filter = "", comment = "" ) write_edf( channels, con, patient_id = "anomymous", recording_id = NULL, record_duration = NA, physical_min = NA, physical_max = NA, start_time = Sys.time() )
x |
channel signals or annotations; for signals, |
channel_num |
channel number, integer |
sample_rate |
sampling frequency |
label |
channel label, default is |
physical_min, physical_max
|
range of the channel values when converting
from physical unit to digital; default is the range of |
is_annotation |
whether the channel is annotation |
transducer_type |
transducer type |
unit |
physical unit or dimension; default is |
filter |
preliminary filters applied to the signals |
comment |
additional comments (maximum 32 bytes) |
channels |
list of channel data, each element should be generated
from |
con |
file path or binary connection |
patient_id |
patient identifier; default is |
recording_id |
recording identifier |
record_duration |
duration of each recording chunk: 'EDF' format slices the data into equal-length chunks and writes the data (interleave channels) to file; this is the duration for each chunk, not the entire recording length |
start_time |
start time of the recording; see |
as_edf_channel returns a channel wrapper (with metadata);
write_edf writes to the connection and returns nothing
signal <- sin(seq(0, 10, 0.01)) channels <- list( # signal as_edf_channel(channel_num = 1, signal, sample_rate = 375.5), as_edf_channel(channel_num = 2, signal, sample_rate = 200), # annotation as_edf_channel(channel_num = 3, data.frame( timestamp = c(0, 1, 2), comments = c("Start", "half to go", "Finish!") )) ) # write to file path <- tempfile(fileext = ".edf") write_edf(con = path, channels = channels) edf <- read_edf(con = path, extract_path = tempdir()) annot <- edf$get_annotations() annot ch1 <- edf$get_channel(1) # around 1e-5 due to digitization range(ch1$value[seq_along(signal)] - signal) ch2 <- edf$get_channel(2) range(ch2$value[seq_along(signal)] - signal) plot(ch1$time, ch1$value, type = "l", main = "Toy-example") lines(ch2$time, ch2$value, col = "red") abline(v = annot$timestamp, col = "gray", lty = 2) edf$delete() unlink(path)signal <- sin(seq(0, 10, 0.01)) channels <- list( # signal as_edf_channel(channel_num = 1, signal, sample_rate = 375.5), as_edf_channel(channel_num = 2, signal, sample_rate = 200), # annotation as_edf_channel(channel_num = 3, data.frame( timestamp = c(0, 1, 2), comments = c("Start", "half to go", "Finish!") )) ) # write to file path <- tempfile(fileext = ".edf") write_edf(con = path, channels = channels) edf <- read_edf(con = path, extract_path = tempdir()) annot <- edf$get_annotations() annot ch1 <- edf$get_channel(1) # around 1e-5 due to digitization range(ch1$value[seq_along(signal)] - signal) ch2 <- edf$get_channel(2) range(ch2$value[seq_along(signal)] - signal) plot(ch1$time, ch1$value, type = "l", main = "Toy-example") lines(ch2$time, ch2$value, col = "red") abline(v = annot$timestamp, col = "gray", lty = 2) edf$delete() unlink(path)