๐Ÿ”ฌ scRNA-seq
HOME

๐Ÿง  scRNA-seq Fundamentals

๐ŸŽฏ What is Single-Cell RNA-Seq?

Single-cell RNA sequencing (scRNA-seq) measures gene expression at the resolution of individual cells. Unlike bulk RNA-seq, which averages expression across thousands of cells, scRNA-seq reveals cellular heterogeneity, identifies rare cell types, and enables trajectory analysis. Since its introduction in 2009, scRNA-seq has revolutionized our understanding of development, disease, and tissue organization.

Why scRNA-seq Matters

Heterogeneity: Cell-to-cell variation. Rare cells: Find rare types. Trajectory: Development. Disease: Mechanisms. Atlas: Human Cell Atlas. Precision: Medicine.

๐Ÿ“Œ Heterogeneity๐Ÿ“Œ Rare cells๐Ÿ“Œ Trajectory๐Ÿ“Œ Atlas
# Single-Cell RNA-Seq โ€” the big picture # Measuring gene expression at single-cell resolution. print(""" === Single-Cell RNA-Seq (scRNA-seq) === What it is: - Gene expression per cell - Individual cells - Heterogeneity - Rare cell types Why it matters: - Cellular heterogeneity - Rare cell types - Developmental trajectories - Disease mechanisms - Human Cell Atlas - Precision medicine Key concepts: - Cell barcodes - UMIs (Unique Molecular Identifiers) - Droplet-based - 10x Genomics - QC - Normalization - Feature selection - PCA - UMAP / t-SNE - Clustering - Marker genes - Cell type annotation - Trajectory analysis Applications: - Cancer - Immunology - Neuroscience - Developmental biology - Stem cells - COVID-19 """) print("=== Historical Context ===") print(""" 2009: First scRNA-seq (Tang et al.) 2012: Smart-seq 2015: Drop-seq, InDrop 2016: 10x Genomics 2017: Human Cell Atlas 2019: Scanpy, Seurat v3 2020: COVID-19 scRNA-seq 2025: Spatial, multi-omics, AI """) print("=== Why It's Hard ===") print(""" 1. DROPOUTS - Many zeros - Low capture - Missing data 2. SPARSITY - ~10% non-zero - Zero-inflated - Statistical challenges 3. BATCH EFFECTS - Different runs - Different days - Integration 4. COMPUTATIONAL - Millions of cells - Memory - Scalability 5. ANNOTATION - Cell types - Manual - Reference """)

๐ŸŽฏ Why scRNA-seq Matters

๐ŸŽฏ The Value of scRNA-seq

scRNA-seq has transformed biology by revealing cellular heterogeneity that was invisible to bulk methods, enabling the discovery of new cell types and disease mechanisms.

Key Benefits

Heterogeneity: Cell-to-cell. Rare: Discovery. Trajectory: Development. Disease: Mechanisms. Atlas: Reference. Precision: Medicine.

๐ŸŽฏ Heterogeneity๐ŸŽฏ Rare๐ŸŽฏ Trajectory๐ŸŽฏ Atlas
# Why scRNA-seq Matters print("=== 1. Cellular Heterogeneity ===") print(""" Heterogeneity: - Cell-to-cell variation - Subpopulations - States Example: Bulk: average expression Single-cell: individual cells โ†’ New subtypes """) print("\n=== 2. Rare Cell Types ===") print(""" Rare: - Low abundance - Hidden in bulk - Discovery Example: Immune cells โ†’ Rare subsets โ†’ Function """) print("\n=== 3. Developmental Trajectories ===") print(""" Trajectory: - Differentiation - Development - Pseudotime Example: Stem cells โ†’ Differentiation โ†’ Trajectory """) print("\n=== 4. Disease Mechanisms ===") print(""" Disease: - Cancer heterogeneity - Immune response - Infection Example: Tumor โ†’ Cell types โ†’ Mechanisms """) print("\n=== 5. Human Cell Atlas ===") print(""" Atlas: - Reference - All cell types - Human Example: HCA โ†’ Reference โ†’ Comparison """) print("\n=== 6. Precision Medicine ===") print(""" Precision: - Personalized - Treatment - Response Example: Cancer โ†’ scRNA-seq โ†’ Therapy """) print("\n=== 7. Immunology ===") print(""" Immunology: - Immune cells - Response - Vaccines Example: T cells โ†’ Subsets โ†’ Function """) print("\n=== 8. Neuroscience ===") print(""" Neuroscience: - Brain cells - Neurons - Glia Example: Brain โ†’ Cell types โ†’ Atlas """) print("\n=== 9. Stem Cells ===") print(""" Stem cells: - Differentiation - Regeneration - Therapy Example: iPSC โ†’ Differentiation โ†’ Trajectory """) print("\n=== 10. COVID-19 ===") print(""" COVID-19: - Immune response - Lung - Severity Example: COVID-19 โ†’ scRNA-seq โ†’ Mechanisms """)

โš™๏ธ Workflow Overview

๐ŸŽฏ The scRNA-seq Pipeline

A typical scRNA-seq workflow goes from sample preparation to biological interpretation, involving cell capture, sequencing, QC, normalization, clustering, and annotation.

Workflow

Sample: Cells. Capture: Droplets. Sequence: 10x. QC: Filter. Normalize: Scale. Cluster: Groups. Annotate: Types.

