Skip to content

Commit

Permalink
Updated banc_decapitate and ggplot util function for neurons
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderbates committed Jul 4, 2024
1 parent eff17ef commit e630eb7
Show file tree
Hide file tree
Showing 11 changed files with 325 additions and 51 deletions.
18 changes: 17 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
# Generated by roxygen2: do not edit by hand

S3method(banc_decapitate,data.frame)
S3method(banc_decapitate,matrix)
S3method(banc_decapitate,mesh3d)
S3method(banc_decapitate,neuron)
S3method(banc_decapitate,neuronlist)
S3method(ggplot2_neuron_path,neuron)
S3method(ggplot2_neuron_path,neuronlist)
export(banc_all_synapses)
export(banc_backbone_proofread)
export(banc_brain_neuropil.surf)
export(banc_cave_client)
export(banc_cave_query)
export(banc_cave_tables)
Expand All @@ -10,11 +18,14 @@ export(banc_cell_info)
export(banc_cellid_from_segid)
export(banc_change_log)
export(banc_decapitate)
export(banc_front_view)
export(banc_ids)
export(banc_islatest)
export(banc_latestid)
export(banc_leaves)
export(banc_neck_connective.surf)
export(banc_neck_connective_neurons)
export(banc_neuropil.surf)
export(banc_nm2raw)
export(banc_nuclei)
export(banc_partner_summary)
Expand All @@ -24,16 +35,21 @@ export(banc_raw2nm)
export(banc_read_l2dp)
export(banc_read_l2skel)
export(banc_read_neuroglancer_mesh)
export(banc_read_neuron_meshes)
export(banc_read_nuclei_mesh)
export(banc_rootid)
export(banc_scene)
export(banc_segid_from_cellid)
export(banc_set_token)
export(banc_side_view)
export(banc_view)
export(banc_vnc_neuropil.surf)
export(banc_vnc_view)
export(banc_voxdims)
export(banc_xyz2id)
export(choose_banc)
export(dr_banc)
export(banc_read_neuron_meshes)
export(ggplot2_neuron_path)
export(with_banc)
import(bit64)
import(fafbseg)
Expand Down
140 changes: 140 additions & 0 deletions R/ggplot2.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
banc_neuron_comparison_plot <- function(neuron1, neuron2,
filename = NULL,
width = 8, height = 6) {

# Get 3D spatial points
glist <- list()
for(view in names(banc_rotation_matrices)){

# Choose mesh
if(view=="front"){
mesh <- banc_brain_neuropil.surf
decaptitate <- "brain"
}else if(view=="vnc"){
mesh <- banc_vnc_neuropil.surf
decaptitate <- "vnc"
}else{
mesh <- banc_neuropil.surf
decaptitate <- "none"
}

# Get 3D points
vertices <- nat::xyzmatrix(mesh)
if(decaptitate=="brain"){
neuron_pruned1 <- banc_decapitate(neuron1, invert = TRUE)
neuron_pruned2 <- banc_decapitate(neuron2, invert = TRUE)
}else if(decaptitate=="vnc"){
neuron_pruned1 <- banc_decapitate(neuron1, invert = FALSE)
neuron_pruned2 <- banc_decapitate(neuron2, invert = FALSE)
}else{
neuron_pruned1=neuron1
neuron_pruned2=neuron2
}

# Rotate mesh
rotation_matrix <- banc_rotation_matrices[[view]]
rotated_vertices <- as.data.frame(t(rotation_matrix[,1:3] %*% t(as.matrix(vertices))))
rotated_vertices <- rotated_vertices[,-4]
colnames(rotated_vertices) <- c("X","Y","Z")

# Process neuron 1
edges_df1 <- ggplot2_neuron_path(neuron_pruned1, rotation_matrix=rotation_matrix)

# Process neuron 2
edges_df2 <- ggplot2_neuron_path(neuron_pruned2, rotation_matrix=rotation_matrix)

# Create the plot
p <- ggplot() +
geom_point(data = rotated_vertices, aes(x = X, y = Y), color = "grey", size = 1, alpha = 0.05) +
#scale_color_gradient(low = "grey100", high = "grey50") +
ggnewscale::new_scale_colour() +
geom_path(data = edges_df1, aes(x = X, y = Y, color = Z, group = group), alpha = 0.5, linewidth = 0.5) +
scale_color_gradient(low = "navy", high = "cyan") +
ggnewscale::new_scale_colour() +
geom_path(data = edges_df2, aes(x = X, y = Y, color = Z, group = group), alpha = 0.5, linewidth = 0.5) +
scale_color_gradient(low = "coral", high = "darkred") +
theme_minimal() +
coord_equal() +
labs(title = view) +
theme(legend.position = "none") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())

# Add to list
glist[[view]] <- p
}

