Why SoupX separates the soup profile from contamination
A cell barcode can contain RNA molecules released from damaged or lysed cells in addition to RNA from the cell assigned to that barcode. This ambient material is often called the soup. SoupX estimates its gene composition and then estimates how much of each cell's observed library is attributable to that source. The two estimates answer different questions: the soup profile describes which genes are present in ambient RNA, while a cell's contamination fraction describes how much ambient RNA contributes to its observed counts.
The method is useful because ambient counts can make a gene appear expressed in a cell type where it is not actually expressed. Correction is not a direct observation of the cell's unobserved RNA, however. It is an estimate conditional on the soup profile, the contamination estimate, and assumptions about marker expression. A corrected count should therefore be interpreted as a model-based adjustment, not as a recovered measurement known without uncertainty.
Estimating the soup profile
SoupX estimates \(q_g\) from barcodes believed to contain ambient RNA but little or no intact-cell material. These are commonly called empty droplets. In a given sample, let \(e_g\) be the total number of observed molecules for gene \(g\) across the selected empty droplets. The pooled profile estimate is
This is a molecule-weighted estimate: a droplet contributing more counts has more influence on the profile. The estimated proportions sum to one, and a gene with \(\hat q_g=0\) is assigned no expected ambient contribution under this profile. In practice, the empty-droplet selection matters. Barcodes contaminated by intact cells can distort the profile, while an extremely small or shallow set of droplets can make the estimated composition unstable. The profile should be estimated separately for each sample or library when their ambient compositions may differ.
Worked Example: Calculating a Soup Profile
Suppose selected empty droplets have pooled counts of 120 for gene A, 80 for gene B, 50 for gene C, and 750 for all other genes combined. The total is \(120+80+50+750=1{,}000\) molecules.
For gene A, \(\hat q_A=120/1{,}000=0.12\). Similarly, \(\hat q_B=80/1{,}000=0.08\), \(\hat q_C=50/1{,}000=0.05\), and the remaining genes together have profile mass \(750/1{,}000=0.75\).
The values sum to \(0.12+0.08+0.05+0.75=1\), as required. Under this profile, 12% of ambient molecules are estimated to be gene A. This does not mean that 12% of every cell's counts are gene A; the cell's total contamination fraction is a separate quantity.
Estimating contamination from marker genes
The marker-based step uses a gene or set of genes believed to be absent from a particular cell type or cluster. If such a marker is observed in those cells, the method treats its counts as evidence of ambient contamination. This is a strong biological assumption: if the marker is truly expressed endogenously in some cells of the group, those endogenous counts will be mistakenly attributed to soup.
Let \(M\) be a set of marker genes assumed not to be expressed in the cells being used for estimation, and write \(\hat q_M=\sum_{g\in M}\hat q_g\) for the soup profile mass of that set. For a group of cells, let \(K_M\) be the total observed count for those marker genes and \(N\) the total observed count across the group. If the group's contamination fraction is \(\rho\), the model predicts an expected marker count of \(\rho N\hat q_M\). Equating this expectation with the observed marker count gives the method-of-moments estimate
The estimate is meaningful only when \(\hat q_M>0\), and the model requires \(0\leq\rho\leq1\). If the raw ratio exceeds one, the assumed model and data do not support a valid contamination fraction without a constraint or further review. Using several markers can provide more evidence than using one, but only if the markers satisfy the non-expression assumption. Pooling counts across a cluster or another suitable group is usually more stable than estimating a separate ratio from a single sparse cell.
Worked Example: Estimating a Cluster Contamination Fraction
Suppose a cluster contains cells with \(N=10{,}000\) observed molecules in total. A set of genes judged absent from this cluster has \(K_M=30\) observed counts, and the soup profile assigns \(\hat q_M=0.10\) of ambient molecules to those genes. Under the marker assumption, the expected marker count is \(\rho(10{,}000)(0.10)\).
Solving for \(\rho\) gives
The estimated contamination fraction is 3.0% for this group. This calculation is internally plausible because it lies between zero and one. It depends on the marker genes having no endogenous counts in the cluster: if, for example, 10 of the 30 counts were genuine expression, the calculation would overestimate contamination. The estimate is a group-level estimate in this example, not evidence that every cell in the cluster has exactly the same true contamination.
From a contamination estimate to gene-level counts
The SoupX accounting model decomposes an observed gene count into endogenous and ambient contributions. In expectation, the ambient part for gene \(g\) in cell \(c\) is \(\hat\rho_c n_c\hat q_g\). Subtracting that estimated contribution gives a model-based corrected count:
Here \(\hat z_{gc}\) is an estimated endogenous count, not necessarily an integer. It may be negative if the estimated ambient contribution exceeds the observed count; a reported corrected count cannot be negative, so practical implementations must handle this boundary. The equation explains the correction target without specifying how fractional expected contaminant counts are allocated among observed molecules. That allocation choice is a separate implementation detail.
Worked Example: Correcting a Gene Count
A cell has \(n_c=1{,}000\) observed molecules. Suppose its estimated contamination fraction is \(\hat\rho_c=0.030\), the soup profile has \(\hat q_A=0.12\) for gene A, and the observed count for gene A is \(x_{Ac}=20\).
The estimated ambient contribution is
Thus the expected-count correction is \(\hat z_{Ac}=20-3.6=16.4\) molecules. The result says that, under the fitted profile and contamination fraction, about 3.6 of the 20 observed gene A counts are attributed to ambient RNA in expectation. It does not mean that a fractional molecule was observed. Nor does it establish that the cell's biological expression is exactly 16.4 molecules.
Why the marker estimate works, and where it can fail
The estimator follows directly from the marker assumption. If the marker genes contribute no endogenous counts, their expected observed count in the group comes only from soup. The group has \(N\) observed molecules, an estimated fraction \(\rho\) from soup, and a fraction \(\hat q_M\) of soup molecules in the marker set. Multiplying these factors yields the expected marker count:
Setting the observed \(K_M\) equal to this expectation and rearranging gives \(\hat\rho=K_M/(N\hat q_M)\). This is a moment-based justification, not a guarantee that the estimate is precise. It treats the profile as known and does not account for uncertainty in selecting empty droplets, the marker set, or the group. In addition, a marker set with very small \(\hat q_M\) makes the denominator small, so a few counts can produce a highly variable estimate.
SoupX's conceptual model assigns a contamination fraction to each cell, but marker evidence is often sparse at individual-cell resolution. Estimating a separate ratio for every cell can produce many zeros and unstable large values. A practical analysis may estimate contamination using pooled marker evidence for a cell group and apply that estimate to cells in the group, or otherwise stabilize cell-level estimates. This borrows information across cells but assumes that the group-level estimate is suitable for its members. Differences in cell quality or lysis can make contamination vary within a group.
The main assumptions to examine are therefore: the selected empty droplets represent the ambient material in the cell-containing droplets; the marker genes are not endogenously expressed in the cells used to estimate contamination; the soup profile is relevant to those cells; and the chosen grouping does not conceal large differences in contamination. These assumptions are especially consequential for genes that are common in the soup or for cell types with low endogenous counts.
Comparisons, diagnostics, and limitations
Leaving counts uncorrected avoids making marker-based subtraction assumptions, but ambient molecules remain in the expression matrix and can create misleading low-level signal. SoupX offers an explicit, interpretable correction based on a measured soup profile and marker evidence. Its relative simplicity is also a limitation: errors in the profile or markers propagate directly into estimated contamination and corrected counts. Broader model-based approaches can use different assumptions about endogenous and contaminating expression; those approaches are not interchangeable with a marker-based estimate and require their own validation.
Useful checks begin before correction. Confirm that the empty-droplet pool is plausible and that the soup profile is not dominated by a few barcodes that may contain intact cells. Inspect whether the chosen markers have appreciable soup mass; a near-zero \(\hat q_M\) makes the ratio poorly supported. Compare marker-based estimates across reasonable marker sets or cell groups. Large disagreement can signal marker expression in the target cells, a poor soup profile, or genuine heterogeneity in contamination. Also check whether the estimate falls in the permissible range and whether a small number of marker counts is determining it.
A common mistake is to treat every observed marker count as proof of contamination. The correction depends on the marker being absent endogenously in the relevant cells; if it is expressed there, its counts inflate \(\hat\rho\), and the method can subtract genuine signal from many genes. The correction is not evidence that the marker is biologically absent, and a corrected matrix should not replace examination of the original counts and assumptions.
Check Your Understanding
Work through each question, then compare with the solutions below.
- Empty droplets contain 60 counts for gene P and 40 counts for gene Q. What are their estimated soup proportions?
- A cell group has \(N=5{,}000\) total counts, \(K_M=20\) counts in assumed absent markers, and \(\hat q_M=0.08\). Calculate the marker-based contamination estimate.
- For a cell with \(n_c=800\), \(\hat\rho_c=0.025\), and \(\hat q_g=0.10\), calculate the expected ambient contribution for gene \(g\). If its observed count is 12, calculate the expected-count correction.
- Why can endogenous expression of an assumed absent marker bias the contamination estimate, and in which direction?
- Why might a contamination estimate calculated separately in every cell be unstable?
Solutions. (1) The total is \(60+40=100\), so \(\hat q_P=60/100=0.60\) and \(\hat q_Q=40/100=0.40\). (2) \(\hat\rho=20/[5{,}000(0.08)]=20/400=0.050\), or 5.0%. (3) The expected ambient count is \(0.025(800)(0.10)=2\); the corrected expected count is \(12-2=10\). (4) The estimator attributes marker counts to soup, so genuine endogenous marker counts increase \(K_M\) and bias \(\hat\rho\) upward. (5) A single cell may contain few or no marker counts, making its ratio highly discrete and sensitive to sampling noise; pooling or stabilizing estimates can reduce this variability.