โš™๏ธ Sampleโš™๏ธ Captureโš™๏ธ Sequenceโš™๏ธ Cluster
# scRNA-seq Workflow print("=== Overview ===") print(""" Step 1: Sample preparation Step 2: Cell capture (droplets) Step 3: Library preparation Step 4: Sequencing Step 5: Alignment (CellRanger) Step 6: QC Step 7: Normalization Step 8: Feature selection Step 9: Dimensionality reduction Step 10: Clustering Step 11: Marker genes Step 12: Cell type annotation Step 13: Trajectory analysis Step 14: Analysis & interpretation """) print("\n=== Step 1: Sample ===") print(""" Sample: - Tissue - Dissociation - Single cells - Viability Example: Tissue โ†’ Dissociation โ†’ Single cells """) print("\n=== Step 2: Cell Capture ===") print(""" Capture: - Droplet-based - 10x Genomics - Barcoded beads - Oil droplets Example: Cells + beads โ†’ Droplets โ†’ Barcoding """) print("\n=== Step 3: Library Prep ===") print(""" Library: - Reverse transcription - cDNA - Amplification - Sequencing Example: mRNA โ†’ cDNA โ†’ Library """) print("\n=== Step 4: Sequencing ===") print(""" Sequencing: - Illumina - Short reads - 50-150 bp - Paired-end Example: NovaSeq โ†’ Reads โ†’ FASTQ """) print("\n=== Step 5: Alignment ===") print(""" Alignment: - CellRanger - STAR - Reference genome - Count matrix Example: CellRanger count โ†’ Count matrix โ†’ Feature-barcode """) print("\n=== Step 6: QC ===") print(""" QC: - Cell filtering - Gene filtering - Mitochondrial % - Doublets Example: n_genes > 200 MT% < 20% """) print("\n=== Step 7: Normalization ===") print(""" Normalization: - Library size - Log transform - Scaling - Batch correction Example: Normalize โ†’ Log1p โ†’ Scale """) print("\n=== Step 8: Feature Selection ===") print(""" Features: - Highly variable genes - HVGs - 2000-3000 Example: HVG โ†’ Top 2000 โ†’ PCA """) print("\n=== Step 9: Dimensionality Reduction ===") print(""" Dim reduction: - PCA - UMAP - t-SNE Example: PCA โ†’ 50 PCs โ†’ UMAP """) print("\n=== Step 10: Clustering ===") print(""" Clustering: - Leiden - Louvain - Graph-based Example: Leiden โ†’ Clusters โ†’ Cell types """) print("\n=== Step 11: Marker Genes ===") print(""" Markers: - Differential expression - Cluster markers - Annotate Example: Rank genes โ†’ Markers โ†’ Annotation """) print("\n=== Step 12: Annotation ===") print(""" Annotation: - Manual - Automated - Reference Example: Markers โ†’ Cell types โ†’ Annotation """) print("\n=== Step 13: Trajectory ===") print(""" Trajectory: - Pseudotime - Differentiation - PAGA - Monocle Example: Trajectory โ†’ Pseudotime โ†’ Development """) print("\n=== Step 14: Analysis ===") print(""" Analysis: - Differential expression - Composition - Pathways - Visualization Example: Cluster markers โ†’ Pathways โ†’ Biology """)

๐Ÿ”ฌ Platforms & Technologies

๐ŸŽฏ scRNA-seq Technologies

Several platforms exist for scRNA-seq, each with strengths and trade-offs. The 10x Genomics Chromium platform dominates due to its scalability and cost-effectiveness.

Platforms

10x: Droplet. Smart-seq: Plate. Drop-seq: Droplet. Seq-Well: Nanowell. BD Rhapsody: Nanowell. PacBio: Long reads.

๐Ÿ”ฌ 10x๐Ÿ”ฌ Smart-seq๐Ÿ”ฌ Drop-seq๐Ÿ”ฌ Nanowell
# Platforms & Technologies print("=== 1. 10x Genomics ===") print(""" 10x Genomics: - Droplet-based - Most popular - 1000-10000 cells - 3' or 5' Pros: - Scalable - Cost-effective - Standard Cons: - 3' bias - Dropouts Example: Chromium โ†’ 10,000 cells """) print("\n=== 2. Smart-seq ===") print(""" Smart-seq: - Plate-based - Full-length - 96-384 cells - High sensitivity Pros: - Full-length - Sensitive - Isoforms Cons: - Low throughput - Expensive Example: Smart-seq2 โ†’ 384 cells """) print("\n=== 3. Drop-seq ===") print(""" Drop-seq: - Droplet-based - Early method - 1000-10000 cells Pros: - Scalable - Cost-effective Cons: - 3' bias - Dropouts """) print("\n=== 4. Seq-Well ===") print(""" Seq-Well: - Nanowell - Portable - Low cost Pros: - Portable - Low cost Cons: - Throughput """) print("\n=== 5. BD Rhapsody ===") print(""" BD Rhapsody: - Nanowell - Targeted - Multiplexing Pros: - Targeted - Multiplexing Cons: - Cost """) print("\n=== 6. Long Reads ===") print(""" Long reads: - PacBio - Nanopore - Full-length - Isoforms Pros: - Full-length - Isoforms - Splicing Cons: - Cost - Throughput """) print("\n=== 7. Comparison ===") print(f"{'Platform':<20} {'Method':<15} {'Cells':<15} {'Reads':<15}") print("-" * 65) print(f"{'10x':<20} {'Droplet':<15} {'10k':<15} {'3\\'':<15}") print(f"{'Smart-seq':<20} {'Plate':<15} {'384':<15} {'Full':<15}") print(f"{'Drop-seq':<20} {'Droplet':<15} {'10k':<15} {'3\\'':<15}") print(f"{'Seq-Well':<20} {'Nanowell':<15} {'1k':<15} {'3\\'':<15}") print(f"{'BD Rhapsody':<20} {'Nanowell':<15} {'10k':<15} {'3\\'':<15}") print("\n=== 8. Choosing ===") print(""" Choose: - 10x: most cases - Smart-seq: isoforms - Long reads: isoforms - Targeted: specific genes """) print("\n=== 9. UMIs ===") print(""" UMI: - Unique Molecular Identifier - Barcode - Count molecules - Reduce PCR bias Example: Cell barcode + UMI โ†’ Count """) print("\n=== 10. Use Cases ===") print(""" Use cases: - Human: 10x - Mouse: 10x - Rare cells: Smart-seq - Isoforms: Smart-seq - Clinical: 10x """)

๐Ÿงน Quality Control

๐ŸŽฏ Filtering Low-Quality Cells

Quality control (QC) removes low-quality cells, empty droplets, and doublets before analysis. It's essential for reliable results.

QC

Genes: >200. Counts: >500. MT%: <20%. Doublets: Remove. Empty: Remove. HBB: Filter.

