Clusterscope

The single-cell pipeline, one step at a time.

Single-cell RNA sequencing counts how many transcripts of each gene were captured from each individual cell. Turning that table into labeled cell groups takes a chain of steps, usually run in R with the Seurat package. This page runs a simplified version of that chain in your browser. Change a setting at any step and everything downstream is recomputed.

Two modes on this page. Section R, Her data: K4 PanIN vs K5 PDAC (real), shows a reanalysis of the public mouse dataset behind the study. Everything from step 01 onward is the synthetic walkthrough: generated in your browser, not patient or lab data. The synthetic dataset is 600 simulated cells, 40 made-up genes (Gene01 to Gene40) and five hidden groups called Population A to E. None of them stand for real cell types or real genes. Because the page generates the data, it knows the right answer and can score each step against it.
  1. 00The study
  2. RHer data (real)
  3. 01Raw counts
  4. 02Quality control
  5. 03Normalize
  6. 04Variable genes
  7. 05Scale + PCA
  8. 06Clustering
  9. 07t-SNE
  10. 08Markers
00

The study behind this

Real research, summarized from a 2026 abstract. It is separate from the simulation below.

Understanding progression between neoplasia and malignancy of pancreatic ductal adenocarcinoma through single-cell RNA sequencing data

Ridhi Koner, Jason Yoo, Richard Moffitt. Georgia Tech; Winship Cancer Institute, Emory.

Question. Which cell populations and genes distinguish benign PanIN from malignant PDAC?

Methods. Public scRNA-seq data from Kras-mutant genetically engineered mouse models (Burdziak et al., 2023, GEO) were merged and normalized in Seurat, clustered, and visualized with UMAP. Clusters were annotated with the markers Pyy, Sst, Amy1, Wfdc2, Epcam and Col1a1 (Hosein et al., 2019). A heatmap of the top 20 differentially expressed genes compared the PDAC-dominant epithelial cluster with the PanIN-dominant ADM cluster.

Results. Five populations were identified: epithelial, ADM, stromal, acinar, and islet & ductal. PDAC cells were concentrated in the epithelial cluster and PanIN cells in the ADM cluster. Ten genes were elevated in PDAC:

Wfdc2VimCapgTmsb10S100a6Tpi1Tpt1AprtTm4sf1Gapdh

Caveat. These results come from a single GEMM study and need validation in other models and in human tumors.

Section R right below reanalyzes the real public data. The simulation after it (steps 01 to 08) reproduces the steps of this kind of pipeline, not this data. Its populations (A to E) and genes (Gene01 to Gene40) are generic and synthetic, so nothing it shows is a result of the study above.

R

Her data: K4 PanIN vs K5 PDAC (real)

Real public data, not synthetic. Mouse cells from Burdziak et al., Science 2023 (GEO GSE207938), reanalyzed in Python/scanpy. This is not Ridhi's original R/Seurat code, so cluster numbers and exact values will differ from her poster.

K4 is the KC;RIK model at the PanIN stage. K5 is the KPC;RIK model (adds one p53 floxed allele) at the PDAC primary tumor stage. Both are sorted mKate2+ lineage-traced epithelial cells, so fibroblasts and immune cells were removed before sequencing.

Loading the dataset...

UMAP of the downsampled cells.
Her ten PDAC genes, tap to color by one:
Share of K4 (PanIN) and K5 (PDAC) cells in each cluster, all cells. Overall K5 share is .

Her ten genes in this reanalysis

Wilcoxon rank-sum on log-normalized expression, Benjamini-Hochberg adjusted. Rank is the gene's position out of genes sorted toward PDAC (1 is the most PDAC-up gene).

