Update to 0.2.0
[loomr.git] / man / loomR-package.Rd
1 % Generated by roxygen2: do not edit by hand
2 % Please edit documentation in R/package.R
3 \docType{package}
4 \name{loomR-package}
5 \alias{loomR-package}
6 \title{An R interface for loom files}
7 \description{
8 loomR provides an interface for working with loom files in a loom-specific way.
9 We provide routines for validating loom files,
10 iterating with chunks through data within the loom file,
11 and provide a platform for other packages to build support for loom files.
12 Unlike other HDF5 pacakges, loomR actively protectes a loom file's structure, enabling the
13 user to focus on their analysis and not worry about the integrity of their data.
14 }
15 \section{Semantics}{
16
17 Throughout all loomR-related documentation and writing, the following styles for distinguising between loom files,
18 \code{loom} objects, and loomR will and be used. When talking about loom files, or the actual HDF5 file on disk,
19 the word 'loom' will be written in normal text. Capitalization will be done based on a language's rules for
20 capitalization in sentences. For English, that means if the word 'loom' appears at the beginning of a sentence
21 and is being used to refer to a loom file, it will be capilatized. Otherwise, it will be lowercase.
22 For \code{loom} objects, or the object within R, the word 'loom' will always be lowercase and written in monospaced text.
23 When referring to the pacakge loomR, it will always be written in normal text with the 'l', 'o's, and 'm' lowercased and
24 the 'R' uppercased. This style will be used throughout documentation for loomR as well as any vignettes and tutorials
25 produced by the authors.
26 }
27
28 \section{Loom Files}{
29
30 Loom files are an HDF5-based format for storing and interacting with large single-cell RNAseq datasets.
31 Each loom file has at least six parts to it:
32 the raw expression data (\code{matrix}),
33 groups for gene- and cell-metadata (\code{row_attrs} and \code{col_attrs}, respectively),
34 groups for gene-based and cell-based cluster graphs (\code{row_graphs} and \code{col_graphs}, respectively),
35 and \code{layers}, a group containing alternative representations of the data in \code{matrix}.
36 Each dataset within the loom file has rules as to what size it may be, creating a structure for the entire loom file and all the data within.
37 This structure is enforced to ensure that data remains intact and retriveable when spread across the various datasets in the loom file.
38
39 \describe{
40   \item{\code{matrix}}{
41     The dataset that sets the dimensions for most other datasets within a loom file. This dataset has 'n' genes and 'm' cells.
42     Due to the way that loomR presents data, this will appear as 'm' rows and 'n' columns. However, other HDF5 libraries will
43     generally present the data as 'n' rows and 'm' columns
44   }
45   \item{\code{row_attrs} and \code{col_attrs}}{
46     These are one- or two-dimensional datasets where a specific dimension is of length 'n', for row attributes, or 'm', for column attributes.
47     Within loomR, this must be the second dimension of two-dimensional datasets, or the length of one-dimensional datasets Most other
48     HDF5 libraries will show this specific dimension as the first dimension for two-dimensional datasets, or the length of one-dimensional
49     datasets.
50   }
51   \item{\code{row_graphs} and \code{col_graphs}}{
52     Unlike other datasets within a loom file, these are not controlled by \code{matrix}. Instead, within these groups are groups for
53     specific graphs. Each graph group will have three datasets that represent the graph in
54     \href{https://en.wikipedia.org/wiki/Sparse_matrix#Coordinate_list_(COO)}{coordinate format}: \code{a} for row indices, \code{b} for
55     column indices, and \code{w} for values. Each dataset within a graph must be one-dimensional and all datasets within a graph must be
56     the same length. Not all graphs must be the same length as each other.
57   }
58   \item{\code{layers}}{Each dataset within \code{layers} must have the exact same dimensions as \code{matrix}}
59 }
60 }
61
62 \section{Chunk-based iteration}{
63
64 As loom files can theoretically hold million-cell datasets, performing analysis on these datasets can be impossible due to the memory
65 requirements for holding such a dataset in memory. To combat this problem, \code{loom} objects offer native chunk-based iteration through
66 the \code{batch.scan}, \code{batch.next}, \code{map}, and \code{apply} methods. This section will cover the former two methods; the latter
67 two are covered in the \href{http://satijalab.org/loomR/loomR_tutorial.html}{loomR tutorial}.
68
69 \code{batch.scan} and \code{batch.next} are the heart of all chunk-based iteration in the \code{loom} object. These two methods make
70 use of \code{\link{itertools::ichunk}} object to chunk through the data in a loom file. Due to the way that R works, \code{batch.scan}
71 initializes the iterator and \code{batch.next} moves through the iterator.
72
73 The \code{batch.scan} method will break a dataset in the loom file into chunks, based on a chunk size given to it. \code{batch.scan} will
74 work on any dataset, except for two-dimensional attributes and any graph dataset. When iterating over \code{matrix} and the layers, the \code{MARGIN}
75 argument tells the \code{loom} object which way to chunk the data. A \code{MARGIN} of 1 will chunk over genes while a \code{MARGIN} of 2 will chunk
76 over cells. For one-dimmensional attributes, \code{MARGIN} is ignored. \code{batch.scan} returns an integer whose length is the number of iterations
77 it takes to iterate over the dataset selected.
78
79 Pulling data in chunks is done by \code{batch.next}. This method simply returns the next chunk of data. If \code{return.data = FALSE} is passed,
80 \code{batch.next} will instead return the indices of the next chunk. When using these methods, we recommend storing the results of \code{batch.scan}
81 and iterating through this vector to keep track of where the \code{loom} object is in the iteration.
82 \preformatted{
83   # Set up the iterator on the `loom` object lfile
84   batch <- lfile$batch.scan(dataset.use = 'matrix', MARGIN = 2)
85   # Iterate through the dataset, pulling data
86   # If `return.data = FALSE` is passed, the indices
87   # of the next chunk will be returned instead
88   for (i in batch) {
89     data.use <- lfile$batch.next()
90   }
91 }
92 }
93
94 \section{Extending loomR}{
95
96 The \code{loom} class is the heart of loomR. This class is written in the
97 \href{https://cran.r-project.org/web/packages/R6/vignettes/Introduction.html}{R6} object style and can be extended in three ways.
98 For each of the following, one be discretionary when \code{return} is used instead of \code{\link{invisible}}. As \code{loom} object are merely
99 handles to loom files, any function or method that modifies the file should not need to return anything. However, we recommend always returning
100 the \code{loom} object invisibly, using \code{\link{invisible}}. While not necessary for functionality, it means that objects in a user's environment
101 won't get overwritten if they try to reassign their \code{loom} object to the output of a function. For functions and methods that don't modify the
102 loom file, and instead return data, then the \code{return} function should be used.
103
104 The first way to extend \code{loom} objects is by subclassing the object and making a new R6 class. This allows new classes to
105 declare custom R6 methods and gain access to all of the \code{loom} object's methods, including S3- and S4-style methods.
106 New classes can also overwrite any methods for \code{loom} objects, allowing the extender to change the core behaviour of \code{loom} objects.
107 While this option allows the greatest control and access to the \code{loom} object, it involves the greatest amount of work
108 as one would need to write a new R6 class and all the associated boilerplate code. As such, we recommend subclassing \code{loom} objects
109 when a new class is needed, but would advise developers to use the other methods of extending \code{loom} objects for simpler tasks.
110
111 The second way is by using S4-style methods can be written for \code{loom} objects. loomR exports the \code{loom} class as an S4 class, allowing
112 one to write highly-specialized methods that enforce class-specificity and can change behaviour based on the classes of other objects provided to
113 a function. S4 methods look like normal functions to the end user, but can do different things based on the class, or classes, of objects passed to it.
114 This allows for highly-customized routines without cluttering a package's namespace, as only the generic function is exported. S4 methods can also be
115 written for generics exported by other packages, assuming the said generic has been imported before writing new methods. Furthermore, generics
116 and methods can be kept internally, and R will dispatch the appropriate method as if the generic was exported. However, S4 methods have the drawback
117 of not autocompleting arguments in the terminal or RStudio. This means that the user may need to keep documentation open while using these methods,
118 which detracts from the user-friendliness of these methods. Finally, while there is less boilerplate in declaring S4 generics and methods than
119 declaring R6 classes and methods, there is still more to write than our last method. As such, we recommend S4 methods for anyone who needs method
120 dispatch for internal functions only.
121 \preformatted{
122   #' @export SomeFunction
123   methods::setGeneric(
124     name = 'SomeFunction',
125     def = function(object, ...) {
126       return(standardGeneric(f = 'SomeFunction))
127     }
128   )
129
130   # Note, no extra Roxygen notes needed
131   methods::setMethod(
132     f = 'SomeFunction',
133     signature = c('object' = 'loom'),
134     definition = function(object, loom.param, ...) {
135       # do something
136     }
137   )
138 }
139
140 As R6 objects are based on S3 objects, the final way to extend \code{loom} objects is by writing S3-style methods. These methods involve the
141 least amount of boilerplate to set up. S3 generics are written just like normal functions, albiet with a few differences. Firstly, they have
142 two arguments: the argument that determines the class for dispatching and \code{...} to pass other arguments to methods. Finally, the only
143 thing an S3 generic needs to do is call \code{UseMethod} to allow R to dispatch based on the class of whatever the object is. Unlike S4 methods,
144 S3 methods provide tab-autocompletion for method-specific arguments, providing help messages along the way. This means that S3 methods are more
145 user-friendly than S4 methods. Like S4 methods, S3 methods can use S3 generics declared by other packages, with the same assumptions about
146 imports applying here as well. However, S3 methods cannot be kept internally, and must be exported for R to properly dispatch the method. This means
147 that a package's namespace will have n + 1 functions declared for every S3 generic, where n is the number of classes a method is declared for and the
148 one extra is for the generic. Furthermore, as the methods themselves are exported, anyone can simply use the method directly rather than go through
149 the generic and have R dispatch a method based on object class. Despite these drawbacks, S3 methods are how we recommend one extends loomR unless
150 one needs the specific features of R6 classes or S4-style methods.
151 \preformatted{
152   #' @export somefunction
153   somefunction <- function(object, ...) {
154     UseMethod('somefunction', object)
155   }
156
157   #' @export somefunction.loom
158   #' @method somefunction loom
159   somefunction.loom <- function(object, loom.param, ...) {
160     # do something
161   }
162 }
163 }
164