๐Ÿงน Genes๐Ÿงน Counts๐Ÿงน MT%๐Ÿงน Doublets
# Quality Control print("=== 1. Cell Filtering ===") print(""" Cell filtering: - n_genes > 200 - n_counts > 500 - MT% < 20% - Complex Example: Cell 1: 500 genes, MT 10% โ†’ keep Cell 2: 100 genes, MT 5% โ†’ filter Cell 3: 1000 genes, MT 30% โ†’ filter """) print("\n=== 2. Gene Filtering ===") print(""" Gene filtering: - Expressed in >= 3 cells - Remove low - Remove MT genes Example: Gene A: 10 cells โ†’ keep Gene B: 1 cell โ†’ filter """) print("\n=== 3. Mitochondrial ===") print(""" MT%: - Mitochondrial genes - MT- prefix - Apoptosis - Filter Example: MT% < 20% โ†’ keep MT% > 20% โ†’ filter """) print("\n=== 4. Doublets ===") print(""" Doublets: - Two cells in one droplet - DoubletFinder - Scrublet - Remove Example: DoubletFinder โ†’ Remove doublets """) print("\n=== 5. Empty Droplets ===") print(""" Empty: - No cell - Ambient RNA - EmptyDrops - Remove Example: EmptyDrops โ†’ Remove empty """) print("\n=== 6. Ambient RNA ===") print(""" Ambient: - Free RNA - SoupX - DecontX - Remove Example: SoupX โ†’ Remove ambient """) print("\n=== 7. HBB ===") print(""" HBB: - Hemoglobin - Red blood cells - Filter Example: HBB high โ†’ RBC โ†’ Filter """) print("\n=== 8. QC Metrics ===") print(""" Metrics: - n_genes_by_counts - total_counts - pct_counts_mt - pct_counts_ribo - pct_counts_hb Example: sc.pp.calculate_qc_metrics() """) print("\n=== 9. Python QC ===") print(""" import scanpy as sc def qc_filter(adata, min_genes=200, min_counts=500, max_mt=20): \"\"\"QC filter.\"\"\" # Calculate metrics adata.var['mt'] = adata.var_names.str.startswith('MT-') sc.pp.calculate_qc_metrics(adata, qc_vars=['mt'], inplace=True) # Filter cells adata = adata[adata.obs['n_genes_by_counts'] >= min_genes] adata = adata[adata.obs['total_counts'] >= min_counts] adata = adata[adata.obs['pct_counts_mt'] < max_mt] # Filter genes sc.pp.filter_genes(adata, min_cells=3) return adata # Use # adata = qc_filter(adata) """) print("\n=== 10. Best Practices ===") print(""" Best practices: - Visualize QC - Adaptive thresholds - Remove doublets - Remove ambient - Document """)

๐Ÿ“Š Normalization

๐ŸŽฏ Correcting for Technical Variation

Normalization corrects for differences in library size and sequencing depth, making cells comparable. It's essential before clustering and differential expression.

Normalization

Library size: Total counts. Log1p: Stabilize. Scaling: Z-score. Batch: Correct. SCTransform: Seurat. Pearson: Residuals.

๐Ÿ“Š Library size๐Ÿ“Š Log1p๐Ÿ“Š Scaling๐Ÿ“Š Batch
# Normalization print("=== 1. Library Size ===") print(""" Library size: - Total counts per cell - Normalize - CPM-like Example: Cell 1: 10,000 counts Cell 2: 20,000 counts โ†’ Normalize """) print("\n=== 2. Log Transformation ===") print(""" Log: - Stabilize variance - Log1p - Reduce skew Example: log1p(x) """) print("\n=== 3. Scaling ===") print(""" Scaling: - Z-score - Mean 0 - Variance 1 - Before PCA Example: (x - mean) / std """) print("\n=== 4. Batch Correction ===") print(""" Batch: - Different runs - Different days - Correct Tools: - Harmony - BBKNN - Scanorama - Seurat integration Example: Harmony โ†’ Corrected """) print("\n=== 5. SCTransform ===") print(""" SCTransform: - Seurat - Regularized negative binomial - Better Example: SCTransform() """) print("\n=== 6. Pearson Residuals ===") print(""" Pearson: - Residuals - Analytic - Better Example: sc.experimental.pp.normalize_pearson_residuals() """) print("\n=== 7. Python Normalization ===") print(""" import scanpy as sc def normalize(adata): \"\"\"Normalize data.\"\"\" # Library size sc.pp.normalize_total(adata, target_sum=1e4) # Log sc.pp.log1p(adata) # Store raw adata.raw = adata # Scale sc.pp.scale(adata, max_value=10) return adata # Use # adata = normalize(adata) """) print("\n=== 8. Batch Correction Python ===") print(""" import scanpy.external as sce def batch_correct(adata, batch_key="batch"): \"\"\"Batch correction with Harmony.\"\"\" sce.pp.harmony_integrate(adata, batch_key) return adata # Use # adata = batch_correct(adata, "sample") """) print("\n=== 9. R Normalization ===") print(""" library(Seurat) # Normalize seurat_obj <- NormalizeData(seurat_obj) seurat_obj <- FindVariableFeatures(seurat_obj) seurat_obj <- ScaleData(seurat_obj) # SCTransform seurat_obj <- SCTransform(seurat_obj) # Integration seurat_obj <- IntegrateLayers(seurat_obj, method = HarmonyIntegration) """) print("\n=== 10. Best Practices ===") print(""" Best practices: - Normalize - Log - Scale - Batch correct - Document """)

๐Ÿงฌ Feature Selection

๐ŸŽฏ Highly Variable Genes

Feature selection identifies highly variable genes (HVGs) that drive biological variation, reducing noise and dimensionality for downstream analysis.

Features

HVGs: Variable genes. 2000-3000: Standard. Selection: Variance. PCA: Input. Markers: Help. Remove: Noise.

๐Ÿงฌ HVGs๐Ÿงฌ 2000-3000๐Ÿงฌ Variance๐Ÿงฌ PCA
# Feature Selection print("=== 1. What are HVGs? ===") print(""" HVG: - Highly variable genes - High variance - Biological signal - Remove noise Example: Gene A: low variance โ†’ skip Gene B: high variance โ†’ keep """) print("\n=== 2. Selection Methods ===") print(""" Methods: - Seurat: mean-variance - Scanpy: seurat, cell_ranger, seurat_v3 - Poisson Example: sc.pp.highly_variable_genes() """) print("\n=== 3. Number ===") print(""" Number: - 2000-3000 - Standard - Depends Example: 2000 HVGs โ†’ PCA """) print("\n=== 4. Exclude Genes ===") print(""" Exclude: - MT genes - Ribosomal - HBB - Cell cycle Example: Exclude MT- โ†’ HVGs """) print("\n=== 5. Cell Cycle ===") print(""" Cell cycle: - Proliferation - Confounding - Regress Example: Cell cycle score โ†’ Regress """) print("\n=== 6. Python HVG ===") print(""" import scanpy as sc def select_hvg(adata, n_top_genes=2000): \"\"\"Select HVGs.\"\"\" sc.pp.highly_variable_genes( adata, n_top_genes=n_top_genes, flavor='seurat_v3' ) adata = adata[:, adata.var['highly_variable']] return adata # Use # adata = select_hvg(adata) """) print("\n=== 7. R HVG ===") print(""" library(Seurat) seurat_obj <- FindVariableFeatures( seurat_obj, selection.method = "vst", nfeatures = 2000 ) """) print("\n=== 8. Visualization ===") print(""" Visualization: - HVG plot - Mean vs variance - Highlight HVGs Example: sc.pl.highly_variable_genes(adata) """) print("\n=== 9. Batch HVG ===") print(""" Batch: - Per batch - Combine - More robust Example: batch_key='sample' """) print("\n=== 10. Best Practices ===") print(""" Best practices: - 2000-3000 - Exclude MT - Batch-aware - Visualize """)

๐Ÿ“‰ Dimensionality Reduction

๐ŸŽฏ Reducing Dimensions

Dimensionality reduction projects high-dimensional gene expression data into lower dimensions for visualization and clustering. PCA is used first, then UMAP or t-SNE for visualization.

Dim Reduction

PCA: Linear. UMAP: Non-linear. t-SNE: Non-linear. 50 PCs: Standard. Visualization: UMAP. Clustering: PCs.

๐Ÿ“‰ PCA๐Ÿ“‰ UMAP๐Ÿ“‰ t-SNE๐Ÿ“‰ 50 PCs
# Dimensionality Reduction print("=== 1. PCA ===") print(""" PCA: - Linear - Variance - 50 PCs - Input for UMAP Example: sc.tl.pca(adata, n_comps=50) """) print("\n=== 2. UMAP ===") print(""" UMAP: - Non-linear - Fast - Global structure - Visualization Example: sc.tl.umap(adata) """) print("\n=== 3. t-SNE ===") print(""" t-SNE: - Non-linear - Slow - Local structure - Visualization Example: sc.tl.tsne(adata) """) print("\n=== 4. PCA Number ===") print(""" Number: - 50 PCs - Elbow plot - Variance Example: sc.pl.pca_variance_ratio(adata) """) print("\n=== 5. UMAP Parameters ===") print(""" Parameters: - n_neighbors: 15 - min_dist: 0.5 - metric: euclidean Example: sc.pp.neighbors(adata, n_neighbors=15) sc.tl.umap(adata, min_dist=0.5) """) print("\n=== 6. t-SNE Parameters ===") print(""" Parameters: - perplexity: 30 - learning_rate: 1000 - n_iter: 1000 Example: sc.tl.tsne(adata, perplexity=30) """) print("\n=== 7. Python Dim Reduction ===") print(""" import scanpy as sc def dim_reduction(adata, n_pcs=50, n_neighbors=15): \"\"\"Dimensionality reduction.\"\"\" # PCA sc.tl.pca(adata, n_comps=n_pcs) # Neighbors sc.pp.neighbors(adata, n_neighbors=n_neighbors, n_pcs=n_pcs) # UMAP sc.tl.umap(adata) # t-SNE sc.tl.tsne(adata) return adata # Use # adata = dim_reduction(adata) """) print("\n=== 8. Visualization ===") print(""" Visualization: - PCA - UMAP - t-SNE - Color by gene - Color by cluster Example: sc.pl.umap(adata, color=['cluster', 'gene']) """) print("\n=== 9. R Dim Reduction ===") print(""" library(Seurat) seurat_obj <- RunPCA(seurat_obj, npcs = 50) seurat_obj <- RunUMAP(seurat_obj, dims = 1:30) seurat_obj <- RunTSNE(seurat_obj, dims = 1:30) """) print("\n=== 10. Best Practices ===") print(""" Best practices: - 50 PCs - Elbow plot - UMAP for viz - t-SNE local - Document """)

๐Ÿ”ต Clustering

๐ŸŽฏ Grouping Similar Cells

Clustering groups cells with similar expression profiles, revealing cell types and states. Graph-based clustering (Leiden, Louvain) is the standard.

Clustering

Leiden: Standard. Louvain: Classic. Graph: Neighbors. Resolution: Granularity. Markers: Identify. Annotate: Types.

๐Ÿ”ต Leiden๐Ÿ”ต Louvain๐Ÿ”ต Graph๐Ÿ”ต Resolution
# Clustering print("=== 1. Graph-Based ===") print(""" Graph: - KNN graph - Neighbors - Community detection Example: sc.pp.neighbors(adata) sc.tl.leiden(adata) """) print("\n=== 2. Leiden ===") print(""" Leiden: - Standard - Better than Louvain - Resolution Example: sc.tl.leiden(adata, resolution=1.0) """) print("\n=== 3. Louvain ===") print(""" Louvain: - Classic - Fast - Resolution Example: sc.tl.louvain(adata, resolution=1.0) """) print("\n=== 4. Resolution ===") print(""" Resolution: - Granularity - Higher: more clusters - Lower: fewer Example: res=0.5: 5 clusters res=1.0: 10 clusters res=2.0: 20 clusters """) print("\n=== 5. Number of Clusters ===") print(""" Number: - Depends - Biology - Resolution - Markers Example: Try multiple โ†’ Choose """) print("\n=== 6. Cluster Markers ===") print(""" Markers: - Differential expression - Cluster vs rest - Annotate Example: sc.tl.rank_genes_groups(adata, 'leiden') """) print("\n=== 7. Python Clustering ===") print(""" import scanpy as sc def cluster(adata, resolution=1.0): \"\"\"Cluster cells.\"\"\" # Neighbors sc.pp.neighbors(adata, n_neighbors=15, n_pcs=50) # Leiden sc.tl.leiden(adata, resolution=resolution) # UMAP sc.tl.umap(adata) return adata # Use # adata = cluster(adata, resolution=1.0) """) print("\n=== 8. R Clustering ===") print(""" library(Seurat) seurat_obj <- FindNeighbors(seurat_obj, dims = 1:30) seurat_obj <- FindClusters(seurat_obj, resolution = 1.0) seurat_obj <- RunUMAP(seurat_obj, dims = 1:30) """) print("\n=== 9. Visualization ===") print(""" Visualization: - UMAP colored by cluster - Cluster markers - Heatmap Example: sc.pl.umap(adata, color='leiden') """) print("\n=== 10. Best Practices ===") print(""" Best practices: - Leiden - Try resolutions - Check markers - Validate - Annotate """)

