From 422cfeb7b3edf7c647d336acc080a984cff06f79 Mon Sep 17 00:00:00 2001 From: Gregory Jefferis Date: Wed, 6 Jan 2021 01:01:51 +0000 Subject: [PATCH] add [[.neuronlistfh * also test and document --- NAMESPACE | 1 + R/neuronlistfh.R | 43 ++++++++++++++++++++++++++++++ man/neuronlistfh.Rd | 21 +++++++++++++++ tests/testthat/test-neuronlistfh.R | 11 ++++++++ 4 files changed, 76 insertions(+) diff --git a/NAMESPACE b/NAMESPACE index b2b52a82..d678313a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -9,6 +9,7 @@ S3method("[",neuronlistfh) S3method("[",reglist) S3method("[<-",neuronlist) S3method("[[",neuronlistfh) +S3method("[[<-",neuronlistfh) S3method("boundingbox<-",default) S3method("data.frame<-",neuronlist) S3method("xyzmatrix<-",character) diff --git a/R/neuronlistfh.R b/R/neuronlistfh.R index 68d9fae4..152d01ff 100644 --- a/R/neuronlistfh.R +++ b/R/neuronlistfh.R @@ -17,6 +17,25 @@ #' They will usually read them using \code{read.neuronlistfh} and sometimes #' create them by using \code{as.neuronlistfh} on a \code{neuronlist} object. #' +#' @section Modifying neuronlistfh objects: There is very basic support for +#' modifying neuronlistfh objects using the \code{[[} operator. There are two +#' modes depending on the nature of the index in the assignment operation +#' \code{nlfh[[index]]<-neuron}: \itemize{ +#' +#' \item numeric index \emph{for replacement of items only} +#' +#' \item character index \emph{for replacement \bold{or} addition of items} +#' +#' } +#' +#' This distinction is because there must be a character key provided to name +#' the neuron when a new one is being added, whereas an existing element can +#' be referenced by position (i.e. the numeric index). Unfortunately the end +#' user is responsible for manully modifying the attached data.frame when new +#' neurons are added. Doing \code{nlfh[[index]]<-neuron} will do the +#' equivalent of \code{attr(nlfh, 'df')[i, ]=NA} i.e. add a row containing NA +#' values. +#' #' @section Implementation details: neuronlistfh objects are a hybrid between #' regular \code{neuronlist} objects that organise data and metadata for #' collections of neurons and a backing \code{filehash} object. Instead of @@ -272,6 +291,30 @@ as.neuronlist.neuronlistfh<-function(l, ...){ }) } +#' @export +"[[<-.neuronlistfh" <- function (x, i, j, ..., value) { + hash=digest(value) + append=FALSE + if(is.numeric(i)) { + if(i<1 || i > length(x)) + stop("i must be between 1 and ", length(x), "To append using a string index.") + } else { + if(!is.character(i)) stop("i must be a numeric or character index!") + append = !(i %in% names(x)) + } + attr(x, "keyfilemap")[i]=hash + filehash::dbInsert(attr(x, 'db'), hash, value) + # add another row to dataframe + if(append){ + # x is a dummy logical vector, key thing is that this sets the name of x[i] + x[i]=FALSE + attr(x, 'df')[i, ]=NA + } else { + # nothing to do + } + x +} + #' @export as.list.neuronlistfh<-function(x, ...) x diff --git a/man/neuronlistfh.Rd b/man/neuronlistfh.Rd index f07fff82..752fdd00 100644 --- a/man/neuronlistfh.Rd +++ b/man/neuronlistfh.Rd @@ -86,6 +86,27 @@ a \code{neuronlistfh} object which is a character \code{vector} with \code{as.neuronlistfh.neuronlist} converts a regular neuronlist to one backed by a filehash object with an on disk representation } +\section{Modifying neuronlistfh objects}{ + There is very basic support for + modifying neuronlistfh objects using the \code{[[} operator. There are two + modes depending on the nature of the index in the assignment operation + \code{nlfh[[index]]<-neuron}: \itemize{ + + \item numeric index \emph{for replacement of items only} + + \item character index \emph{for replacement \bold{or} addition of items} + + } + + This distinction is because there must be a character key provided to name + the neuron when a new one is being added, whereas an existing element can + be referenced by position (i.e. the numeric index). Unfortunately the end + user is responsible for manully modifying the attached data.frame when new + neurons are added. Doing \code{nlfh[[index]]<-neuron} will do the + equivalent of \code{attr(nlfh, 'df')[i, ]=NA} i.e. add a row containing NA + values. +} + \section{Implementation details}{ neuronlistfh objects are a hybrid between regular \code{neuronlist} objects that organise data and metadata for diff --git a/tests/testthat/test-neuronlistfh.R b/tests/testthat/test-neuronlistfh.R index 2d90b22c..4c6ff601 100644 --- a/tests/testthat/test-neuronlistfh.R +++ b/tests/testthat/test-neuronlistfh.R @@ -74,6 +74,17 @@ test_that("we can load a previously created on disk neuronlistfh representation" kcs20.db1 <- as.neuronlistfh(kcs20, dbdir=file.path(fhpath, 'db1'), dbClass='DB1') expect_equal(kcs20.db1[[1]], kcs20[[1]]) expect_equal(as.neuronlist(kcs20.db1), kcs20) + # make sure we can replace an element (identically in this case) + expect_silent(kcs20.db1[[1]] <- kcs20[[1]]) + expect_equal(as.neuronlist(kcs20.db1), kcs20) + + kcs19 <- as.neuronlistfh(kcs20[1:19], dbdir=file.path(fhpath, 'kcs19'), dbClass='DB1') + expect_silent(kcs19[[names(kcs20)[20]]] <- kcs20[[20]]) + expect_is(kcs19, 'neuronlistfh') + expect_equivalent(nl <- as.neuronlist(kcs19), kcs20) + # fix the last row of the attached metadata + nl[20,]=kcs20[20,] + expect_equal(nl, kcs20) }) test_that("we can create a neuronlistfh with a hashmap",{