diff --git a/NAMESPACE b/NAMESPACE index 140337e3..99191dfe 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -177,6 +177,7 @@ export(ngraph) export(nlapply) export(nmapply) export(nopen3d) +export(npop3d) export(nrrd.voxdims) export(origin) export(pointsinside) @@ -239,6 +240,7 @@ importFrom(nat.utils,makelock) importFrom(nat.utils,removelock) importFrom(rgl,par3d) importFrom(rgl,plot3d) +importFrom(rgl,pop3d) importFrom(rgl,tmesh3d) importFrom(rgl,triangles3d) importFrom(tools,md5sum) diff --git a/R/neuronlist.R b/R/neuronlist.R index 95437ab8..75687e68 100644 --- a/R/neuronlist.R +++ b/R/neuronlist.R @@ -184,8 +184,13 @@ nmapply<-function(FUN, ..., MoreArgs = NULL, SIMPLIFY = FALSE, USE.NAMES = TRUE) #' appropriate), the values are used to plot cell bodies. For neurons the #' values are passed to \code{plot3d.neuron} for neurons. In contrast #' \code{dotprops} objects still need special handling. There must be columns -#' called \code{X,Y,Z} in the data.frame attached to \code{x}, that are then +#' called \code{X,Y,Z} in the data.frame attached to \code{x}, that are then #' used directly by code in \code{plot3d.neuronlist}. +#' +#' Whenever plot3d.neuronlist is called, it will add an entry to an +#' environment \code{.plotted3d} in \code{nat} that stores the ids of all the +#' plotted shapes (neurons, cell bodies) so that they can then be removed by a +#' call to \code{npop3d}. #' @param x a neuron list or, for \code{plot3d.character}, a character vector of #' neuron names. The default neuronlist used by plot3d.character can be set by #' using \code{options(nat.default.neuronlist='mylist')}. See @@ -261,6 +266,7 @@ plot3d.neuronlist<-function(x, subset, col=NULL, colpal=rainbow, skipRedraw=200, if(is.logical(soma)) soma=2 rval <- c(rval, spheres3d(df[, c("X", "Y", "Z")], radius = soma, col = cols)) } + assign(".last.plot3d", rval, envir=.plotted3d) df$col=cols attr(rval,'df')=df invisible(rval) diff --git a/R/pop3d.R b/R/pop3d.R new file mode 100644 index 00000000..80a06764 --- /dev/null +++ b/R/pop3d.R @@ -0,0 +1,19 @@ +#' Remove plotted neurons or other 3d objects +#' +#' The normal usage will not specify \code{x} in which case the last neurons +#' plotted by \code{plot3d.neuronlist} or any of its friends will be removed. +#' @param x rgl ids of objects to remove +#' @param slow Whether to remove neurons one by one (slowly) default: FALSE +#' @param type Type of objects to remove see \code{pop3d}. +#' @export +#' @seealso \code{\link[rgl]{pop3d}}, \code{\link{plot3d.neuronlist}} +#' @importFrom rgl pop3d +npop3d <- function(x, slow=FALSE, type='shapes') { + if(missing(x)){ + if(exists(".last.plot3d", envir=.plotted3d)) + x <- get(".last.plot3d", envir=.plotted3d) + else x <- NULL + } + if(slow) invisible(sapply(x, function(x) try(pop3d(x, type=type)))) + else try(pop3d(unlist(x), type=type)) +} diff --git a/R/zzz.R b/R/zzz.R index 71f569cb..21581a43 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -24,4 +24,7 @@ } # will store information about formats that we can read -.fileformats <- new.env() \ No newline at end of file +.fileformats <- new.env() + +# Will store stack of plotted rgl objects, ready for popping +.plotted3d <- new.env() diff --git a/man/npop3d.Rd b/man/npop3d.Rd new file mode 100644 index 00000000..024c21e0 --- /dev/null +++ b/man/npop3d.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2 (4.0.1): do not edit by hand +\name{npop3d} +\alias{npop3d} +\title{Remove plotted neurons or other 3d objects} +\usage{ +npop3d(x, slow = FALSE, type = "shapes") +} +\arguments{ + \item{x}{rgl ids of objects to remove} + + \item{slow}{Whether to remove neurons one by one (slowly) + default: FALSE} + + \item{type}{Type of objects to remove see \code{pop3d}.} +} +\description{ +The normal usage will not specify \code{x} in which case +the last neurons plotted by \code{plot3d.neuronlist} or any +of its friends will be removed. +} +\seealso{ +\code{\link[rgl]{pop3d}}, \code{\link{plot3d.neuronlist}} +} + diff --git a/man/plot3d.neuronlist.Rd b/man/plot3d.neuronlist.Rd index 2611a6be..25de39ab 100644 --- a/man/plot3d.neuronlist.Rd +++ b/man/plot3d.neuronlist.Rd @@ -90,6 +90,12 @@ must be columns called \code{X,Y,Z} in the data.frame attached to \code{x}, that are then used directly by code in \code{plot3d.neuronlist}. +Whenever plot3d.neuronlist is called, it will add an entry +to an environment \code{.plotted3d} in \code{nat} that +stores the ids of all the plotted shapes (neurons, cell +bodies) so that they can then be removed by a call to +\code{npop3d}. + plot3d.character will check if options('nat.default.neuronlist') has been set and then use x as an identifier to find a neuron in that neuronlist. diff --git a/tests/testthat/test-pop3d.R b/tests/testthat/test-pop3d.R new file mode 100644 index 00000000..ef0315e9 --- /dev/null +++ b/tests/testthat/test-pop3d.R @@ -0,0 +1,10 @@ +context("npop3d") + +test_that("pop last plotted neurons",{ + open3d() + original.rgl.ids=rgl.ids() + plot3d(c("EBH11R", "EBH20L"), db=Cell07PNs) + npop3d() + expect_equal(rgl.ids(), original.rgl.ids) + rgl.close() +})