๐Ÿ”– Marker Genes

๐ŸŽฏ Finding Cluster Markers

Marker genes are genes that are differentially expressed in a cluster compared to other clusters. They are used to identify and annotate cell types.

Markers

Differential: Cluster vs rest. Rank: Genes. Wilcoxon: Test. LogFC: Effect. Annotation: Cell types. Visualization: Heatmap, dotplot.

๐Ÿ”– Differential๐Ÿ”– Rank๐Ÿ”– Wilcoxon๐Ÿ”– Annotation
# Marker Genes print("=== 1. Differential Expression ===") print(""" DE: - Cluster vs rest - Statistical test - Rank genes Tests: - Wilcoxon - t-test - Logistic regression Example: sc.tl.rank_genes_groups(adata, 'leiden') """) print("\n=== 2. Rank Genes ===") print(""" Rank: - Top genes - Score - LogFC Example: sc.tl.rank_genes_groups(adata, 'leiden', method='wilcoxon') sc.pl.rank_genes_groups(adata) """) print("\n=== 3. Marker Genes ===") print(""" Markers: - Known markers - Cell types - Validate Examples: - CD3D: T cells - CD79A: B cells - CD14: Monocytes - NKG7: NK cells - MS4A1: B cells - LYZ: Myeloid - ACTA2: Fibroblasts - PECAM1: Endothelial """) print("\n=== 4. Visualization ===") print(""" Visualization: - Heatmap - Dotplot - Violin - UMAP Example: sc.pl.heatmap(adata, marker_genes, groupby='leiden') sc.pl.dotplot(adata, marker_genes, groupby='leiden') sc.pl.violin(adata, marker_genes, groupby='leiden') """) print("\n=== 5. Python Markers ===") print(""" import scanpy as sc def find_markers(adata, groupby='leiden', method='wilcoxon'): \"\"\"Find marker genes.\"\"\" sc.tl.rank_genes_groups( adata, groupby=groupby, method=method ) return adata # Use # adata = find_markers(adata) """) print("\n=== 6. Get Markers ===") print(""" def get_markers(adata, n_genes=10): \"\"\"Get top markers.\"\"\" markers = {} for group in adata.obs['leiden'].unique(): df = sc.get.rank_genes_groups_df(adata, group=group) markers[group] = df.head(n_genes)['names'].tolist() return markers # Use # markers = get_markers(adata) """) print("\n=== 7. R Markers ===") print(""" library(Seurat) markers <- FindAllMarkers(seurat_obj, only.pos = TRUE) top_markers <- markers %>% group_by(cluster) %>% top_n(10) """) print("\n=== 8. Annotation ===") print(""" Annotation: - Markers - Cell types - Manual - Automated Example: Cluster 0: CD3D+ โ†’ T cells Cluster 1: CD79A+ โ†’ B cells """) print("\n=== 9. Automated ===") print(""" Automated: - SingleR - CellTypist - scType - scmap Example: SingleR โ†’ Cell types """) print("\n=== 10. Best Practices ===") print(""" Best practices: - Multiple markers - Known markers - Validate - Visualize - Document """)

๐Ÿท๏ธ Cell Type Annotation

๐ŸŽฏ Assigning Cell Types

Cell type annotation assigns biological identities to clusters based on marker genes, reference datasets, and automated tools.

Annotation

Manual: Markers. Automated: SingleR, CellTypist. Reference: Atlas. Validate: Markers. Hierarchy: Levels. Ontology: CL.

๐Ÿท๏ธ Manual๐Ÿท๏ธ Automated๐Ÿท๏ธ Reference๐Ÿท๏ธ Validate
# Cell Type Annotation print("=== 1. Manual Annotation ===") print(""" Manual: - Markers - Known genes - Expert knowledge Example: Cluster 0: CD3D, CD3E โ†’ T cells Cluster 1: CD79A, MS4A1 โ†’ B cells Cluster 2: CD14, LYZ โ†’ Monocytes """) print("\n=== 2. Automated Annotation ===") print(""" Automated: - SingleR - CellTypist - scType - scmap Example: SingleR โ†’ Reference-based """) print("\n=== 3. SingleR ===") print(""" SingleR: - Reference-based - Correlation - R package Example: library(SingleR) pred <- SingleR(test = sce, ref = ref, labels = ref$label) """) print("\n=== 4. CellTypist ===") print(""" CellTypist: - Python - Logistic regression - Reference Example: import celltypist predictions = celltypist.annotate(adata, model='Immune_All_Low.pkl') """) print("\n=== 5. Reference Atlases ===") print(""" References: - Human Cell Atlas - Tabula Muris - Allen Brain Atlas - Immune Cell Atlas Example: HCA โ†’ Reference โ†’ Annotation """) print("\n=== 6. Marker Validation ===") print(""" Validation: - Known markers - Consistent - Visualize Example: Cluster 0: T cells โ†’ CD3D+ โ†’ Validate """) print("\n=== 7. Hierarchy ===") print(""" Hierarchy: - Level 1: T cells - Level 2: CD4 T cells - Level 3: Treg Example: Annotate โ†’ Hierarchy """) print("\n=== 8. Ontology ===") print(""" Ontology: - Cell Ontology (CL) - Standard - Ontology Example: CL:0000084 โ†’ T cell """) print("\n=== 9. Python Annotation ===") print(""" import scanpy as sc def annotate(adata, markers_dict): \"\"\"Annotate clusters manually.\"\"\" # Map clusters to cell types cluster_to_type = { '0': 'T cells', '1': 'B cells', '2': 'Monocytes', # ... } adata.obs['cell_type'] = adata.obs['leiden'].map(cluster_to_type) return adata # Use # adata = annotate(adata, markers) """) print("\n=== 10. Best Practices ===") print(""" Best practices: - Multiple methods - Markers - Reference - Validate - Ontology """)

๐Ÿงญ Trajectory Analysis

๐ŸŽฏ Inferring Developmental Paths

Trajectory analysis (pseudotime) infers developmental or differentiation paths from scRNA-seq data. It orders cells along a continuum of states, revealing transitions between cell types.

Trajectory

Pseudotime: Order cells. Monocle: Classic. PAGA: Graph. Slingshot: Curves. scVelo: RNA velocity. CellRank: Fate.

๐Ÿงญ Pseudotime๐Ÿงญ Monocle๐Ÿงญ PAGA๐Ÿงญ scVelo
# Trajectory Analysis print("=== 1. What is Trajectory? ===") print(""" Trajectory: - Developmental path - Differentiation - Pseudotime - Order cells Example: Stem cell โ†’ progenitor โ†’ mature โ†’ Trajectory """) print("\n=== 2. Pseudotime ===") print(""" Pseudotime: - Order cells - Progress - Root Example: Pseudotime 0 โ†’ start Pseudotime 1 โ†’ end """) print("\n=== 3. Monocle ===") print(""" Monocle: - R package - Classic - DDRTree Example: library(monocle3) cds <- new_cell_data_set(expression_matrix) cds <- learn_graph(cds) cds <- order_cells(cds) """) print("\n=== 4. PAGA ===") print(""" PAGA: - Python - Graph abstraction - Connectivity Example: sc.tl.paga(adata, groups='leiden') sc.pl.paga(adata) """) print("\n=== 5. Slingshot ===") print(""" Slingshot: - R package - Curves - Lineages Example: library(slingshot) sce <- slingshot(sce, clusterLabels = 'leiden') """) print("\n=== 6. RNA Velocity ===") print(""" RNA velocity: - Spliced/unspliced - Direction - scVelo Example: import scvelo as scv scv.pp.filter_and_normalize(adata) scv.tl.velocity(adata) scv.tl.velocity_graph(adata) """) print("\n=== 7. CellRank ===") print(""" CellRank: - Fate - Direction - Python Example: import cellrank as cr cr.tl.initial_states(adata) cr.tl.lineages(adata) """) print("\n=== 8. Python Trajectory ===") print(""" import scanpy as sc def trajectory(adata, groupby='leiden'): \"\"\"Trajectory analysis with PAGA.\"\"\" sc.tl.paga(adata, groups=groupby) sc.pl.paga(adata) # Diffusion map sc.tl.diffmap(adata) # DPT sc.tl.dpt(adata) return adata # Use # adata = trajectory(adata) """) print("\n=== 9. Visualization ===") print(""" Visualization: - PAGA graph - Pseudotime UMAP - Trajectory - Gene dynamics Example: sc.pl.umap(adata, color='dpt_pseudotime') """) print("\n=== 10. Best Practices ===") print(""" Best practices: - Multiple methods - Validate - Biology - Visualize - Document """)

๐Ÿ› ๏ธ Tools (Scanpy, Seurat, CellRanger)

๐ŸŽฏ scRNA-seq Tools

Many tools exist for scRNA-seq analysis. Each has strengths and is suited to different use cases.

Tools

CellRanger: Alignment. Scanpy: Python. Seurat: R. Monocle: Trajectory. SingleR: Annotation. Harmony: Integration.

๐Ÿ› ๏ธ CellRanger๐Ÿ› ๏ธ Scanpy๐Ÿ› ๏ธ Seurat๐Ÿ› ๏ธ Monocle
# Tools print("=== CellRanger ===") print(""" CellRanger: - 10x Genomics - Alignment - Count matrix - Standard Command: cellranger count --id=sample \\ --transcriptome=ref \\ --fastqs=fastq_path \\ --sample=sample """) print("\n=== Scanpy ===") print(""" Scanpy: - Python - Comprehensive - Fast - Scalable Features: - QC - Normalization - Clustering - UMAP - Markers - Trajectory Install: pip install scanpy """) print("\n=== Seurat ===") print(""" Seurat: - R - Comprehensive - Popular - Integration Features: - QC - Normalization - Clustering - UMAP - Markers - Integration Install: install.packages("Seurat") """) print("\n=== Monocle ===") print(""" Monocle: - R - Trajectory - Pseudotime - DDRTree Install: BiocManager::install("monocle3") """) print("\n=== SingleR ===") print(""" SingleR: - R - Annotation - Reference-based Install: BiocManager::install("SingleR") """) print("\n=== Harmony ===") print(""" Harmony: - Integration - Batch correction - Fast Install: install.packages("harmony") """) print("\n=== Other Tools ===") print(""" 1. scVelo - RNA velocity 2. CellTypist - Annotation 3. PAGA - Trajectory 4. scran - Normalization 5. Scrublet - Doublets 6. SoupX - Ambient RNA 7. DoubletFinder - Doublets 8. CellChat - Cell-cell communication """) print("\n=== Tool Comparison ===") print(f"{'Tool':<20} {'Language':<15} {'Best For':<25}") print("-" * 60) print(f"{'CellRanger':<20} {'CLI':<15} {'Alignment':<25}") print(f"{'Scanpy':<20} {'Python':<15} {'Comprehensive':<25}") print(f"{'Seurat':<20} {'R':<15} {'Comprehensive':<25}") print(f"{'Monocle':<20} {'R':<15} {'Trajectory':<25}") print(f"{'SingleR':<20} {'R':<15} {'Annotation':<25}") print(f"{'Harmony':<20} {'R/Python':<15} {'Integration':<25}") print("\n=== When to Use Which ===") print(""" USE CellRanger: โœ“ 10x alignment โœ“ Count matrix USE Scanpy: โœ“ Python โœ“ Comprehensive โœ“ Scalable USE Seurat: โœ“ R โœ“ Comprehensive โœ“ Popular USE Monocle: โœ“ Trajectory โœ“ Pseudotime USE SingleR: โœ“ Annotation โœ“ Reference USE Harmony: โœ“ Integration โœ“ Batch correction """)

๐Ÿ Python (Scanpy)

๐ŸŽฏ scRNA-seq with Scanpy

Scanpy is the leading Python library for scRNA-seq analysis. It provides comprehensive tools for QC, normalization, clustering, visualization, and more.

Scanpy

AnnData: Data structure. QC: Filter. Normalize: Scale. Cluster: Leiden. UMAP: Visualize. Markers: Find.