# Arrange plot
g <- gridExtra::grid.arrange(glist[["main"]], glist[["side"]], glist[["front"]], glist[["vnc"]], ncol = 2,
layout_matrix = rbind(c(1,1,1,2,2,3,3,3,3),
c(1,1,1,2,2,3,3,3,3),
c(1,1,1,2,2,4,4,4,4),
c(1,1,1,2,2,4,4,4,4)
))
if(filename){
ggsave(filename, plot = p, width = width, height = height)
invisible()
}else{
plot(g)
}
}

#' Convert Neuron Objects to ggplot2-Compatible Path Data
#'
#' @description
#' This function converts 'neuron' or 'neuronlist' objects, which represent 3D
#' points linked by lines in space, into data frames that describe paths
#' compatible with ggplot2's geom_path.
#'
#' @param x A 'neuron' or 'neuronlist' object to be converted.
#' @param rotation_matrix An optional 4x4 rotation matrix to apply to the neuron coordinates.
#' @param ... Additional arguments passed to methods.
#'
#' @return A data frame with columns X, Y, Z, and group, where each group
#' represents a continuous path in the neuron.
#'
#' @export
ggplot2_neuron_path <- function(x, rotation_matrix = NULL, ...) UseMethod('ggplot2_neuron_path')

#' @rdname ggplot2_neuron_path
#' @method ggplot2_neuron_path neuron
#' @export
ggplot2_neuron_path.neuron <- function(x, rotation_matrix = NULL){
x$d <- x$d[order(x$d$Parent),]
x$d <- x$d[order(x$d$PointNo),]
npoints <- nat::xyzmatrix(x)
edges_df <- data.frame()
if(!is.null(rotation_matrix)){
npoints <- as.data.frame(t(rotation_matrix[,1:3] %*% t(xyzmatrix(npoints))))
npoints <- npoints[,-4]
colnames(npoints) <- c("X","Y","Z")
}
ss <-nat::seglist(x)
seglist <- ss[[1]]$SegList
for(s in 1:length(seglist)){
g <- npoints[seglist[[s]],]
g$group <- s
edges_df <- rbind(edges_df,g)
}
edges_df
}

#' @rdname ggplot2_neuron_path
#' @method ggplot2_neuron_path neuronlist
#' @export
ggplot2_neuron_path.neuronlist <- function(x, rotation_matrix = NULL){
ll <- lapply(x, ggplot2_neuron_path, rotation_matrix = rotation_matrix, ...)
max.group <- 0
for(i in 1:length(ll)){
ll[[i]]$group <- ll[[i]]$group + max.group
max.group <- max(ll[[i]]$group, na.rm = TRUE)
}
do.call(rbind, ll)
}



