R/augmentCordinateFeatures.R

Defines functions augmentCordinateFeatures augmentCordinateFeatures.PlateData augmentCordinateFeatures.WellData augmentCordinateFeatures.ImageData augmentCordinateFeatures.default

Documented in augmentCordinateFeatures

#' Augment all features involving locations
#'
#' All features containing the strings "Location_Center_X" or
#' "Location_Center_Y" are extended to include their membership to an ellipse (
#' concentric w.r.t. image center/well center), their membership to a tile (at
#' well and image level), the number of nonempty neighbor tiles, the type of
#' tile (inwards/outwards facing image border/edge) the distance to the image/
#' well center, the local object density to the image center. If features
#' labelled  with "Location_Shifted_X" or "Location_Shifted_Y" are present
#' (augmentImageLocation), Those are extended too.
#'
#' @param x           The PlateData/WellData/ImageData object of interest.
#' @param ellipse     An integer corresponding to the number of ellipses.
#' @param facet       A vector of length 2 e.g. c(14, 10) corresponding to the
#'                    number of bins in x-direction (14) and y-direction (10).
#' @param center.dist Logical, whether to include distances to image/well
#'                    centers.
#' @param density     Logical, whether to estimate densities.
#' 
#' @return The augmented version of the original object.
#' 
#' @examples
#' data <- PlateData(PlateLocation("J101-2C"))
#' aug <- augmentCordinateFeatures(data, 5, c(14, 10), TRUE, TRUE)
#' 
#' @export
augmentCordinateFeatures <- function(x, ...) {
  UseMethod("augmentCordinateFeatures", x)
}

#' @export
augmentCordinateFeatures.PlateData <- function(x, ellipse=NULL, facet=NULL,
                                               center.dist=FALSE,
                                               density=FALSE) {
  output <- augmentCordinateFeatures(x$data[[1]], ellipse, facet, center.dist,
                                     density)
  x$data <- llply(x$data, function(dat, ell, fac, cen, den) {
    suppressMessages(res <- augmentCordinateFeatures(dat, ell, fac, cen, den))
    return(res)
  }, ellipse, facet, center.dist, density,
  .progress=getOption("singleCellFeatures.progressBars"))
  return(x)
}

#' @export
augmentCordinateFeatures.WellData <- function(x, ellipse=NULL, facet=NULL,
                                              center.dist=FALSE,
                                              density=FALSE) {
  output <- augmentCordinateFeatures(x$data[[1]], ellipse, facet, center.dist,
                                     density)
  suppressMessages(x$data <- lapply(x$data, augmentCordinateFeatures, ellipse,
                   facet, center.dist, density))
  return(x)
}

#' @export
augmentCordinateFeatures.ImageData <- function(x, ellipse=NULL, facet=NULL,
                                               center.dist=FALSE,
                                               density=FALSE) {

  singleEllipse <- function(ind, x, y, cent, elli) {
    sum <- (x[,ind] - cent[1])^2 / (elli[1])^2 +
           (y[,ind] - cent[2])^2 / (elli[2])^2
    return(1 - (sum <= 1))
  }

  multipleEllipses <- function(ind, x, y, cent, n.ell, elli) {
    sum <- apply(elli, 2, function(e, x, y, cent) {
      return((x[,ind] - cent[1])^2 / (e[1])^2 +
             (y[,ind] - cent[2])^2 / (e[2])^2)
    }, x, y, cent)
    if(is.null(nrow(sum))) {
      subtr <- sum(sapply(sum, function(row) row <= 1))
    } else {
      subtr <- rowSums(apply(sum, 2, function(row) row <= 1))
    }
    res <- n.ell - subtr
    return(res)
  }

  facetCalc <- function(ind, x, fac) {
    return(ceiling(x[,ind] / fac))
  }

  facetType <- function(ind, x, y, facet, n.img, img) {
    res <- rep(0, length(x[,ind]))
    if(img == 1) {
      res <- res + (x[,ind] == facet[1])                     # inward boundary
      res <- res + (y[,ind] == 1)                            # inward boundary
      res <- res + 3 * (x[,ind] == 1)                        # outward boundary
      res <- res + 3 * (y[,ind] == facet[2])                 # outward boundary
      res <- res - (x[,ind] == 1 & y[,ind] == facet[2])      # outward corner
    } else if(img == 2) {
      res <- res + (y[,ind] == 1)                            # inward boundary
      res <- res + (x[,ind] == facet[1])                     # inward boundary
      res <- res + (x[,ind] == 1)                            # inward boundary
      res <- res + 3 * (y[,ind] == facet[2])                 # outward boundary
    } else if(img == 3) {
      res <- res + (x[,ind] == 1)                            # inward boundary
      res <- res + (y[,ind] == 1)                            # inward boundary
      res <- res + 3 * (x[,ind] == facet[1])                 # outward boundary
      res <- res + 3 * (y[,ind] == facet[2])                 # outward boundary
      res <- res - (x[,ind] == facet[1] & y[,ind] == facet[2])# outward corner
    } else if(img == 4 & n.img == 9) {
      res <- res + (y[,ind] == facet[2])                     # inward boundary
      res <- res + (x[,ind] == facet[1])                     # inward boundary
      res <- res + (y[,ind] == 1)                            # inward boundary
      res <- res + 3 * (x[,ind] == 1)                        # outward boundary
    } else if(img == 5 & n.img == 9) {
      res <- res + (y[,ind] == 1 | y[,ind] == facet[2])      # inward boundary
      res <- res + (x[,ind] == 1 | x[,ind] == facet[1])      # inward boundary
    } else if(img == 6 & n.img == 9) {
      res <- res + (y[,ind] == facet[2])                     # inward boundary
      res <- res + (x[,ind] == 1)                            # inward boundary
      res <- res + (y[,ind] == 1)                            # inward boundary
      res <- res + 3 * (x[,ind] == facet[1])                 # outward boundary
    } else if(img == (n.img - 2)) {
      res <- res + (x[,ind] == facet[1])                     # inward boundary
      res <- res + (y[,ind] == facet[2])                     # inward boundary
      res <- res + 3 * (x[,ind] == 1)                        # outward boundary
      res <- res + 3 * (y[,ind] == 1)                        # outward boundary
      res <- res - (x[,ind] == 1 & y[,ind] == 1)             # outward corner
    } else if(img == (n.img - 1)) {
      res <- res + (y[,ind] == facet[2])                     # inward boundary
      res <- res + (x[,ind] == facet[1])                     # inward boundary
      res <- res + (x[,ind] == 1)                            # inward boundary
      res <- res + 3 * (y[,ind] == 1)                        # outward boundary
    } else if(img == n.img) {
      res <- res + (x[,ind] == 1)                            # inward boundary
      res <- res + (y[,ind] == facet[2])                     # inward boundary
      res <- res + 3 * (x[,ind] == facet[1])                 # outward boundary
      res <- res + 3 * (y[,ind] == 1)                        # outward boundary
      res <- res - (x[,ind] == facet[1] & y[,ind] == 1)      # outward corner
    } else stop("can only deal with 6/9 image wells.")
    return(res)
  }

  facetBorder <- function(ind, x, y, facet) {
    # initialize empty grid/border matrices
    grid <- matrix(0, facet[2], facet[1])
    # calculate col-major grid index for each object
    index <- y[,ind] + (x[,ind] - 1) * facet[2]
    # summarize as counts
    counts <- table(index)
    # fill grid with counts
    grid[as.numeric(names(counts))] <- counts
    grid <- grid > 0
    # extend grid with a frame of zeros
    grid.ext <- rbind(rep(1, (facet[1] + 2)),
                      cbind(rep(1, facet[2]), grid, rep(1, facet[2])),
                      rep(1, (facet[1] + 2)))
    # set up stencil
    row <- rep(rep(1:facet[2], facet[1]))
    col <- rep(1:facet[1], each=facet[2])
    colP1 <- col + 1
    colM1 <- col - 1
    rowP1 <- row + 1
    rowP2 <- row + 2
    nrowP <- facet[2] + 2
    stencil <- cbind(row   + colM1 * nrowP, # northwest neighbor
                     row   + col   * nrowP, # north neighbor
                     row   + colP1 * nrowP, # northeast neighbor
                     rowP1 + colP1 * nrowP, # west neighbor
                     rowP2 + colP1 * nrowP, # east neighbor
                     rowP2 + col   * nrowP, # southwest neighbor
                     rowP2 + colM1 * nrowP, # south neighbor
                     rowP1 + colM1 * nrowP) # southeast neighbor
    # apply stencil row-wise to grid
    border <- apply(stencil, 1, function(ind, mat) {
      return(sum(mat[ind]))
    }, as.numeric(grid.ext))
    # map col-major object index to border array
    return(border[index])
    #border <- matrix(border, facet[2], facet[1])
    #matrix((as.numeric(border) * as.numeric(grid)), facet[2], facet[1])
  }

  distCalc <- function(ind, x, y, cent) {
    return(sqrt((x[,ind] - cent[1])^2 + (y[,ind] - cent[2])^2))
  }

  densCalc <- function(ind, x, y) {
    data <- cbind(x[,ind], y[,ind])
    if(nrow(data) < 2) {
      warning("not estimating densities with less than 2 cells.")
      return(rep(NA, nrow(data)))
    }
    capture.output(dens <- sm::sm.density(data, display="none"))
    surf <- list(x=dens$eval.points[, 1],
                 y=dens$eval.points[, 2],
                 z=dens$estimate)
    res  <- fields::interp.surface(surf, data)
    return(res)
  }


  if(is.null(ellipse) & is.null(facet) & !center.dist & !density) {
    warning("nothing to do.")
    return(x)
  }
  # check if shifted features are present
  shifted <- any(grepl("Shifted_X" ,getFeatureNames(x)))
  image.dimensions1 <- c(1392, 1040)
  image.center1     <- image.dimensions1 / 2
  if(x$image.total == 9) {
    image.dimensions2 <- c((1392 * 3 + 20), (1040 * 3 + 20))
  } else if(x$image.total == 6) {
    image.dimensions2 <- c((1392 * 3 + 20), (1040 * 2 + 10))
  } else stop("can only deal with 6/9 image wells.")
  image.center2     <- image.dimensions2 / 2
  if(!is.null(ellipse)) {
    ellipse <- as.integer(ellipse)
    if(ellipse < 1 | ellipse > 20) stop("expecting ellipse to be in 1:20")
    if(ellipse != 1) {
      rect1 <- image.dimensions1[1] * image.dimensions1[2]
      step1 <- 1:(ellipse - 1) * rect1 / ellipse
      rect2 <- image.dimensions2[1] * image.dimensions2[2]
      step2 <- 1:(ellipse - 1) * rect2 / ellipse
      message("ellipse sizes: ", paste(step1, collapse=", "),
              " (within images)")
      if(shifted) {
        message("  and: ", paste(step2, collapse=", "), " (within wells)")
      }
      elli1 <- sapply(step1, function(x) {
        b <- sqrt(x / pi * image.dimensions1[2] / image.dimensions1[1])
        a <- image.dimensions1[1] * b / image.dimensions1[2]
        return(c(a, b))
      })
      elli2 <- sapply(step2, function(x) {
        b <- sqrt(x / pi * image.dimensions2[2] / image.dimensions2[1])
        a <- image.dimensions2[1] * b / image.dimensions2[2]
        return(c(a, b))
      })
    } else {
      elli1 <- image.center1 - 100
      elli2 <- image.center2 - 200
      if(shifted) {
        message("using a single ellipse, 100px (within images) and \n200px ",
                "(within wells) dist from borders.")
      } else {
        message("using a single ellipse, 100px dist from borders.")
      }
    }
    x$data.mat <- lapply(x$data.mat, function(group) {
      if(!is.null(group)) {
        index1.x <- grep("Location_Center_X", colnames(group))
        index1.y <- grep("Location_Center_Y", colnames(group))
        index2.x <- grep("Location_Shifted_X", colnames(group))
        index2.y <- grep("Location_Shifted_Y", colnames(group))
        if(length(index1.x) != length(index1.y)) {
          stop("expecting equal number of center features for x & y")
        }
        if(length(index2.x) != length(index2.y)) {
          stop("expecting equal number of shifted features for x & y")
        }

        length.original <- ncol(group)
        length.center   <- length(index1.x)
        length.shifted  <- length(index2.x)
        if((length.center > 0 | length.shifted > 0) & nrow(group) == 0) {
          # in case no rows are present, add features to colnames anyway
          if(length.center > 0 & length.shifted > 0) {
            nmes <- c(
              colnames(group),
              gsub("Center_X$", "In_Ellipse_Image", colnames(group)[index1.x]),
              gsub("Shifted_X$", "In_Ellipse_Well", colnames(group)[index2.x]))
            dims <- c(0, length.original + length.center + length.shifted)
          } else if(length.center > 0) {
            nmes <- c(colnames(group), gsub("Center_X$", "In_Ellipse_Image",
                                            colnames(group)[index1.x]))
            dims <- c(0, length.original + length.center)
          } else if(length.shifted > 0) {
            nmes <- c(colnames(group), gsub("Shifted_X$", "In_Ellipse_Well",
                                            colnames(group)[index2.x]))
            dims <- c(0, length.original + length.shifted)
          }
          dim(group)      <- dims
          colnames(group) <- nmes
          return(group)
        } else if((length.center > 0 | length.shifted > 0) & nrow(group) > 0) {
          if(length.center > 0) {
            # center features
            feat1.x <- group[,index1.x, drop=FALSE]
            feat1.y <- group[,index1.y, drop=FALSE]
            if (ellipse == 1) {
              # only one ellipse
              res1.ell <- sapply(1:ncol(feat1.x), singleEllipse, feat1.x,
                                 feat1.y, image.center1, elli1)
            } else {
              # multiple ellipses
              res1.ell <- sapply(1:ncol(feat1.x), multipleEllipses, feat1.x,
                                 feat1.y, image.center1, ellipse, elli1)
            }
            dim(res1.ell) <- dim(feat1.x)
          } else res1.ell <- NULL
          if (length.shifted > 0) {
            # shifted features
            feat2.x <- group[,index2.x, drop=FALSE]
            feat2.y <- group[,index2.y, drop=FALSE]
            if (ellipse == 1) {
              # only one ellipse
              res2.ell <- sapply(1:ncol(feat2.x), singleEllipse, feat2.x,
                                 feat2.y, image.center2, elli2)
            } else {
              # multiple ellipses
              res2.ell <- sapply(1:ncol(feat2.x), multipleEllipses, feat2.x,
                                 feat2.y, image.center2, ellipse, elli2)
            }
            dim(res2.ell) <- dim(feat2.x)
          } else res2.ell <- NULL

          if(!is.null(res1.ell) & !is.null(res2.ell)) {
            res <- cbind(group, res1.ell, res2.ell)
            range1 <- (length.original + 1):(length.original + length.center)
            range2 <- (length.original + length.center + 1):(length.original +
                       length.center + length.shifted)
            colnames(res)[range1] <- gsub("Center_X$", "In_Ellipse_Image",
                                          colnames(group)[index1.x])
            colnames(res)[range2] <- gsub("Shifted_X$", "In_Ellipse_Well",
                                          colnames(group)[index2.x])
          } else if (!is.null(res1.ell)) {
            res <- cbind(group, res1.ell)
            range1 <- (length.original + 1):(length.original + length.center)
            colnames(res)[range1] <- gsub("Center_X$", "In_Ellipse_Image",
                                          colnames(group)[index1.x])
          } else if (!is.null(res2.ell)) {
            res <- cbind(group, res2.ell)
            range2 <- (length.original + length.center + 1):(length.original +
                       length.center + length.shifted)
            colnames(res)[range2] <- gsub("Shifted_X$", "In_Ellipse_Well",
                                          colnames(group)[index2.x])
          } else stop("?!?")
          return(res)
        } else {
          return(group)
        }
      } else return(NULL)
    })
  }
  if(!is.null(facet)) {
    facet <- as.integer(facet)
    if(!(is.vector(facet, mode="integer") & length(facet) == 2)) {
      stop("expecting an integer vector of length 2 for facet.")
    }
    facet.size <- image.dimensions1 / facet
    message("facet size: ", round(facet.size[1]), " (x), ",
            round(facet.size[2]), " (y)")
    x$data.mat <- lapply(x$data.mat, function(group) {
      if(!is.null(group)) {
        index.x <- grep("Location_Center_X", colnames(group))
        index.y <- grep("Location_Center_Y", colnames(group))
        if(length(index.x) != length(index.y)) {
          stop("expecting equal number of center features for x & y")
        }
        length.original <- ncol(group)
        length.new      <- length(index.x)
        if(length.new > 0 & nrow(group) == 0) {
          # in case no rows are present, add features to colnames anyway
          if(shifted) {
            nmes <- c(
              colnames(group),
              gsub("Center_X$", "Facet_X_Image", colnames(group)[index.x]),
              gsub("Center_Y$", "Facet_Y_Image", colnames(group)[index.y]),
              gsub("Center_X$", "Facet_X_Well", colnames(group)[index.x]),
              gsub("Center_Y$", "Facet_Y_Well", colnames(group)[index.y]),
              gsub("Center_X$", "Facet_Type", colnames(group)[index.x]),
              gsub("Center_X$", "Facet_Border", colnames(group)[index.x]))
            dims <- c(0, length.original + 6 * length.new)
          } else {
            nmes <- c(
              colnames(group),
              gsub("Center_X$", "Facet_X_Image", colnames(group)[index.x]),
              gsub("Center_Y$", "Facet_Y_Image", colnames(group)[index.y]),
              gsub("Center_X$", "Facet_Type", colnames(group)[index.x]),
              gsub("Center_X$", "Facet_Border", colnames(group)[index.x]))
            dims <- c(0, length.original + 4 * length.new)
          }
          dim(group)      <- dims
          colnames(group) <- nmes
          return(group)
        } else if(length.new > 0 & nrow(group) > 0) {
          feat.x <- group[,index.x, drop=FALSE]
          feat.y <- group[,index.y, drop=FALSE]
          facet.x <- sapply(1:ncol(feat.x), facetCalc, feat.x, facet.size[1])
          facet.y <- sapply(1:ncol(feat.y), facetCalc, feat.y, facet.size[2])
          dim(facet.x) <- dim(feat.x)
          dim(facet.y) <- dim(feat.y)
          facet.type <- sapply(1:ncol(feat.x), facetType, facet.x, facet.y,
                               facet, x$image.total, x$image.index)
          dim(facet.type) <- dim(feat.x)
          facet.border <- sapply(1:ncol(feat.x), facetBorder, facet.x, facet.y,
                                facet)
          dim(facet.border) <- dim(feat.x)
          res.fac <- cbind(facet.x, facet.y, facet.type, facet.border)
          colnames(res.fac) <- c(
            gsub("Center_X$", "Facet_X_Image", colnames(group)[index.x]),
            gsub("Center_Y$", "Facet_Y_Image", colnames(group)[index.y]),
            gsub("Center_X$", "Facet_Type", colnames(group)[index.x]),
            gsub("Center_X$", "Facet_Border", colnames(group)[index.x]))
          if(shifted) {
            shifted.x <- facet.x + (x$image.col - 1) * facet[1]
            shifted.y <- facet.y + (x$image.total / 3 - x$image.row) * facet[2]
            res.fac <- cbind(facet.x, facet.y, shifted.x, shifted.y,
                             facet.type, facet.border)
            colnames(res.fac) <- c(
              gsub("Center_X$", "Facet_X_Image", colnames(group)[index.x]),
              gsub("Center_Y$", "Facet_Y_Image", colnames(group)[index.y]),
              gsub("Center_X$", "Facet_X_Well", colnames(group)[index.x]),
              gsub("Center_Y$", "Facet_Y_Well", colnames(group)[index.y]),
              gsub("Center_X$", "Facet_Type", colnames(group)[index.x]),
              gsub("Center_X$", "Facet_Border", colnames(group)[index.x]))
          }
          return(cbind(group, res.fac))
        } else {
          return(group)
        }
      } else return(NULL)
    })
  }
  if(center.dist) {
    message("including distance to image center.")
    x$data.mat <- lapply(x$data.mat, function(group) {
      if(!is.null(group)) {
        index1.x <- grep("Location_Center_X", colnames(group))
        index1.y <- grep("Location_Center_Y", colnames(group))
        index2.x <- grep("Location_Shifted_X", colnames(group))
        index2.y <- grep("Location_Shifted_Y", colnames(group))
        if(length(index1.x) != length(index1.y)) {
          stop("expecting equal number of center features for x & y")
        }
        if(length(index2.x) != length(index2.y)) {
          stop("expecting equal number of shifted features for x & y")
        }

        length.original <- ncol(group)
        length.center   <- length(index1.x)
        length.shifted  <- length(index2.x)
        if((length.center > 0 | length.shifted > 0) & nrow(group) == 0) {
          # in case no rows are present, add features to colnames anyway
          if(length.center > 0 & length.shifted > 0) {
            nmes <- c(colnames(group),
                      gsub("Center_X$", "Dist_Center_Image",
                           colnames(group)[index1.x]),
                      gsub("Shifted_X$", "Dist_Center_Well",
                           colnames(group)[index2.x]))
            dims <- c(0, length.original + length.center + length.shifted)
          } else if(length.center > 0) {
            nmes <- c(colnames(group),
                      gsub("Center_X$", "Dist_Center_Image",
                           colnames(group)[index1.x]))
            dims <- c(0, length.original + length.center)
          } else if(length.shifted > 0) {
            nmes <- c(colnames(group),
                      gsub("Shifted_X$", "Dist_Center_Well",
                           colnames(group)[index2.x]))
            dims <- c(0, length.original + length.shifted)
          }
          dim(group)      <- dims
          colnames(group) <- nmes
          return(group)
        } else if((length.center > 0 | length.shifted > 0) & nrow(group) > 0) {
          if(length.center > 0) {
            feat1.x <- group[,index1.x, drop=FALSE]
            feat1.y <- group[,index1.y, drop=FALSE]
            dist1 <- sapply(1:ncol(feat1.x), distCalc, feat1.x, feat1.y,
                            image.center1)
            dim(dist1) <- dim(feat1.x)
          } else dist1 <- NULL
          if (length.shifted > 0) {
            feat2.x <- group[,index2.x, drop=FALSE]
            feat2.y <- group[,index2.y, drop=FALSE]
            dist2 <- sapply(1:ncol(feat2.x), distCalc, feat2.x, feat2.y,
                            image.center2)
            dim(dist2) <- dim(feat2.x)
          } else dist2 <- NULL
          if(!is.null(dist1) & !is.null(dist2)) {
            res <- cbind(group, dist1, dist2)
            range1 <- (length.original + 1):(length.original + length.center)
            range2 <- (length.original + length.center + 1):(length.original
              + length.center + length.shifted)
            colnames(res)[range1] <- gsub("Center_X$", "Dist_Center_Image",
                                         colnames(group)[index1.x])
            colnames(res)[range2] <- gsub("Shifted_X$", "Dist_Center_Well",
                                         colnames(group)[index2.x])
          } else if(!is.null(dist1)) {
            res <- cbind(group, dist1)
            range1 <- (length.original + 1):(length.original + length.center)
            colnames(res)[range1] <- gsub("Center_X$", "Dist_Center_Image",
                                         colnames(group)[index1.x])
          } else if(!is.null(dist2)) {
            res <- cbind(group, dist2)
            range2 <- (length.original + length.center + 1):(length.original
              + length.center + length.shifted)
            colnames(res)[range2] <- gsub("Shifted_X$", "Dist_Center_Well",
                                         colnames(group)[index2.x])
          } else stop("?!?")
          return(res)
        } else {
          return(group)
        }
      } else return(NULL)
    })
  }
  if(density) {
    message("calculating densities.")
    x$data.mat <- lapply(x$data.mat, function(group) {
      if(!is.null(group)) {
        index.x <- grep("Location_Center_X", colnames(group))
        index.y <- grep("Location_Center_Y", colnames(group))
        if(length(index.x) != length(index.y)) {
          stop("expecting equal number of center features for x & y")
        }

        length.original <- ncol(group)
        length.center   <- length(index.x)
        if(length.center > 0 & nrow(group) == 0) {
          # in case no rows are present, add features to colnames anyway
          nmes <- c(colnames(group),
                    gsub("Center_X$", "Kern_Dens_Image",
                         colnames(group)[index.x]))
          dims <- c(0, length.original + length.center)
          dim(group)      <- dims
          colnames(group) <- nmes
          return(group)
        } else if(length.center > 0 & nrow(group) > 0) {
          feat.x <- group[,index.x, drop=FALSE]
          feat.y <- group[,index.y, drop=FALSE]
          dens <- sapply(1:ncol(feat.x), densCalc, feat.x, feat.y)
          dim(dens) <- dim(feat.x)
          res <- cbind(group, dens)
          range <- (length.original + 1):(length.original + length.center)
          colnames(res)[range] <- gsub("Center_X$", "Kern_Dens_Image",
                                       colnames(group)[index.x])
          return(res)
        } else {
          return(group)
        }
      } else return(NULL)
    })

  }
  return(x)
}

#' @export
augmentCordinateFeatures.default <- function(x, ...) {
  stop("can only deal with Data (ImageData/WellData/PlateData) objects.")
}
nbenn/singleCellFeatures documentation built on May 23, 2019, 12:24 p.m.