Skip to content

Commit

Permalink
Add hemibrain_neuron_meshes
Browse files Browse the repository at this point in the history
  • Loading branch information
jefferis committed Apr 13, 2021
1 parent 781c63f commit f9156f4
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 2 deletions.
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ Suggests:
elmr,
dbscan,
RColorBrewer,
nat.hdf5
nat.hdf5,
Rvcg
VignetteBuilder: knitr
Depends:
R (>= 3.1),
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ export(hemibrain_meta)
export(hemibrain_multi3d)
export(hemibrain_nblast)
export(hemibrain_neuron_bodyids)
export(hemibrain_neuron_meshes)
export(hemibrain_neurons)
export(hemibrain_overlap_locality)
export(hemibrain_prune_online)
Expand Down Expand Up @@ -207,6 +208,7 @@ importFrom(dplyr,group_by)
importFrom(dplyr,mutate)
importFrom(dplyr,n)
importFrom(dplyr,select)
importFrom(fafbseg,flywire_cloudvolume)
importFrom(foreach,"%do%")
importFrom(foreach,"%dopar%")
importFrom(googledrive,as_id)
Expand Down
99 changes: 99 additions & 0 deletions R/hemibrain_neuron_meshes.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# convert cloudvolume python mesh to an R mesh3d object
# method vf just uses the vertex and face arrays
# ply writes out to Stanford ply format and reads back in again
#' @importFrom
cvmesh2mesh <- function(x, method=c('vf', 'ply'), ...) {
method=match.arg(method)
if(method=='vf') {
verts=t(x$vertices)
stopifnot(nrow(verts)==3)
faces=t(x$faces+1)
stopifnot(max(faces)<=ncol(verts))
stopifnot(min(faces)>0)
stopifnot(nrow(faces)==3)
m=rgl::tmesh3d(vertices = verts, indices = faces, homogeneous = F)
} else {
bytes=x$to_ply()
tf=tempfile(fileext = paste0('.', method))
on.exit(unlink(tf))
writeBin(bytes, con = tf)
m=Rvcg::vcgPlyRead(tf, ...)
}
m
}

#' Read hemibrain neurite or mitochondrial meshes into an R neuronlist object
#'
#' @description \code{hemibrain_neuron_meshes} reads standard neuron meshes
#'
#' @param bodyids One more hemibrain body ids (including as expressions passed
#' to \code{\link{neuprint_ids}})
#' @param lod the level of detail (highest resolution is 0, default of 2 gives a
#' good overall morphology while 3 is also useful and smaller still)
#' @param cloudvolume.url Optional a specific URL from which to download mesh
#' data.
#' @param conn A neuprint connection to the hemibrain dataset
#' @param dataset Optionally specify which version of the hemibrain dataset to
#' use (when \code{NULL} uses the most recent)
#' @param ... Additional arguments passed to \code{\link{nlapply}}
#'
#' @return A \code{\link{neuronlist}} object
#' @export
#'
#' @examples
#' \donttest{
#' da2.lod3=hemibrain_neuron_meshes("DA2_lPN", lod=3)
#' da2.lod3
#' }
#' \dontrun{
#' da2=hemibrain_neuron_meshes("DA2_lPN")
#' # lod 2 ~ 5x bigger than lod 3 but does look nicer
#' da2
#' plot3d(da2)
#'
#' da2mito=hemibrain_mito_meshes("DA2_lPN")
#'
#' # if you just wanted one neuron (as a mesh3d object) rather than neuronlist
#' dl4=hemibrain_neuron_meshes("name:DL4_adPN_R")[[1]]
#' }
#' @importFrom fafbseg flywire_cloudvolume
hemibrain_neuron_meshes <- function(bodyids, lod=2L, cloudvolume.url=NULL, conn=NULL, dataset=NULL, ...) {
dataset = neuprintr:::check_dataset(dataset, conn = conn)
bodyids = neuprintr::neuprint_ids(bodyids, conn = conn, dataset = dataset)
if(is.null(cloudvolume.url)) {
cloudvolume.url = sprintf(
"precomputed://gs://neuroglancer-janelia-flyem-%s/segmentation",
sub(":", "/", dataset, fixed = T)
)
}
# in case they are integer64
bodyids=as.character(bodyids)
nn=bodyids;names(nn) <- bodyids
res=nlapply(nn, hemibrain_neuron_mesh, lod=lod, cloudvolume.url=cloudvolume.url, ...)
res[,] <- neuprint_get_meta(names(res), conn=conn, dataset = dataset)
return(res)
}

hemibrain_neuron_mesh <- function(bodyids, lod, cloudvolume.url, method='vf') {
cv=fafbseg::flywire_cloudvolume(cloudvolume.url = cloudvolume.url)
# convert to python longint if necessary
li=reticulate::py_eval(bodyids, convert = F)
lod=as.integer(lod)
cm=cv$mesh$get(li, lod = lod)
if(!any(bodyids %in% names(cm))) {
stop("Failed to read segid: ", bodyids)
}
# we get back a dict where the key is a python 64 bit int
cmesh=reticulate::py_get_item(cm, li)
m=cvmesh2mesh(cmesh, method=method)
m
}


#' @rdname hemibrain_neuron_meshes
#' @description \code{hemibrain_mito_meshes} reads mitochondrial meshes
hemibrain_mito_meshes <- function(bodyids, lod=2L, ...) {
cvu="precomputed://gs://neuroglancer-janelia-flyem-hemibrain/v1.2/mito-objects-grouped"
hemibrain_neuron_meshes(bodyids, lod=lod, cloudvolume.url = cvu, ...)
}

3 changes: 2 additions & 1 deletion _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@ reference:
- 'hemibrain_somas'
- '`hemibrain_reroot`'
- 'hemilineages'
- title: Synapses and meshes
- title: Synapses and neuron and ROI meshes
desc: ~
contents:
- '`hemibrain_extract_synapses`'
- '`hemibrain_remove_bad_synapses`'
- '`hemibrain_neuron_meshes`'
- '`hemibrain_roi_meshes`'
- 'hemibrain.surf'
- 'hemibrain_al.surf'
Expand Down
60 changes: 60 additions & 0 deletions man/hemibrain_neuron_meshes.Rd

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

0 comments on commit f9156f4

Please sign in to comment.