
Build a Bonsai tree over the cells
bonsai_sc.RdBonsai reconstructs a tree over the cells in which every cell is a leaf and the internal nodes are inferred ancestral states, with branch lengths that carry the amount of change between them. Unlike a kNN graph it uses each measurement's error bar, which is what Sanity provides: the raw counts go through Sanity first, for posterior log fold changes with error bars, and Bonsai builds the tree on those. The tree is then laid out in 2D. For details, please refer to de Groot, et al. and Breda, et al.
No HVG selection needed. By default every gene goes in, streamed through
Sanity in chunks, and only the genes with enough signal over their own noise
(min_signal_to_noise in params_sc_bonsai()) are kept for the
tree. That is the gene selection of the Bonsai paper, and it keeps memory at
one chunk plus the survivors. Pass hvg to restrict the candidates.
Runtime grows a little faster than linearly with the number of cells. In bonsai-rs's own benchmarks the search took about 70 seconds at 10,000 cells and 210 seconds at 25,000 on ten cores. Sanity comes on top, linear in the number of genes it has to fit; on the CPU that is the larger share once all genes go in.
The object itself is not touched. Store the leaf coordinates with
set_bonsai_embedding() if you want them next to the other
embeddings.
On MetaCells every metacell is a leaf. Their raw counts are sums over
their cells, and a sum of Poisson counts is Poisson, so Sanity treats a
metacell exactly as it treats a cell: its total counts are the library size,
and a bigger metacell gets tighter error bars, which Bonsai weights by. That
is the way to large data: 100k cells in metacells of 50 is a 2,000-leaf tree.
What you give up is any structure inside a metacell.
Usage
bonsai_sc(
object,
hvg = NULL,
bonsai_params = params_sc_bonsai(),
.verbose = TRUE
)Arguments
- object
SingleCellsorMetaCellsclass.- hvg
Optional integer. Restrict the candidate genes to these, e.g. the output of
get_hvg()plus one. Please provide 1-indexed genes here! IfNULL, every gene in the object is a candidate.- bonsai_params
List. See
params_sc_bonsai().- .verbose
Boolean or integer. Controls verbosity and returns run times.
FALSE-> quiet,TRUEor1L-> normal verbosity,2L-> detailed verbosity.
Value
A BonsaiTree S3 object with:
nodes - data.table with
node,parent(NAfor the root),branch,is_leaf,cell_id(NAfor the inferred ancestors),n_cells(the cells behind a leaf: 1 for single cells, the originating cells for a metacell;NAfor the ancestors),xandy. The leaves come first, in the order of the object's cells or metacells.loglik - The loglikelihood of the final tree.
steps - data.table with the loglikelihood after each search step and the step's wall time in seconds.
timings - data.table with the wall time in seconds of each stage:
sanity,ingest,bonsai(the whole search),layout, andtotal, the whole call as R saw it.genes_used - The genes the tree was built on.
genes_dropped - The candidate genes left out: no counts in the cells, ill-conditioned Sanity posteriors, or a signal-to-noise ratio below
min_signal_to_noise.cell_idx - The cells or metacells the tree was built over (0-indexed).
layout, hyperbolic - The current layout.
params - The parameters of the run.
Examples
# a tree over the demo cells, genes selected by their signal-to-noise
sc <- demo_single_cells(
prepped = FALSE,
syn_data_params = params_sc_synthetic_data(n_cells = 200L, n_genes = 50L)
)
tree <- bonsai_sc(sc, .verbose = FALSE)
tree
#> BonsaiTree: 200 leaves, 198 inferred ancestors
#> Genes: 48 used, 2 dropped
#> Loglikelihood: -2277.2
#> Layout: equal_angle
#> Seconds: sanity 0.1 | ingest 0.0 | bonsai 0.2 | layout 0.0 | total 0.3
unlink(sc@dir_data, recursive = TRUE, force = TRUE)