Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

HTO demultiplexing

Cell hashing labels cells from each sample with a distinct oligonucleotide tag before the samples are pooled. Depending on the protocol, tags are attached through antibodies or lipids. Demultiplexing uses hashtag oligo (HTO) counts to recover sample assignments: a singlet has one positive tag, a negative has none, and a doublet has more than one.

Pooling lets samples share a capture, but an incorrect assignment can mix their biological signals. Inspect the assignments before comparing samples. This is separate from integrating RNA and protein measurements in Read RNA and protein together with CITE-seq.

Download the Cell Hashing example

We use the eight-donor PBMC experiment from Stoeckius et al. (2018), available as GSE108313. Each donor has one of eight tags, BatchA through BatchH. The experiment also includes untagged HEK293T and mouse NIH3T3 cells. We retain those controls here, so some negative assignments are expected.

The two downloads total about 34 MB. The HTO file supplies the tag counts; the RNA file lets us select barcodes with RNA evidence before demultiplexing. We import only the small HTO matrix into CyteArc. An HTO assay can also share a datastore with RNA, ADT, or ATAC assays when their cell barcodes are aligned.

The example uses a temporary directory. Use a project directory instead if you want to keep the downloaded files and Zarr store after closing the notebook.

Started: 2026-10-11T21:10:26.836097Z | Wall time: 0.557 s

hto 1.07 rna 32.73 Name: Downloaded MB, dtype: float64

Started: 2026-10-11T21:10:27.395176Z | Wall time: 9.040 s

Read the eight hashtag channels

The HTO CSV has tags along rows and barcodes along columns. Three rows, bad_struct, no_match, and total_reads, describe read processing rather than hashtags. Remove those before importing. For readable plots, shorten each tag identifier to its BatchA through BatchH prefix; the suffix is its oligonucleotide sequence.

BatchABatchBBatchCBatchDBatchEBatchFBatchGBatchH
barcode
GGCGACTAGAGGACGG30162626988155532
CATCAAGGTCTTGTCC43902224472117
AAACCTGAGTGATCGG12151923212763
TGAGGGAGTACTTAGC262013246757632
CCTAAAGAGATGTGGC741224175519825

Started: 2026-10-11T21:10:36.436754Z | Wall time: 1.864 s

Choose barcodes using RNA counts

HTO signal alone does not establish that a droplet contains a cell. We keep barcodes present in both files with at least 200 RNA UMIs, following the study’s initial RNA threshold. This is a teaching selection, not a reproduction of every filtering step in the paper. In particular, we do not remove the untagged control cell lines.

The RNA table has 40,899 genes and 50,000 barcodes and expands to about 4 GB. We only need one total per barcode, so read and sum one gene at a time. This step can take about a minute.

Barcodes in the HTO file 65000 Barcodes in both files 39842 Shared barcodes with at least 200 RNA UMIs 21522 Name: Barcodes, dtype: int64

Started: 2026-10-11T21:10:38.302154Z | Wall time: 32.811 s

Import the HTO assay

Declare the assay as type HTO. The store contains eight features, so min_features_per_cell=-1 keeps the selected barcodes without applying the usual first-open feature-count floor. RNA totals are retained as cell metadata; the RNA matrix is not copied.

This cell creates a new store. Rerun the notebook from the beginning to use a fresh temporary directory, or choose another output path when repeating the import.

DataStore has 21522 (21522) cells with 1 assays: HTO Cell metadata: 'I', 'ids', 'names', 'HTO_nCounts', 'HTO_nFeatures', 'RNA_nCounts' HTO assay has 8 features and following metadata: 'I', 'ids', 'names', 'dropOuts', 'nCells'

Started: 2026-10-11T21:11:11.114597Z | Wall time: 1.481 s

Assign singlets, doublets, and negatives

CyteArc follows the general HTOdemux strategy. It normalizes each tag with CLR, uses K-means to form one more cluster than the number of tags, and chooses each tag’s lowest-count cluster as its background. Counts above the fitted negative-binomial distribution’s 99th percentile are positive. This differs from Seurat’s default clustering, so the assignments need not match Seurat’s results.

qc.hto_demultiplexing saves an immutable identity artifact and leaves cell metadata unchanged. A singlet receives its strongest normalized tag’s identifier. Negative means no positive tags, and Doublet means at least two; the latter can also include higher-order multiplets.

BarcodesPercent
HTO identity
Singlet1632275.8
Doublet320314.9
Negative19979.3

Started: 2026-10-11T21:11:12.597312Z | Wall time: 0.853 s

This run assigns 16,322 singlets, 3,203 doublets, and 1,997 negatives. These are classifications for the selection above, not independently validated identities or an estimate of the loading rate. Negative calls can include the untagged controls as well as cells with weak tag signal. A negative label alone does not tell us which explanation applies to a particular barcode.

Barcodes
HTO identity
BatchA2193
BatchB2281
BatchC2141
BatchD1943
BatchE1764
BatchF1791
BatchG2007
BatchH2202
Doublet3203
Negative1997

Started: 2026-10-11T21:11:13.451191Z | Wall time: 0.010 s

Inspect the tag signal

The heatmap shows mean CLR-normalized HTO counts for each assigned group. Singlets should be enriched for their assigned tag. Doublets combine different tag pairs, so their group average can show several tags even though an individual doublet need not carry all eight. The plot summarizes the same measurements used for assignment; it is a diagnostic, not an independent validation.

Heatmap of mean CLR HTO counts for eight tags across assigned groups. Singlet groups have strong diagonal tag signals; the doublet group averages signal across tags.

Started: 2026-10-11T21:11:13.461739Z | Wall time: 0.219 s

Group averages can hide ambiguous cells. Compare the full BatchA and BatchB distributions below. An assigned singlet group can still contain low background counts for other tags; a nonzero count is not automatically a positive tag call.

Violin plots of BatchA and BatchB CLR HTO counts across assigned groups. Each tag is strongest in its matching singlet group, with broad doublet distributions and lower background elsewhere.

Started: 2026-10-11T21:11:13.682039Z | Wall time: 0.521 s

Keep an explicit singlet selection

Select the eight tag identifiers to retain singlets. The resulting artifact records the selection without deleting negative or doublet rows. In a datastore with matching RNA or other assays, pass it as cell_selection= to downstream analyses.

Selected singlets 16322 Barcodes retained in the store 21522 Name: Barcodes, dtype: int64

Started: 2026-10-11T21:11:14.205044Z | Wall time: 0.040 s

Common mistakes and limitations

  • Feeding sequencing-summary rows or normalized values into demultiplexing changes the input. Use only the raw hashtag channels and check that barcodes match across assays.

  • Treating the labels as ground truth: background and weak staining affect assignments. Inspect tag distributions, and do not relabel negatives or doublets as a donor without further evidence.

  • Assuming HTO singlets cannot be multiplets: two cells with the same tag can escape detection. HTO demultiplexing does not replace RNA quality control or RNA doublet scoring; see Quality control across assays.

The DataStore API reference documents the current demultiplexing signature.

References
  1. Stoeckius, M., Zheng, S., Houck-Loomis, B., Hao, S., Yeung, B. Z., Mauck, W. M., Smibert, P., & Satija, R. (2018). Cell Hashing with barcoded antibodies enables multiplexing and doublet detection for single cell genomics. Genome Biology, 19(1). 10.1186/s13059-018-1603-1