83 changes: 45 additions & 38 deletions R/meshes.R
Original file line number Diff line number Diff line change
Expand Up @@ -61,47 +61,54 @@ banc_read_nuclei_mesh <- function(ids, lod = 1L, savedir=NULL, method=c('vf', '
#' plot3d(m.brain, col = "cyan")
#' plot3d(banc.surf, col = "grey", alpha = 0.1)
#' }
banc_decapitate <- function(x, invert = FALSE, reference = "BANC"){
y.cut <- 5e+05
v1 <- c(0,y.cut,0)
v2 <- c(1e10,y.cut,0)
v3 <- c(0,y.cut,1e10)
if (reference!="BANC"){
v1 <- nat.templatebrains::xform_brain(v1, sample = "BANC", reference = reference)
v2 <- nat.templatebrains::xform_brain(v2, sample = "BANC", reference = reference)
v3 <- nat.templatebrains::xform_brain(v3, sample = "BANC", reference = reference)
y.cut <- v1[,2]
banc_decapitate<-function(x, y.cut = 5e+05, invert = FALSE, ...) UseMethod('banc_decapitate')

#' @export
#' @rdname banc_decapitate
banc_decapitate.neuron <- function(x, y.cut = 5e+05, invert = FALSE, ...){
z <- as.data.frame(nat::xyzmatrix(x))
rownames(z) <- x$d$PointNo
z <- subset(z,z$Y<y.cut)
nat::prune_vertices(x, verticestoprune = rownames(z), invert = invert, ...)
}

#' @export
#' @rdname banc_decapitate
banc_decapitate.neuronlist <- function(x, y.cut = 5e+05, invert = FALSE, ...){
nat::nlapply(x, banc_decapitate, y.cut = y.cut, invert = invert, ...)
}

#' @export
#' @rdname banc_decapitate
banc_decapitate.matrix <- function(x, y.cut = 5e+05, invert = FALSE){
z <- nat::xyzmatrix(x)
if(invert){
z[z[,2]<y.cut,]
}else{
z[z[,2]>y.cut,]
}
ismesh <- any( c(class(x[[1]]), class(x)) %in% "mesh3d")
if(!ismesh & any(class(x)%in%c("neuron","neuronlist","mesh3d"))){
if (invert){
z <- subset(x,x$y<y.cut)
}else{
z <- subset(x,x$y>y.cut)
}
}else if (ismesh){
if (any(class(x)=="mesh3d")){
z <- Morpho::cutMeshPlane(x,
v1=v1, v2=v2, v3=v3,
normal = NULL, keep.upper = invert)
}else if (any(class(x)=="neuronlist")){
z <- nat::nlapply(x, Morpho::cutMeshPlane,
v1=v1, v2=v2, v3=v3,
normal = NULL, keep.upper = invert)
}else{
z <- lapply(x, Morpho::cutMeshPlane,
v1=v1, v2=v2, v3=v3,
normal = NULL, keep.upper = invert)
}
}

#' @export
#' @rdname banc_decapitate
banc_decapitate.data.frame <- function(x, y.cut = 5e+05, invert = FALSE){
z <- nat::xyzmatrix(x)
if(invert){
x[z[,2]<y.cut,]
}else{
ydim <- intersect(colnames(x),c("Y","y"))[[1]]
if (invert){
z <- x[x[,ydim]<y.cut,]
}else{
z <- x[x[,ydim]>y.cut,]
}
x[z[,2]>y.cut,]
}
z
}

#' @export
#' @rdname banc_decapitate
banc_decapitate.mesh3d <- function(x, y.cut = 5e+05, invert = FALSE, ...){
v1 <- c(0,y.cut,0)
v2 <- c(1e10,y.cut,0)
v3 <- c(0,y.cut,1e10)
Morpho::cutMeshPlane(x,
v1=v1, v2=v2, v3=v3,
normal = NULL, keep.upper = invert)
}

#' Read BANC euroglancer meshes, e.g., ROI meshes
Expand Down
20 changes: 20 additions & 0 deletions man/banc.surf.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion man/banc_all_synapses.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions man/banc_cellid_from_segid.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 16 additions & 1 deletion man/banc_decapitate.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
Loading

0 comments on commit e630eb7

Please sign in to comment.