๐Ÿ AnnData๐Ÿ QC๐Ÿ Cluster๐Ÿ UMAP
# Python (Scanpy) print("=== 1. Install ===") print(""" pip install scanpy pip install leidenalg """) print("\n=== 2. Load Data ===") print(""" import scanpy as sc # Load 10x data adata = sc.read_10x_mtx( 'filtered_feature_bc_matrix/', var_names='gene_symbols', cache=True ) print(adata) """) print("\n=== 3. QC ===") print(""" # Calculate metrics adata.var['mt'] = adata.var_names.str.startswith('MT-') sc.pp.calculate_qc_metrics(adata, qc_vars=['mt'], inplace=True) # Filter adata = adata[adata.obs['n_genes_by_counts'] >= 200] adata = adata[adata.obs['total_counts'] >= 500] adata = adata[adata.obs['pct_counts_mt'] < 20] sc.pp.filter_genes(adata, min_cells=3) """) print("\n=== 4. Normalize ===") print(""" # Normalize sc.pp.normalize_total(adata, target_sum=1e4) sc.pp.log1p(adata) # Store raw adata.raw = adata # HVG sc.pp.highly_variable_genes(adata, n_top_genes=2000) adata = adata[:, adata.var['highly_variable']] # Scale sc.pp.scale(adata, max_value=10) """) print("\n=== 5. PCA ===") print(""" sc.tl.pca(adata, n_comps=50) sc.pl.pca_variance_ratio(adata, n_pcs=50) """) print("\n=== 6. Clustering ===") print(""" # Neighbors sc.pp.neighbors(adata, n_neighbors=15, n_pcs=50) # Leiden sc.tl.leiden(adata, resolution=1.0) # UMAP sc.tl.umap(adata) # Plot sc.pl.umap(adata, color='leiden') """) print("\n=== 7. Markers ===") print(""" # Rank genes sc.tl.rank_genes_groups(adata, 'leiden', method='wilcoxon') # Plot sc.pl.rank_genes_groups(adata, n_genes=10) # Get markers markers = sc.get.rank_genes_groups_df(adata, group='0') print(markers.head(10)) """) print("\n=== 8. Annotation ===") print(""" # Manual annotation cluster_to_type = { '0': 'T cells', '1': 'B cells', '2': 'Monocytes', # ... } adata.obs['cell_type'] = adata.obs['leiden'].map(cluster_to_type) # Plot sc.pl.umap(adata, color='cell_type') """) print("\n=== 9. Trajectory ===") print(""" # PAGA sc.tl.paga(adata, groups='leiden') sc.pl.paga(adata) # Diffusion map sc.tl.diffmap(adata) # DPT sc.tl.dpt(adata) # Plot sc.pl.umap(adata, color='dpt_pseudotime') """) print("\n=== 10. Complete Pipeline ===") print(""" import scanpy as sc def scrna_pipeline(filepath): \"\"\"Complete scRNA-seq pipeline.\"\"\" # Load adata = sc.read_10x_mtx(filepath, var_names='gene_symbols') # QC adata.var['mt'] = adata.var_names.str.startswith('MT-') sc.pp.calculate_qc_metrics(adata, qc_vars=['mt'], inplace=True) adata = adata[adata.obs['n_genes_by_counts'] >= 200] adata = adata[adata.obs['pct_counts_mt'] < 20] sc.pp.filter_genes(adata, min_cells=3) # Normalize sc.pp.normalize_total(adata, target_sum=1e4) sc.pp.log1p(adata) adata.raw = adata # HVG sc.pp.highly_variable_genes(adata, n_top_genes=2000) adata = adata[:, adata.var['highly_variable']] sc.pp.scale(adata, max_value=10) # PCA sc.tl.pca(adata, n_comps=50) # Cluster sc.pp.neighbors(adata, n_neighbors=15, n_pcs=50) sc.tl.leiden(adata, resolution=1.0) sc.tl.umap(adata) # Markers sc.tl.rank_genes_groups(adata, 'leiden', method='wilcoxon') return adata # Use # adata = scrna_pipeline("filtered_feature_bc_matrix/") """)

โš–๏ธ Tool Comparison

๐ŸŽฏ Which Tool?

Choosing the right scRNA-seq tool depends on your programming language, data size, and analysis goals.

Comparison

Scanpy: Python. Seurat: R. CellRanger: Alignment. Monocle: Trajectory. SingleR: Annotation. Harmony: Integration.

โš–๏ธ Scanpyโš–๏ธ Seuratโš–๏ธ CellRangerโš–๏ธ Monocle
Tool Language Step Best For
CellRangerCLIAlignment10x data
ScanpyPythonComprehensivePython users
SeuratRComprehensiveR users
MonocleRTrajectoryPseudotime
SlingshotRTrajectoryCurves
PAGAPythonTrajectoryGraph
scVeloPythonVelocityDirection
SingleRRAnnotationReference
CellTypistPythonAnnotationAutomated
HarmonyR/PythonIntegrationBatch
# Decision Guide print("=== Choose Tool by Language ===") print(""" Python: โ†’ Scanpy โ†’ PAGA โ†’ scVelo โ†’ CellTypist R: โ†’ Seurat โ†’ Monocle โ†’ Slingshot โ†’ SingleR CLI: โ†’ CellRanger โ†’ STARsolo """) print("\n=== Choose Tool by Task ===") print(""" Alignment: โ†’ CellRanger โ†’ STARsolo QC: โ†’ Scanpy โ†’ Seurat Clustering: โ†’ Scanpy โ†’ Seurat Trajectory: โ†’ Monocle โ†’ PAGA โ†’ Slingshot โ†’ scVelo Annotation: โ†’ SingleR โ†’ CellTypist Integration: โ†’ Harmony โ†’ BBKNN โ†’ Scanorama """) print("\n=== Speed Comparison ===") print(f"{'Tool':<20} {'10k cells':<15} {'100k cells':<15} {'1M cells':<15}") print("-" * 65) print(f"{'Scanpy':<20} {'1 min':<15} {'10 min':<15} {'1 hour':<15}") print(f"{'Seurat':<20} {'2 min':<15} {'20 min':<15} {'2 hours':<15}") print(f"{'Monocle':<20} {'5 min':<15} {'1 hour':<15} {'10 hours':<15}") print("\n=== When to Use Which ===") print(""" USE CellRanger: โœ“ 10x alignment โœ“ Count matrix USE Scanpy: โœ“ Python โœ“ Comprehensive โœ“ Scalable USE Seurat: โœ“ R โœ“ Comprehensive โœ“ Integration USE Monocle: โœ“ Trajectory โœ“ Pseudotime USE SingleR: โœ“ Annotation โœ“ Reference USE Harmony: โœ“ Integration โœ“ Batch correction """)

