Analysis scripts and processed data for reproducing figures in:
Yeung, J., Tan, J., et al. (2026). Joint analysis of multiply perturbed cells improves statistical power and cost efficiency in Perturb-seq. bioRxiv. https://doi.org/10.64898/2026.07.10.737863
- Code (
scripts/,utils/,config.R): MIT License - Data (
data/): CC BY 4.0
- GEO accession (pilot & sublib2): GSE337988 — raw and processed data
- Replogle et al. (2022) reanalysis: raw data at GSE146194; processed DE matrices at Zenodo (10.5281/zenodo.21232999)
- Processed figure data: included in
data/(CSV files for all figure panels)
├── config.R # Central path configuration
├── data/ # Processed CSV data for all figure panels (~87 MB)
│ ├── fig1/ # Figure 1: guides per cell (pilot)
│ ├── fig1_sup/ # Sup Figure 1: sprinter interaction effects
│ ├── fig2/ # Figure 2: information loss + full vs marginal (pilot)
│ ├── fig2_sup/ # Sup Figure 2: DE method comparisons
│ ├── fig3/ # Figure 3: statistical power (pilot)
│ ├── fig4/ # Figure 4: sublib2 analysis
│ └── fig5/ # Figure 5: Replogle reanalysis
├── scripts/ # R scripts that generate each figure
│ ├── fig1/ # 4 scripts → Fig 1B-G, Sup S1F
│ ├── fig1_sup/ # 1 script → Sup S1D
│ ├── fig2/ # 2 scripts → Fig 2B-G, Sup S3A
│ ├── fig2_sup/ # 2 scripts → Sup S2A-E
│ ├── fig3/ # 1 script → Fig 3B-C, Sup S3B
│ ├── fig4/ # 4 scripts → Fig 4B-I, Sup S4A-E
│ └── fig5/ # 3 scripts → Fig 5B-H, Sup S5A-D
└── utils/
├── crop_utils.R # Plotting, info imbalance, SPRINTER screening
├── rms_cosine_theory.R # Theoretical cosine similarity functions
└── sc_limma_voom.R # Single-cell limma-voom (RunScLimmaVoom, scVoom)
The data/ directory contains all processed CSV files needed to recreate every figure panel. Each CSV corresponds to a specific panel as documented in FIGURE_PANEL_DATA_MAP.md and SUPFIGURE_PANEL_DATA_MAP.md.
The scripts in scripts/ contain the complete analysis code that generates both the figures and the underlying CSV data from processed single-cell objects. To re-run the full pipeline:
- Edit
config.Rto setDATA_ROOT_GSTOREandDATA_ROOT_SCRATCHto your local data paths - Ensure R dependencies are installed (see below)
- Run individual scripts:
Rscript scripts/fig1/00-show_nguides_across_MOI.R
CRAN/Bioconductor packages:
dplyr,tidyr,ggplot2,data.table,Matrix,argparseggrepel,ggrastr,lsa,viridis,pheatmap,ComplexHeatmapSingleCellExperiment,SummarizedExperimentlimma,edgeR,scran,scrapperFNN,ggrepel,ggrastr,parallel,scales
For differential expression we use RunScLimmaVoom (provided in utils/sc_limma_voom.R), a limma-voom variant that replaces the standard lowess mean-variance trend with a robust regularized loess fit via scrapper::fitVarianceTrend and uses scran size factors instead of CPM normalization. Additional utility functions are provided in utils/crop_utils.R (scatter plots, information imbalance, SPRINTER interaction screening).
All dependencies are available from CRAN or Bioconductor.
| Figure | Panels | Script |
|---|---|---|
| Fig 1 | B, C, D | scripts/fig1/00-show_nguides_across_MOI.R |
| Fig 1 | E, F | scripts/fig1/2-downstream_limma_full_covar_with_heatmap.R |
| Fig 1 | G | scripts/fig1/extract_go_msigdb_csv_from_rds.R |
| Fig 2 | B, C | scripts/fig2/1-compare_full_regression_vs_marginal_with_barplots.R |
| Fig 2 | D, E, G | scripts/fig2/10-calculate_information_loss_pilot_cleaned.R |
| Fig 3 | B, C | scripts/fig3/20-calculate_statistical_power_pilot.R |
| Fig 4 | B | scripts/fig4/00-nguides_by_MOI.R |
| Fig 4 | C | scripts/fig4/10-calculate_information_loss_sublib2.R |
| Fig 4 | D, E, F | scripts/fig4/20-calculate_statistical_power_sublib2.R |
| Fig 4 | G, H, I | scripts/fig4/30-calculate_SNR_vs_cosine_similarity_sublib2.R |
| Fig 5 | B, C | scripts/fig5/00-show_nguides_in_Replogle.R |
| Fig 5 | D-H | scripts/fig5/20-calculate_statistical_power_Replogle_top_3000.R |
| Sup S1 | A, B, C | scripts/fig1/3-correlate_residuals_sprinter_limma_spline.R |
| Sup S1 | D | scripts/fig1_sup/3-correlate_residuals_sprinter_limma_spline_refit_top_covar_check_LFCs.R |
| Sup S1 | F | scripts/fig1/00-show_nguides_across_MOI.R |
| Sup S2 | A | scripts/fig2/1-compare_full_regression_vs_marginal_with_barplots.R |
| Sup S2 | B, E | scripts/fig2_sup/4-compare_LimmaVoom_vs_other_methods_by_MOI.R |
| Sup S2 | C, D | scripts/fig2_sup/4-FRPerturb_and_Othersdownstream_2026.R |
| Sup S3 | A | scripts/fig2/10-calculate_information_loss_pilot_cleaned.R |
| Sup S3 | B | scripts/fig3/20-calculate_statistical_power_pilot.R |
| Sup S4 | A, B, C | scripts/fig4/00-nguides_by_MOI.R |
| Sup S4 | D, E | scripts/fig4/30-calculate_SNR_vs_cosine_similarity_sublib2.R |
| Sup S5 | A, B, C | scripts/fig5/20-calculate_statistical_power_Replogle_top_3000.R |
| Sup S5 | D | scripts/fig5/00-ntargets_by_perturbation_replogle.R |
Panels 1A, 2A, 2F, 3A, 4A, 5A are schematics created in Adobe Illustrator (no script).
- perturbmatch package: https://github.com/Genentech/perturbmatch -- the standalone R package for propensity-score matching in high-MOI Perturb-seq experiments.