Single-cell RNA-seq analysis of human peripheral blood mononuclear cells (PBMCs) using scanpy. The repository holds the full downstream workflow: quality control, normalisation, feature selection, dimensionality reduction, Leiden clustering, marker-gene testing, and annotation of clusters to cell types.
PBMCs are a standard benchmark for single-cell workflows because the expected populations are known, which makes them a good system for checking that a pipeline recovers the right biology rather than just producing clusters. The workflow follows the established scanpy PBMC analysis pattern, with the QC thresholds and marker panel set out explicitly below.
| Cells before / after QC filtering | fill in |
| Genes retained after filtering | fill in |
| Highly variable genes selected | fill in |
| Leiden clusters identified | fill in |
| Cell types annotated | CD4+ T, CD8+ T, B, NK, monocytes, dendritic cells, platelets |
| Largest population | CD4+ T cells |
The dominant population is CD4+ T cells, which is what a healthy PBMC sample should give: T cells typically make up the majority of mononuclear cells in peripheral blood, with monocytes, B cells and NK cells forming smaller fractions and dendritic cells and platelets rarer still. Recovering that composition is the main sanity check on the pipeline.
Quality control. Cells with fewer than 200 detected genes and genes present in fewer than 3 cells are removed. Cells are then filtered on two QC metrics: fewer than 2,500 detected genes, and under 5 per cent mitochondrial counts. The upper gene threshold removes likely doublets, and the mitochondrial cutoff removes stressed or dying cells whose transcriptome is dominated by mitochondrial reads.
Normalisation. Counts are normalised per cell to 10,000 and log1p-transformed, so that clustering reflects expression profile rather than sequencing depth.
Feature selection. Highly variable genes are selected (min_mean=0.0125, max_mean=3,
min_disp=0.5) and the data scaled to a maximum of 10. Restricting to variable genes focuses the
structure on biological variation and reduces noise from uniformly expressed genes.
Dimensionality reduction and clustering. PCA (arpack), then a neighbourhood graph over 40
principal components with 10 neighbours, then UMAP for visualisation and Leiden for clustering.
Marker genes and annotation. Cluster markers are ranked with rank_genes_groups, then clusters
are annotated using a canonical PBMC marker panel:
| Cell type | Marker |
|---|---|
| T cells | CD3D |
| B cells | MS4A1 |
| NK cells | GNLY |
| Monocytes | CD14, LYZ |
| Dendritic cells | FCER1A |
| Platelets | PPBP |
Annotation is done by inspecting a dot plot of these markers across clusters and assigning each cluster to the type whose markers it expresses, rather than relying on an automated label transfer.
data/
preprocessing.py full analysis script (QC through annotation)
pbmc_preprocessed.h5ad input AnnData object
fig/ output figures
conda create -n pbmc python=3.11
conda activate pbmc
pip install scanpy anndata matplotlib pandas leidenalg
python data/preprocessing.pyThe input path is set at the top of preprocessing.py.
- Cluster-to-cell-type assignment is manual and based on a small canonical marker panel, so rare or transitional populations may be merged into larger clusters.
- Marker testing uses a t-test; a rank-based test such as Wilcoxon is generally more robust for single-cell count data and would be the natural next step.
- QC thresholds are the commonly used defaults for PBMC data rather than values tuned to this dataset, and would need revisiting for a different tissue or chemistry.
Packaging the workflow so it runs end to end from a config file, and replacing manual annotation with a reproducible, scripted assignment step.