Agrees with the abstract

    Differs or cannot be confirmed

      Public data: Burdziak et al., Science 2023 (GEO GSE207938). Reanalysis in Python/scanpy.

      Below this point the page switches back to synthetic data. Steps 01 to 08 are a teaching simulation with made-up genes, not the dataset above.
      01

      Raw counts

      The starting point is a count matrix with one row per gene and one column per cell. Each entry is the number of transcript molecules (UMIs) of that gene detected in that cell. Real experiments have thousands of cells and around 20,000 genes. This one has 600 cells and 40 genes so every step can run instantly.

      How the generator works: each cell gets a library size from a log-normal distribution. Each population raises its own five marker genes (Gene01 to Gene05 for A, Gene06 to Gene10 for B, and so on up to Gene25 for E). Gene26 to Gene36 are shared background genes, and Gene37 to Gene40 stand in for mitochondrial genes. Counts are drawn from a negative binomial. About 5% of cells are made deliberately degraded, with tiny libraries and a high mitochondrial share, so step 2 has something to catch.

      Counts for 60 sample cells (12 per population, grouped). Darker means more counts, on a log scale.
      Library size: total counts per cell, all 600 cells.
      
      
      02

      Quality control

      Some captured "cells" are broken or empty. They tend to have very few counts, and a large share of their counts come from mitochondrial genes, because cytoplasmic RNA leaks out while mitochondrial transcripts stay behind. Seurat users filter on nCount_RNA and percent.mt. Move the thresholds and watch which cells are dropped.

      Each dot is a cell. Library size (log scale) against mito %. Removed cells are in terracotta.
      Library size with the cutoff marked.
      
      
      03

      Normalize

      A cell with twice the library size shows roughly twice the counts for every gene, which says nothing about its biology. LogNormalize divides each cell's counts by its total, multiplies by 10,000 and takes log1p. The log compresses the long right tail so a few huge values do not dominate.

      Before: raw counts, every gene in every kept cell (axis cut at the 99th percentile).
      After: log1p(count / library size × 10,000).
      
      
      04

      Highly variable genes

      Genes that vary a lot between cells, more than their average level would predict, carry most of the information about cell identity. Downstream steps use only those. Seurat's default vst method fits a loess curve of log variance against log mean on raw counts and usually keeps 2,000 genes. With only 40 genes, this page fits a straight line to log variance against log mean of the normalized values and ranks genes by how far above the line they sit.

      Each dot is a gene. Filled dots are selected. The line is the fitted mean-variance trend.

      Selected genes

      Outlined in teal: one of the 25 marker genes the generator planted. The method never sees that label.
      
      
      05

      Scale and PCA

      ScaleData shifts each selected gene to mean 0 and standard deviation 1, so a highly expressed gene does not outweigh a quiet one. PCA then finds the directions along which cells differ most. This page computes the covariance matrix of the scaled genes and finds its eigenvectors exactly (Jacobi rotations). Seurat uses a truncated SVD (irlba), which on a matrix this small gives the same components up to sign.

      The elbow plot shows how much variance each component captures. Components past the elbow are mostly noise. With five populations, you should see about four strong components.

      Elbow plot: % of variance explained per principal component. Teal bars are used downstream.
      PC 1 vs PC 2, colored by the hidden ground-truth population. The algorithm never sees these colors.
      
      
      06

      Clustering

      Seurat clusters in two calls. FindNeighbors links each cell to its k nearest neighbors in PCA space, then weights each link by how many neighbors the two cells share (Jaccard overlap, a shared-nearest-neighbor or SNN graph). FindClusters runs the Louvain algorithm, which groups cells that are more densely linked to each other than to the rest. Higher resolution gives more, smaller clusters. Past eight clusters the colors repeat.

      This page does the same steps with its own small implementation: brute-force k-NN in PCA space, Jaccard SNN weights with links under 1/15 pruned (Seurat's default prune.SNN), and Louvain with node moving plus graph aggregation. It is not Seurat's code, so cluster numbers and exact boundaries can differ from what R would give on the same matrix. Clusters are numbered from 0 by size, as Seurat does.

      PC 1 vs PC 2, now colored by the clusters the algorithm found.

      Clusters vs ground truth

      Cells in each found cluster (rows) by true population (columns). A perfect result has one dominant cell per row and column. The adjusted Rand index (ARI) is 1 for perfect agreement and about 0 for random labels.
      
      
      07

      t-SNE embedding

      To look at the cells in two dimensions, t-SNE places points so that cells that are close in PCA space stay close on the page. It starts from random positions and improves them over many iterations, which you can watch below. Perplexity sets roughly how many neighbors each cell tries to keep near it.

      This is exact t-SNE (every pair of cells, which is fine for about 600 cells), with early exaggeration of 12 for the first 250 of 1,000 iterations. Seurat's RunTSNE uses the faster Barnes-Hut approximation from Rtsne. UMAP (RunUMAP), a related nonlinear embedding, is the more common choice today and is what the study above used; it is not implemented here. Distances between separate islands in a t-SNE plot are not meaningful: the clusters come from step 6, not from this picture.

      t-SNE 1 vs t-SNE 2.

      What to try

      Set perplexity to 5 and the populations shatter into small fragments, because each cell only tries to keep a handful of neighbors close. At 30 to 50 the five groups come back as solid islands.

      Switch the coloring to ground truth and compare it with the clusters. Where they disagree, look back at the table in step 6.

      Push the step 6 resolution to 3 or more (or drop k.param to 10 first) and watch islands get split into several colors while the layout stays the same. Clustering and embedding are separate computations. On this clean synthetic data, any resolution from about 0.1 to 2 finds the same five groups; real data is rarely that forgiving.

      
      
      08

      Marker genes

      To give a cluster a name, you find the genes that set it apart. FindAllMarkers compares each cluster against all other cells, gene by gene, with a Wilcoxon rank-sum test, and reports the log2 fold change and the share of cells expressing the gene in each group (pct.1 inside, pct.2 outside). P-values are Bonferroni-adjusted across all 40 genes. Here the true answer is known, so the last column shows which population each gene was planted in.

      Click a gene in the table or the dot plot to color the embedding by its expression, as FeaturePlot does.

      Top markers per cluster

      Up to three per cluster, positive markers only, adjusted p < 0.05 and log2 fold change > 0.25, sorted by fold change.
      Dot plot. Dot size: % of cells in the cluster expressing the gene. Color: average expression, scaled across clusters. Axes are flipped from Seurat's default to fit narrow screens.
      Feature plot: