Skip to content

Code Guidelines

Paul Hoffman edited this page Aug 6, 2019 · 6 revisions

Code Guidelines

In order to ensure high-quality methods in SeuratWrappers, as well as to streamline the code review process, we have a few guidelines we ask developers to follow.

Code Placement and Structure

Each method and associated helper functions should be placed in a single .R file, including both exported and internal functions. This file should be placed in the R/ directory and named after the method (eg. fast_mnn.R). Developers should not modify the .R files of other methods, or the internal.R, the latter of which is maintained by the Satija Lab for helper functions that we believe would be useful. Bug fixes, however, are always welcome.

All functions should be documented using Roxygen syntax. Internal functions should omit the ' in the comment block (eg. # instead of #'). Please be sure to include @author, @references, and @seealso tags to ensure proper attribution and links back to original code.

We anticipate most code submitted to SeruatWrappers will be standalone functions. However, we welcome the addition of new generics and methods. New generics should have an accompanying Seurat and default (or whatever object the "default" method should run on), to allow further extension by other developers (for an example, see alra.R).

Methods for generics defined in imported packages are welcome. When adding methods for an imported generics, please first have general documentation that corresponds to nothing (NULL). For example, in conos.R, we create an empty as.Seurat documentation for all as.Seurat methods defined in SeuratWrappers. This dummy documentation inherits parameters from the as.Seurat generic, sets the Rdocumentation name to something general using the @rdname tag, and sets the name and alias to the name of the generic function for easy searching (?as.Seurat will pull up both the Seurat and SeuratWrappers help pages)

#' Extra conversions to Seurat objects
#'
#' @inheritParams Seurat::as.Seurat
#'
#' @rdname as.Seurat.extras
#' @name as.Seurat
#'
#' @seealso \code{\link[Seurat]{as.Seurat}}
#'
#' @aliases as.Seurat
#'
NULL

All methods in SeuratWrappers for the same generic should use the same Rdocumentation name. For example, in velocity.R, an as.Seurat method is defined for lists objects. In conos.R, another method for as.Seurat is defined, but for Conos objects. For both methods, the Rdocumentation name is as.Seurat.extras, so the documentation for all methods gets assembled together.

Seurat Object Data Access

When accessing data from a Seurat object, please use Seurat's accessor functions to pull the required data. For slots that don't have an accessor, please use the slot function. Use of the @ operator to access data is strongly discouraged.

For storing results into a Seurat object, please use the standard places for storing data. For example, expression data should be stored as an Assay object. Other places to store data include as a DimReduc object, a nearest-neighbor Graph, or object metadata. Data that doesn't correspond to one of these locations can be stored as a list in the tools slot by using Tool<-.

We encourage storing command call and parameters for each method. Storing command information can be accomplished with LogSeuratCommand, which will automatically pick up function name, parameters, and exact call string and store the information in the Seurat object properly. An example of using LogSeruatObject can be found below

MyFunction <- function(object, ...) {
  object <- LogSeuratCommand(object = object)
  return(object)
}

Dependent Packages

For the most part, we encourage developers to not add dependencies to SeuratWrappers; exceptions can be made on a case-by-case basis. When adding your method, please use CheckPackage to ensure that your dependent packages are installed and add them to the Suggests field in DESCRIPTION. As such, when calling a function from a non-imported, non-dependent package, please use the standard package::function syntax. Devlopers are welcome to use functions from imported packages, such as Seurat, so long as they're properly imported using the Roxygen @importFrom syntax.

Note: Please be sure to add new packages, including for vignettes, to the the DESCRIPTION file. For any packages hosted on GitHub, please ensure that you add the GitHub repository to the Remotes field; Bioconductor and CRAN packages do not need an entry in this field.

Provided Helper Functions

SeuratWrappers provides a number of internal helper functions that may come in handy. These functions are documented here:

%||%/Set If Null

Reimplemented from Hadley Wickham's answer on StackOverflow, %||% is a binary operator that returns the value of the right-hand side if the left-hand side is NULL

> x <- NULL
> y <- 5
> x %||% Y
[1] 5
> x <- 2
> x %||% y
[1] 2

%iff%/Set If Not Null

Inspired by a need for a reciprocal %||%, %iff% is a binary operator that returns the value of the right-hand side if the left-hand side is not NULL

> x <- 2
> y <- 5
> x %iff% y
[1] 5
> x <- NULL
> x %iff% y
[1] NULL

CheckPackage

CheckPackage will check to see if a package is installed and if not, attempt to install it. Installation attempts happen only when R is in interactive mode and only with user permission. Currently, CheckPackage can install from CRAN (or any CRAN-like repo set in user options), Bioconductor through BiocManager::install, or from GitHub through remotes::install_github.

There are two parameters for CheckPackage: package and repository

  • package is the name of the package to check and install. If a GitHub package, please pass the full user/repo name (this requires that the GitHub repository is the same name as the package)
  • repository is either cran, bioconductor, or github

IsMatrixEmpty

IsMatrixEmpty checks to see if a matrix, or S4 Matrix, has either no dimensionality (nrow and ncol are 0) or is a new matrix (nrow and ncol are 1, only value is NA). This covers cases where a matrix is generated from either new(Class = 'matrix') or matrix(), as either are valid for empty slots in Seurat Assay objects