Skip to main content

    Scanpy on the platform

    Single-cell RNA-seq analysis with Scanpy for preprocessing, clustering, and trajectory inference.

    scanpy

    Scanpy takes single-cell RNA-seq data from raw counts to annotated cell types and marker genes — the classical, fast, interpretable path through quality control, clustering, differential expression, and trajectory inference. Reach for it as your default for single-cell analysis when speed and interpretability matter and you don't have heavy batch effects to correct. When you do — multiple samples to integrate, or unknown cell types to annotate — pair it with scvi-tools, whose deep generative models plug into the same AnnData object. See what you can achieve for the full set.

    Scanpy single-cell analysis on the platform

    Scanpy is a scalable toolkit for analyzing single-cell gene expression data, built on top of the AnnData data structure. Through the platform, you can run comprehensive scRNA-seq workflows from raw counts to publication-ready visualizations -- including quality control, normalization, dimensionality reduction, clustering, differential expression, and trajectory inference.

    Scanpy is the most widely used Python framework for single-cell analysis, with native support for datasets ranging from a few hundred cells to millions. It integrates tightly with the broader scverse ecosystem (scvi-tools, squidpy, muon) for advanced modeling tasks.

    Citations

    Wolf FA, Angerer P, Theis FJ. SCANPY: large-scale single-cell gene expression data analysis. Genome Biology. 2018;19:15. doi: 10.1186/s13059-017-1382-0

    How the platform runs Scanpy

    The platform runs Scanpy as a GPU-accelerated job on rapids-singlecell (cuML, cuGraph, cupy on a T4 GPU), which speeds up PCA, k-NN, UMAP, and Leiden relative to the CPU-only open-source package. You supply an AnnData .h5ad file (S3 URI or HTTPS URL) and choose one workflow:

    • full (default) — the complete pipeline: QC → normalize → highly variable genes → PCA → neighbors → UMAP → Leiden → differential expression.
    • qc — quality control and filtering only.
    • clustering — QC through Leiden and UMAP, without marker genes.
    • de — differential expression / marker genes.

    Beyond these four GPU workflows, the tool exposes CPU-based extension workflows for batch correction (harmony_integrate, scanorama_integrate, combat_correct), automated annotation (celltypist_annotate), gene-set and marker scoring (aucell_score, cosg_markers, hotspot_modules), stemness (cytotrace2_potency), and RNA velocity (scvelo_velocity).

    The sections below describe the underlying Scanpy methods in depth — the platform pipeline follows this same sequence, with GPU-accelerated implementations of the compute-heavy steps.

    The platform's Scanpy job focuses on the QC-to-clustering-to-markers path plus scverse extensions. Niche standalone workflows (trajectory inference, GRN, spatial clustering, cellxgene search) are handled by dedicated tools rather than this job — the trajectory and PAGA material below is background on the method, not a workflow you select here.

    Technical approach

    The AnnData object model

    Scanpy operates on the AnnData (Annotated Data) object, which stores all information for a single-cell experiment in a structured format:

    SlotContentsExample
    XExpression matrix (cells x genes)Raw counts or normalized values
    obsCell-level metadata (one row per cell)Sample ID, batch, cell type labels
    varGene-level metadata (one row per gene)Gene symbols, highly variable flags
    obsmCell embeddings (multi-dimensional)PCA coordinates, UMAP coordinates
    obspCell-cell graphsNearest-neighbor connectivity matrix
    unsUnstructured metadataClustering parameters, color palettes
    layersAlternative expression matricesRaw counts, spliced/unspliced (for RNA velocity)

    This design means a single .h5ad file captures the entire analysis state -- raw data, processed matrices, embeddings, cluster assignments, and metadata -- making results fully reproducible.

    Preprocessing pipeline

    Scanpy's standard preprocessing workflow follows a well-established sequence:

    1. Quality control and filtering

    • Filter cells by minimum gene count (default: 200 genes) to remove empty droplets
    • Filter genes by minimum cell count (default: 3 cells) to remove uninformative genes
    • Calculate mitochondrial gene percentages and filter cells above a threshold (default: 20%) to remove dying cells
    • Optionally filter doublets using scrublet scores

    2. Normalization

    • Library-size normalization (sc.pp.normalize_total): Scale each cell to a target sum (typically 10,000) so that expression values are comparable across cells with different sequencing depths
    • Log transformation (sc.pp.log1p): Apply log(1+x) to stabilize variance and make the data more normally distributed
    • Store raw counts in adata.layers['counts'] before normalization for differential expression

    3. Highly variable gene (HVG) selection

    • Identify genes with high cell-to-cell variation using sc.pp.highly_variable_genes
    • Typically select 2,000-5,000 HVGs to focus downstream analysis on informative genes
    • Methods: seurat (default), seurat_v3 (for raw counts), or cell_ranger
    • HVG selection dramatically reduces dimensionality and noise without losing biological signal

    4. Scaling

    • Center and scale expression values to zero mean and unit variance (sc.pp.scale)
    • Optionally clip extreme values (e.g., max_value=10) to limit the influence of outliers

    Dimensionality reduction

    Scanpy implements a two-stage dimensionality reduction approach:

    PCA (Principal Component Analysis)

    • Reduces the HVG expression matrix from ~2,000 dimensions to 50 principal components
    • Captures the major axes of biological variation
    • The number of informative PCs can be assessed with an elbow plot (sc.pl.pca_variance_ratio)
    • Typically 30-50 PCs are used for downstream steps

    Neighbor graph construction

    • Builds a k-nearest neighbor (kNN) graph in PCA space using sc.pp.neighbors
    • Default: 15 neighbors, Euclidean distance in PCA space
    • This graph is the foundation for both clustering and visualization

    UMAP and t-SNE

    • UMAP (sc.tl.umap): Produces a 2D embedding that preserves both local and global structure. Preferred for most applications. Key parameters: min_dist (compactness, default 0.5) and spread (default 1.0)
    • t-SNE (sc.tl.tsne): Produces a 2D embedding optimized for local structure. Better for visually separating tight clusters, but does not preserve global distances. Key parameter: perplexity (default 30)

    UMAP is generally recommended over t-SNE for exploratory analysis because it runs faster, scales better, and preserves more global structure. Use t-SNE when you need to emphasize local cluster separation for publication figures.

    Clustering

    Scanpy implements graph-based community detection algorithms:

    Leiden algorithm (sc.tl.leiden)

    • Preferred method -- produces well-connected communities with a quality guarantee
    • The resolution parameter controls cluster granularity: lower values (0.1-0.5) yield fewer, larger clusters; higher values (1.0-2.0) yield more, smaller clusters
    • Default resolution: 1.0
    • Operates on the kNN graph constructed during neighbor computation

    Louvain algorithm (sc.tl.louvain)

    • Older alternative to Leiden -- faster but can produce poorly connected communities
    • Same resolution parameter semantics as Leiden
    • Generally recommended to use Leiden instead unless backward compatibility is needed

    Choosing resolution: Start with the default (1.0) and adjust based on biological expectations. Over-clustering is generally preferable to under-clustering -- you can always merge clusters, but splitting them requires re-running.

    Differential expression

    Scanpy identifies marker genes for each cluster using sc.tl.rank_genes_groups:

    MethodDescriptionBest For
    wilcoxonWilcoxon rank-sum test (default)Most applications; robust to non-normality
    t-testWelch's t-testNormally distributed data, fast
    t-test_overestim_vart-test with overestimated varianceConservative, fewer false positives
    logregLogistic regressionMulti-class marker selection

    Results include log fold change, p-values, and adjusted p-values (Benjamini-Hochberg). Use the top-ranked genes per cluster to annotate cell types by cross-referencing with known marker databases (CellMarker, PanglaoDB).

    Trajectory inference

    Scanpy supports pseudotime and lineage analysis through several approaches:

    • Diffusion pseudotime (sc.tl.dpt): Computes pseudotime ordering based on diffusion distances in the neighbor graph. Requires specifying a root cell (typically the most undifferentiated population).
    • PAGA (sc.tl.paga): Partition-based graph abstraction. Creates a coarse-grained graph of cluster connectivity, useful for identifying differentiation trajectories and transitions between cell states.
    • RNA velocity (via scVelo): Not built into Scanpy but integrates seamlessly. Uses spliced/unspliced RNA ratios to infer the direction of cell state transitions.

    When to use Scanpy

    Primary applications

    • scRNA-seq quality control and analysis: The core use case. From raw 10X Genomics or Smart-seq2 data through to annotated cell types and marker genes.
    • Spatial transcriptomics preprocessing: Scanpy handles the expression matrix for spatial technologies (Visium, MERFISH, Slide-seq). Use squidpy for spatial-specific analyses on top.
    • Atlas-scale integration: With backed mode (sc.read_h5ad(backed='r')), Scanpy can handle datasets with millions of cells without loading the full matrix into memory.
    • Comparative analysis: Compare cell populations across conditions, treatments, or time points using differential expression and composition analysis.
    • Cell type annotation: Combine clustering with marker gene analysis and reference-based annotation (e.g., via Celltypist or manual curation).

    Comparison with Seurat

    Seurat is the primary R-based alternative to Scanpy. Key differences:

    AspectScanpy (Python)Seurat (R)
    LanguagePythonR
    Data structureAnnData (.h5ad)Seurat object (.rds)
    ScalabilityBetter for large datasets (>500K cells) via backed modeMemory-limited; requires Seurat v5 disk-backed for large data
    Ecosystemscverse (scvi-tools, squidpy, muon)Signac (ATAC-seq), Azimuth (reference mapping)
    Integration methodsHarmony, BBKNN, scVI (via scvi-tools)CCA, RPCA, Harmony
    VisualizationMatplotlib-based (customizable but verbose)ggplot2-based (publication-ready defaults)
    CommunityLarger in computational biology / MLLarger in experimental biology / clinical

    Both frameworks produce comparable results for standard workflows. Choose based on your language preference and downstream ecosystem needs. Results can be converted between formats using anndata2ri or SeuratDisk.

    Limitations

    • Memory-intensive for large datasets: Datasets above 500,000 cells require careful memory management. Use backed mode, sparse matrices, and chunked processing. For datasets above 2 million cells, consider subsampling or using geometric sketching before full analysis.
    • Limited built-in batch correction: Scanpy's native batch correction (sc.pp.combat) is basic. For multi-sample integration, use scVI-tools (scvi.model.SCVI), Harmony (sc.external.pp.harmony_integrate), or BBKNN (sc.external.pp.bbknn) -- all of which integrate with Scanpy but are separate packages.
    • CPU-only for extension workflows: On the platform, the core workflows (full, qc, clustering, de) run GPU-accelerated via rapids-singlecell, but the batch-correction, annotation, and scoring extensions (Harmony, Scanorama, ComBat, CellTypist, AUCell, COSG, Hotspot, CytoTrace2, scVelo) run on CPU. Upstream open-source Scanpy is CPU-only; rapids-singlecell is the GPU-backed drop-in the platform uses.
    • No built-in multi-modal analysis: For combined scRNA-seq + scATAC-seq or CITE-seq, use muon (part of scverse) which extends AnnData to multi-modal data.
    • Trajectory inference is basic: Scanpy's diffusion pseudotime and PAGA are useful for simple trajectories, but complex branching lineages are better handled by CellRank or scVelo.

    Integration with scVI-tools

    scVI-tools provides deep generative models that complement Scanpy's preprocessing:

    • scVI: Variational autoencoder for dimensionality reduction, batch correction, and differential expression. Produces a latent space that replaces PCA for downstream clustering and visualization.
    • scANVI: Semi-supervised variant of scVI that uses reference cell type labels for annotation transfer.
    • SOLO: Doublet detection using a variational autoencoder.
    • totalVI: Joint modeling of RNA and protein (CITE-seq) data.

    The typical workflow is: preprocess with Scanpy (QC, filtering, normalization) then train a scVI model for batch-corrected embeddings and differential expression. The scVI latent space can be stored in adata.obsm['X_scVI'] and used directly with Scanpy's neighbor graph and clustering functions.

    Integration with the platform ecosystem

    • Upstream: Load data from 10X Genomics, Smart-seq2, or other platforms
    • Downstream: Feed results to scVI-tools for advanced modeling, target validation pipelines for cell-type-specific target expression

    Chat Usage

    Example Prompts

    • "Run Scanpy full pipeline on this H5AD file"
    • "Cluster these single-cell data with Leiden resolution 0.5"
    • "Run QC and normalize my scRNA-seq dataset, then find marker genes"
    • "Compute UMAP and identify differentially expressed genes per cluster"
    • "Run trajectory analysis with diffusion pseudotime on my preprocessed data"

    Workflow Chaining

    • Feeds into: Target validation (cell types expressing your target), scVI-tools (probabilistic modeling), differential expression analysis
    • Accepts from: AnnData .h5ad files (uploaded, or produced upstream). Convert 10X Cell Ranger output or CSV matrices to .h5ad before submitting — the job reads .h5ad only.

    Was this page helpful?

    Loading...