Pull everything back: highlights, labels and scores (Seurat, SingleCellExperiment)#

Open In Colab

Whatever you make in the viewer — a lasso, a label field, a gene signature score, a gene set — comes back onto your object in one call, cellucid_pull(object, viewer): columns of a Seurat object’s meta.data or a SingleCellExperiment’s colData, and the gene sets in misc$cellucid / metadata(x)$cellucid. R copies on change, so assign the result.

Time: 10 minutes. The same tutorial in Python: Pull everything back.

# A fresh R library (Google Colab's R runtime, a new machine) installs the packages once.
for (package in c("remotes", "SeuratObject")) {
  if (!requireNamespace(package, quietly = TRUE)) install.packages(package)
}
if (!requireNamespace("cellucid", quietly = TRUE)) {
  if ("cellucid" %in% rownames(available.packages())) install.packages("cellucid") else remotes::install_github("theislab/cellucid-r")
}

The data#

SeuratObject’s own example, pbmc_small: 80 blood cells, 230 genes, a t-SNE and the clusters RNA_snn_res.1. Use your own Seurat or SingleCellExperiment object in its place.

library(cellucid)
library(SeuratObject)
data("pbmc_small")
seu <- pbmc_small
seu
viewer <- cellucid_view(seu, dataset_id = "pbmc-small", dataset_name = "PBMC small")

Where the viewer appears:

Where you run R

The viewer

a Jupyter notebook (JupyterLab, Notebook 7, VS Code, Google Colab; IRkernel)

in the cell’s output, once the cell finishes (a notebook widget over the kernel’s own connection: no port, no server)

RStudio, Positron

the Viewer pane

any other R console

a browser tab

In a notebook, R hears the viewer between cells: run what reads the viewer’s work (cellucid_selection(), cellucid_pull()) in a later cell than the one that showed it.

Work in the viewer#

  1. A lasso. In Highlighting choose Lasso, drag around a group of cells and click Confirm.

  2. A label field. In the field list, Copy groups, rename the copy my_labels and, in its legend, rename a category (the pencil) or drag one onto another to merge them.

  3. A score. In Analysis › Gene signature, enter MS4A1, CD79A, CD79B and run it.

Then run the next cell.

for (result in cellucid_results(viewer)) {
  name <- c(result$meta$label, result$meta$key, result$meta$name, "")[[1]]
  cat(sprintf("%-12s %-28s %s\n", result$kind, result$id, name))
}

cellucid_results() is what the viewer has sent; it stops with a message only before the viewer has sent it once (when the dataset opens): run the cell again then.

One call#

pulled <- cellucid_pull(seu, viewer, return_summary = TRUE)
seu <- pulled$data
names(pulled$summary$columns)

Result

Column

Type

a highlight group

cellucid_highlight__<group id>

logical

a label field

its name (my_labels)

factor, the viewer’s categories as levels

a score, a continuous field

its name (<set> score)

numeric

a gene set

—

seu@misc$cellucid$gene_sets

The same names as Python’s viewer.pull(adata). A field pushed from R (cellucid_push()) comes back only with include_pushed = TRUE.

written <- names(pulled$summary$columns)
head(seu[[]][, written, drop = FALSE])
lasso <- grep("^cellucid_highlight__", written, value = TRUE)
for (column in lasso) print(table(seu$groups, seu[[column]][, 1]))

Again and again#

Pull again after more work: the columns an earlier pull wrote are replaced, and those whose result you deleted are removed (summary$removed). A column of the same name that Cellucid did not write is a conflict: on_conflict = "error" (the default) stops, "replace" overwrites, "suffix" writes <name>_2 beside it.

pulled <- cellucid_pull(seu, viewer, return_summary = TRUE)
seu <- pulled$data
pulled$summary$removed

The cells themselves#

cellucid_selection(viewer) is the last selection ($cell_names, $cells); cellucid_subset(object, viewer, which) gives the cells of a highlight group (by id or label), of the last selection (which = NULL) or the visible cells ("visible") as a subset of the object.

groups <- Filter(function(result) identical(result$kind, "highlight"), cellucid_results(viewer))
vapply(groups, function(result) result$meta$label, "")
picked <- cellucid_subset(seu, viewer, groups[[1]]$id)
picked
cellucid_stop(viewer)

A SingleCellExperiment#

The same calls, with colData and metadata(). The object is built here from pbmc_small; use your own.

library(SingleCellExperiment)
sce <- SingleCellExperiment(
  assays = list(counts = LayerData(pbmc_small, layer = "counts")),
  colData = pbmc_small[[]],
  reducedDims = list(TSNE = Embeddings(pbmc_small, "tsne"))
)
sce_viewer <- cellucid_view(sce, dataset_id = "pbmc-small-sce", dataset_name = "PBMC small (SCE)")

Lasso some cells and Confirm, then:

sce <- cellucid_pull(sce, sce_viewer)
colData(sce)[, grep("^cellucid_highlight__", colnames(colData(sce))), drop = FALSE]
cellucid_stop(sce_viewer)

Next#