โ“ FAQ

๐ŸŽฏ Frequently Asked Questions

Answers to common questions about single-cell RNA-seq.

What is single-cell RNA-seq?

Single-cell RNA sequencing (scRNA-seq) measures gene expression at the resolution of individual cells. Unlike bulk RNA-seq, which averages expression across thousands of cells, scRNA-seq reveals cellular heterogeneity, identifies rare cell types, and enables trajectory analysis.

What is the 10x Genomics platform?

10x Genomics Chromium is the most widely used droplet-based scRNA-seq platform. It encapsulates individual cells with barcoded beads in oil droplets, enabling thousands of cells to be profiled in a single run. CellRanger is the standard pipeline for processing 10x data.

What is the difference between Scanpy and Seurat?

Scanpy is a Python library for scRNA-seq analysis, while Seurat is an R package. Both provide comprehensive tools for QC, normalization, clustering, UMAP/t-SNE, marker gene detection, and visualization. Scanpy is preferred for Python users; Seurat for R users.

What is UMAP and how does it differ from t-SNE?

UMAP (Uniform Manifold Approximation and Projection) and t-SNE (t-distributed Stochastic Neighbor Embedding) are dimensionality reduction methods for visualization. UMAP is faster and better preserves global structure; t-SNE better preserves local structure. Both are commonly used in scRNA-seq.

What is trajectory analysis in scRNA-seq?

Trajectory analysis (pseudotime) infers developmental or differentiation paths from scRNA-seq data. It orders cells along a continuum of states, revealing transitions between cell types. Tools include Monocle, PAGA, Slingshot, and scVelo (RNA velocity).

What is a UMI?

A UMI (Unique Molecular Identifier) is a short random barcode attached to each mRNA molecule before amplification. UMIs allow counting of original mRNA molecules, reducing PCR bias and improving quantification accuracy.

What are doublets and how do I remove them?

Doublets occur when two cells are captured in the same droplet, creating artificial hybrid expression profiles. Tools like DoubletFinder, Scrublet, and Scrublet detect and remove doublets.

What is batch correction?

Batch correction removes technical variation between samples processed at different times or in different runs. Tools include Harmony, BBKNN, Scanorama, and Seurat integration.

How do I annotate cell types?

Annotate cell types using marker genes (manual) or automated tools like SingleR (reference-based) and CellTypist (machine learning). Always validate annotations with known markers and visualize on UMAP.

What is the best clustering resolution?

The optimal resolution depends on your biological question. Try multiple resolutions (0.4, 0.6, 0.8, 1.0) and choose the one that gives stable, biologically meaningful clusters validated by marker genes.

# Quick Reference print("=== Quick Answers ===") print(""" Q: What is scRNA-seq? A: Gene expression at single-cell resolution. Q: Best platform? A: 10x Genomics. Q: Best alignment? A: CellRanger. Q: Best Python tool? A: Scanpy. Q: Best R tool? A: Seurat. Q: QC thresholds? A: >200 genes, <20% MT. Q: Clustering? A: Leiden. Q: Visualization? A: UMAP, t-SNE. Q: Trajectory? A: Monocle, PAGA, scVelo. Q: Annotation? A: SingleR, CellTypist. Q: Integration? A: Harmony. Q: Free? A: Yes โ€” all major tools are free. """)

๐Ÿš€ Future

๐ŸŽฏ Where scRNA-seq Is Going

The future is spatial transcriptomics, multi-omics, single-cell ATAC, AI, clinical, and atlas-scale.

Future Directions

Spatial: Location. Multi-omics: RNA+ATAC+protein. AI: Prediction. Clinical: Diagnostics. Atlas: Millions. Single-cell: Multi-modal.

๐Ÿš€ Spatial๐Ÿš€ Multi-omics๐Ÿš€ AI๐Ÿš€ Clinical
# Future of scRNA-seq print("=== 1. Spatial Transcriptomics ===") print(""" Trend: Spatial Current: - Dissociated cells - No location Future: - Spatial - Location - Tissue context Examples: - Visium - MERFISH - Xenium - Slide-seq Future: - Spatial context - Microenvironment - Tissue architecture """) print("\n=== 2. Multi-Omics ===") print(""" Trend: Multi-omics Current: - RNA only Future: - RNA + ATAC - RNA + protein - RNA + methylation - Multi-modal Examples: - CITE-seq - Multiome - scNMT Future: - Integrated - Multi-modal - Systems """) print("\n=== 3. AI ===") print(""" Trend: AI + scRNA-seq Ideas: - Deep learning - Integration - Annotation - Prediction Examples: - scGPT - Geneformer - scBERT Future: - Foundation models - Better integration - Predictive """) print("\n=== 4. Clinical ===") print(""" Trend: Clinical Current: - Research Future: - Clinical - Diagnostics - Therapeutics Examples: - Cancer - Immunology - COVID-19 Future: - Clinical implementation - Precision - Equity """) print("\n=== 5. Atlas ===") print(""" Trend: Atlas-scale Current: - Thousands of cells Future: - Millions - Billions - Human Cell Atlas Examples: - HCA - Tabula - Brain Atlas Future: - Complete atlases - Reference - Integration """) print("\n=== 6. Single-Cell Multi-Modal ===") print(""" Trend: Multi-modal Current: - One modality Future: - RNA + ATAC + protein - Multi-modal - Single-cell Examples: - CITE-seq - Multiome - Perturb-seq Future: - Multi-modal - Integrated - Systems """) # TIMELINE print("\n=== Timeline ===") print(""" Past: 2009: First scRNA-seq 2015: Drop-seq 2016: 10x Genomics 2017: HCA 2019: Scanpy, Seurat v3 2020: COVID-19 Present: 2025: Spatial 2026: Multi-omics Future: 2030: AI 2035: Clinical 2040: Atlas? """) print("\n=== Final Thoughts ===") print(""" scRNA-seq is: - Transforming biology - Cellular resolution - Heterogeneity - Evolving The future is: - Spatial - Multi-omics - AI - Clinical - Atlas - Single-cell multi-modal "One cell at a time." Keep exploring. Keep building. """)