archr

$npx mdskill add swaruplab/operon/archr

Analyze single-cell ATAC-seq data using the mature ArchR R pipeline.

  • Process scATAC-seq fragments into Arrow files for scalable analysis.
  • Depends on R, ArchR, MACS2, and optional Monocle3/Slingshot.
  • Uses iterative LSI, Harmony, and doublet inference for clustering.
  • Outputs peak calls, motif enrichments, trajectories, and interactive browser.

SKILL.md

.github/skills/archrView on GitHub ↗
---
name: archr
description: Single-cell ATAC-seq analysis with ArchR (R). The mature R-based scATAC pipeline — Arrow files, doublet inference, iterative LSI + Harmony, clustering, gene scores, MACS2 peak calling, motif enrichment, chromVAR deviations, footprinting, scRNA-seq integration (label transfer), trajectory analysis (built-in + Monocle3 + Slingshot), and ArchR's interactive genome browser. Sister protocol to snapatac2 — pick this for established R workflows.
license: MIT
metadata:
---

# ArchR: scATAC-seq Analysis in R

## Overview

[ArchR](https://www.archrproject.com/) is the mature R-based pipeline for scATAC-seq analysis. It uses an on-disk **Arrow file** format (HDF5-based, indexed by barcode) so it scales to hundreds of thousands of cells on modest hardware. The `ArchRProject` object is a thin reference to one or more Arrow files plus all derived data (matrices, embeddings, peaks, motif enrichments).

The full pipeline branches like this:

```
Fragments / BAM
   ↓
Arrow files  ←  doublet inference (LSI-based, knn-method)
   ↓
ArchRProject
   ↓
Iterative LSI (+ Harmony) → clusters → UMAP / tSNE
   ↓
Gene scores (TileMatrix + GeneScoreMatrix) → marker genes → label transfer from scRNA-seq
   ↓
Pseudo-bulk replicates → MACS2 peak calling per cluster → reproducible peak set → PeakMatrix
   ↓
Marker peaks → motif enrichment → chromVAR deviations → TF footprinting
   ↓
Trajectories (built-in / Monocle3 / Slingshot), Peak2GeneLinkage, positive TF regulators
```

ArchR overlaps heavily with [SnapATAC2](../snapatac2/SKILL.md) in scope. **When to choose ArchR**: established R-based labs, downstream ecosystem in R (Seurat, Bioconductor), need for built-in motif / chromVAR / footprinting in one package. **When to choose SnapATAC2**: Python ecosystem, atlas-scale (millions of cells), tighter scverse integration.

## When to Use This Skill

- Standard scATAC analysis: fragment → cells → clusters → peaks
- Integrating scATAC with scRNA-seq via cross-platform CCA (`addGeneIntegrationMatrix`)
- Motif enrichment + chromVAR deviations + TF footprinting all in one place
- Trajectory analysis on chromatin accessibility (built-in or Monocle3/Slingshot)
- Multiome (paired ATAC + RNA) analysis
- Bulk ATAC projection onto a single-cell embedding

**Not for**: extremely large atlases (≥ 1M cells — ArchR is heavy here; switch to SnapATAC2); CUT&Tag / CUT&RUN (use specialised tools); spatial ATAC (use spatial-transcriptomics protocol with ATAC adaptations).

## Prerequisites

- R ≥ 4.0 (4.2+ recommended)
- Bioconductor + many deps; budget for a long initial install
- ~64 GB RAM recommended for ~100k cells; ~256 GB for ~500k+
- Linux/macOS strongly preferred (Windows works for analysis but Arrow-file creation is slow)

```r
# Install from CRAN/BioC + ArchR's installer
install.packages("devtools")
devtools::install_github("GreenleafLab/ArchR", ref = "master", repos = BiocManager::repositories())
library(ArchR)
ArchR::installExtraPackages()      # MACS2, chromVAR, motifmatchr, etc.
```

For multiomic ATAC+RNA: also need `Seurat` and a working `cellranger-arc` (or 10X multiome) preprocessing pipeline.

## Quick Start — Full Pipeline

```r
library(ArchR)
set.seed(1)
addArchRThreads(threads = 16)        # adjust to your machine
addArchRGenome("hg38")                # or "mm10", "hg19"

# ── 1. Create Arrow files from fragment files ───────────────────────────────
# Fragment files: typically cellranger-atac output (fragments.tsv.gz + .tbi)
inputFiles <- c(
  "donor1" = "/data/donor1/fragments.tsv.gz",
  "donor2" = "/data/donor2/fragments.tsv.gz"
)

ArrowFiles <- createArrowFiles(
  inputFiles      = inputFiles,
  sampleNames     = names(inputFiles),
  filterTSS       = 4,               # TSS enrichment cutoff — raise for stringent QC
  filterFrags     = 1000,            # min fragments per cell
  addTileMat      = TRUE,            # build the bin matrix (default 500 bp)
  addGeneScoreMat = TRUE,            # build gene scores from accessibility
  threads         = 16
)

# ── 2. Doublet detection ────────────────────────────────────────────────────
doubScores <- addDoubletScores(
  input      = ArrowFiles,
  k          = 10,                   # KNN for doublet score
  knnMethod  = "UMAP",
  LSIMethod  = 1
)

# ── 3. Create the project ───────────────────────────────────────────────────
proj <- ArchRProject(
  ArrowFiles      = ArrowFiles,
  outputDirectory = "ATAC_analysis",
  copyArrows      = TRUE             # copies arrows into outputDirectory — safe
)
proj <- filterDoublets(ArchRProj = proj)

# Inspect what matrices exist
getAvailableMatrices(proj)
# "TileMatrix", "GeneScoreMatrix"

# ── 4. Dimensionality reduction + clustering ────────────────────────────────
proj <- addIterativeLSI(
  ArchRProj  = proj,
  useMatrix  = "TileMatrix",
  name       = "IterativeLSI",
  iterations = 2,
  clusterParams = list(resolution = c(0.2), sampleCells = 10000, n.start = 10),
  varFeatures = 25000,
  dimsToUse   = 1:30
)

# (Multi-sample: add Harmony batch correction)
proj <- addHarmony(
  ArchRProj   = proj,
  reducedDims = "IterativeLSI",
  name        = "Harmony",
  groupBy     = "Sample"
)

proj <- addClusters(input = proj, reducedDims = "Harmony", name = "Clusters",
                     resolution = 0.8)
proj <- addUMAP(ArchRProj = proj, reducedDims = "Harmony", name = "UMAP")

# Save & visualize
proj <- saveArchRProject(ArchRProj = proj)
p1 <- plotEmbedding(ArchRProj = proj, colorBy = "cellColData",
                     name = "Sample",   embedding = "UMAP")
p2 <- plotEmbedding(ArchRProj = proj, colorBy = "cellColData",
                     name = "Clusters", embedding = "UMAP")
plotPDF(p1, p2, name = "UMAP-Sample-Clusters.pdf",
        ArchRProj = proj, addDOC = FALSE, width = 5, height = 5)

# ── 5. Gene scores + marker genes ───────────────────────────────────────────
proj <- addImputeWeights(proj)                  # MAGIC-style smoothing for plots

markerGenes <- c("CD3D", "CD3E", "MS4A1", "CD14", "LYZ", "NKG7", "FCGR3A")
p <- plotEmbedding(
  ArchRProj      = proj,
  colorBy        = "GeneScoreMatrix",
  name           = markerGenes,
  embedding      = "UMAP",
  imputeWeights  = getImputeWeights(proj)
)
plotPDF(plotList = p, name = "UMAP-Marker-Genes-Imputed.pdf",
        ArchRProj = proj, addDOC = FALSE, width = 5, height = 5)

# ── 6. Browser-style track plots ────────────────────────────────────────────
p <- plotBrowserTrack(
  ArchRProj  = proj,
  groupBy    = "Clusters",
  geneSymbol = markerGenes,
  upstream   = 50000,
  downstream = 50000
)
plotPDF(plotList = p, name = "Tracks-Marker-Genes.pdf",
        ArchRProj = proj, addDOC = FALSE, width = 5, height = 5)

# Interactive (for exploratory sessions only)
# ArchRBrowser(ArchRProj = proj)

# ── 7. Peak calling (requires MACS2) ────────────────────────────────────────
# Pseudo-bulk replicates per cluster so MACS2 has enough reads
proj <- addGroupCoverages(ArchRProj = proj, groupBy = "Clusters")

# Reproducible peak set across replicates
proj <- addReproduciblePeakSet(
  ArchRProj = proj,
  groupBy   = "Clusters",
  pathToMacs2 = findMacs2(),
  threads   = 16
)

# Add peak matrix (cells × peaks)
proj <- addPeakMatrix(ArchRProj = proj)
getAvailableMatrices(proj)
# Now includes "PeakMatrix"

# ── 8. Marker peaks per cluster ─────────────────────────────────────────────
markersPeaks <- getMarkerFeatures(
  ArchRProj   = proj,
  useMatrix   = "PeakMatrix",
  groupBy     = "Clusters",
  bias        = c("TSSEnrichment", "log10(nFrags)"),
  testMethod  = "wilcoxon"
)

# Extract significant marker peaks per cluster
markerList <- getMarkers(markersPeaks, cutOff = "FDR <= 0.01 & Log2FC >= 1")
markerList$C1   # top peaks for cluster C1

# ── 9. Motif enrichment ─────────────────────────────────────────────────────
proj <- addMotifAnnotations(
  ArchRProj = proj,
  motifSet  = "cisbp",                          # or "JASPAR2020", "homer"
  name      = "Motif"
)

enrichMotifs <- peakAnnoEnrichment(
  seMarker  = markersPeaks,
  ArchRProj = proj,
  peakAnnotation = "Motif",
  cutOff    = "FDR <= 0.01 & Log2FC >= 1"
)

# Heatmap of motif enrichment across clusters
heatmapEM <- plotEnrichHeatmap(enrichMotifs, n = 7, transpose = TRUE)
plotPDF(heatmapEM, name = "Motifs-Enriched-Marker-Heatmap.pdf",
        ArchRProj = proj, addDOC = FALSE, width = 8, height = 6)

# ── 10. chromVAR deviations ─────────────────────────────────────────────────
# Per-cell motif activity scores
proj <- addBgdPeaks(proj)
proj <- addDeviationsMatrix(
  ArchRProj      = proj,
  peakAnnotation = "Motif",
  force          = TRUE
)

# Plot per-cell deviation z-scores for top TFs
p <- plotEmbedding(
  ArchRProj    = proj,
  colorBy      = "MotifMatrix",
  name         = c("z:GATA1_1", "z:CEBPA_4", "z:PAX5_1"),
  embedding    = "UMAP",
  imputeWeights = getImputeWeights(proj)
)
plotPDF(plotList = p, name = "TF-Deviation-Scores.pdf",
        ArchRProj = proj, addDOC = FALSE, width = 5, height = 5)

# Save
proj <- saveArchRProject(ArchRProj = proj)
```

Convenience: `Rscript scripts/build_archr.R --fragments samples.txt --genome hg38 --out ATAC_analysis`. See [references/peaks_motifs.md](references/peaks_motifs.md) for peak / motif / footprinting depth; [references/integration.md](references/integration.md) for scRNA-seq integration + multiome + trajectories.

---

## scRNA-seq Integration

If you have a paired or unpaired scRNA-seq dataset with cell-type labels, ArchR can transfer those labels to the ATAC cells using Seurat's CCA.

```r
# Load the scRNA-seq Seurat object
seRNA <- readRDS("rna_reference.rds")    # must contain cell type labels in @meta.data$cell_type

# Cross-platform alignment + label transfer
proj <- addGeneIntegrationMatrix(
  ArchRProj         = proj,
  useMatrix         = "GeneScoreMatrix",
  matrixName        = "GeneIntegrationMatrix",
  reducedDims       = "Harmony",
  seRNA             = seRNA,
  addToArrow        = TRUE,
  groupRNA          = "cell_type",
  nameCell          = "predictedCell",
  nameGroup         = "predictedGroup",
  nameScore         = "predictedScore",
  threads           = 16
)

# Plot the predicted cell types on UMAP
p <- plotEmbedding(
  ArchRProj = proj,
  colorBy   = "cellColData",
  name      = "predictedGroup",
  embedding = "UMAP"
)
plotPDF(p, name = "UMAP-Predicted-CellType.pdf",
        ArchRProj = proj, addDOC = FALSE, width = 6, height = 5)
```

`addGeneIntegrationMatrix` writes the integrated matrix into the Arrow files (`addToArrow = TRUE`) so it persists across sessions.

---

## Multiome (paired ATAC + RNA)

If using 10X multiome (one assay per cell), ArchR handles both modalities through the same project:

```r
proj <- ArchRProject(
  ArrowFiles      = ArrowFiles,         # from multiome ATAC fragments
  outputDirectory = "Multiome_analysis"
)

# Add the RNA matrix from cellranger-arc output
rna_se <- import10xFeatureMatrix(
  input = "filtered_feature_bc_matrix.h5",
  names = "donor1"
)
proj <- addGeneExpressionMatrix(
  input  = proj,
  seRNA  = rna_se,
  threads = 16
)

# Joint LSI: combine ATAC + RNA into one embedding
proj <- addIterativeLSI(
  ArchRProj  = proj,
  useMatrix  = "GeneExpressionMatrix",
  name       = "LSI_RNA",
  varFeatures = 2500,
  dimsToUse  = 1:30
)
proj <- addCombinedDims(
  proj,
  reducedDims = c("IterativeLSI", "LSI_RNA"),
  name        = "LSI_Combined"
)
proj <- addUMAP(proj, reducedDims = "LSI_Combined", name = "UMAP_Combined")
proj <- addClusters(proj, reducedDims = "LSI_Combined", name = "JointClusters",
                     resolution = 0.8)
```

---

## Trajectory Analysis

ArchR's built-in trajectory implementation, taking a list of cluster labels in order:

```r
trajectory <- c("Naive_T", "Memory_T", "Effector_T")   # cluster identities along the path
proj <- addTrajectory(
  ArchRProj  = proj,
  name       = "T_cell_trajectory",
  groupBy    = "Clusters",
  trajectory = trajectory,
  embedding  = "UMAP"
)

# Visualize
p <- plotTrajectory(
  ArchRProj = proj,
  trajectory = "T_cell_trajectory",
  colorBy    = "cellColData",
  name       = "T_cell_trajectory",
  embedding  = "UMAP"
)
plotPDF(p, name = "Trajectory.pdf",
        ArchRProj = proj, addDOC = FALSE, width = 6, height = 5)

# Gene scores or motif deviations along pseudotime
trajGSM <- getTrajectory(
  ArchRProj  = proj,
  name       = "T_cell_trajectory",
  useMatrix  = "GeneScoreMatrix",
  log2Norm   = TRUE
)
heatmap <- plotTrajectoryHeatmap(trajGSM, varCutOff = 0.95)
plotPDF(heatmap, name = "Trajectory-GeneScores.pdf",
        ArchRProj = proj, addDOC = FALSE, width = 6, height = 8)
```

Alternative trajectory backends: `addMonocleTrajectory()`, `addSlingShotTrajectories()`.

---

## Key Parameters to Adjust

### `createArrowFiles`
- `filterTSS` (default 4) — TSS enrichment cutoff. Raise to 7-10 for stringent (fresh PBMC); keep at 4 for nuclei / tissue.
- `filterFrags` (default 1000) — min fragments. Lower for shallow libraries.
- `minFrags` / `maxFrags` — hard bounds on per-cell fragment count.

### `addIterativeLSI`
- `iterations` (default 2) — number of LSI re-runs (each refines the variable feature set).
- `varFeatures` (default 25000) — variable bins kept after the first iteration.
- `dimsToUse` (default 1:30) — LSI components to retain. Drop dim 1 if it correlates with depth (`corCutOff = 0.75` auto-drops).

### `addHarmony`
- Always include `groupBy = "Sample"` (or the appropriate batch column).
- `corCutOff = 0.75` — drops components correlated with depth before correcting.

### Peak calling
- `addReproduciblePeakSet(reproducibility = "(n+1)/2")` — require peaks in majority of replicates per group.
- Increase `pseudoBulkN` (default 500 cells per pseudo-bulk) for clusters with > 5000 cells.

---

## Best Practices

- **Allocate enough threads.** `addArchRThreads(threads = 16)` early. Most ArchR functions parallelize per-Arrow-file.
- **Save the project often.** `saveArchRProject(proj)` between every major step. ArchR analyses are long; losing state hurts.
- **Use the disk-backed Arrow format.** Don't subset the project in-memory — call `subsetArchRProject()` to create a new project directory.
- **Inspect `getCellColData(proj)` after each major step.** All per-cell metadata accumulates there — useful for sanity-checking column additions.
- **`addImputeWeights` is for plots only.** Don't run downstream analyses on imputed values — they're a visualization smoothing trick.
- **Marker peaks need `bias = c("TSSEnrichment", "log10(nFrags)")`** — without it, marker peaks are confounded by per-cell depth.
- **chromVAR runs on the deviations matrix**, not the gene score matrix. Set up `addBgdPeaks` first.
- **For ≥ 200k cells, drop the TileMatrix after building gene scores** — it's huge and rarely needed downstream.

---

## End-to-End Template

`assets/archr_template.R` — single parameterized script. Edit the CONFIGURATION block (input fragments, genome, batch column, marker genes, optional RNA reference) and run end-to-end.

## Convenience Scripts

- `scripts/build_archr.R` — Arrow files → ArchRProject → LSI/Harmony/UMAP/leiden → save
- `scripts/downstream_archr.R` — peaks + motifs + chromVAR + (optional) RNA integration

---

## References

- [ArchR website](https://www.archrproject.com/) — Greenleaf Lab
- [Full ArchR manual / bookdown](https://www.archrproject.com/bookdown/index.html) — 24 chapters
- [Brief tutorial](https://www.archrproject.com/articles/Articles/tutorial.html)
- [Function reference](https://www.archrproject.com/reference/index.html)
- Granja et al. (2021), *ArchR is a scalable software package for integrative single-cell chromatin accessibility analysis*, *Nature Genetics*

More from swaruplab/operon

SkillDescription
agentd-drug-discoveryUse the AgentD workflow to mine evidence, design molecules, and rank candidates with SAR plus ADMET annotations for early drug discovery tasks.
alphafold-databaseAccess AlphaFold 200M+ AI-predicted protein structures. Retrieve structures by UniProt ID, download PDB/mmCIF files, analyze confidence metrics (pLDDT, PAE), for drug discovery and structural biology.
antibody-design-agentAn advanced agent for de novo antibody design and optimization using state-of-the-art protein language models (MAGE, RFdiffusion).
automated-bioinformatics-pipelinesPipeline maestro
autonomous-biomedical-agentAutonomous biomedical AI agent framework for executing complex research tasks across genomics, drug discovery, molecular biology, and clinical analysis. Use this skill when conducting multi-step biomedical research including CRISPR screening design, single-cell RNA-seq analysis, ADMET prediction, GWAS interpretation, rare disease diagnosis, or lab protocol optimization. Leverages LLM reasoning with code execution and integrated biomedical databases.
autonomous-oncology-agentPrecision Oncology
basecallingConvert raw Nanopore signal data (FAST5/POD5) to nucleotide sequences using Dorado basecaller. Covers model selection, GPU acceleration, modified base detection, and quality filtering. Use when processing raw Nanopore data before alignment. Note: Guppy is deprecated; use Dorado for all new analyses.
batch-processingProcess multiple sequence files in batch using Biopython. Use when working with many files, merging/splitting sequences, or automating file operations across directories.
bindingdb-databaseQuery BindingDB for measured drug-target binding affinities (Ki, Kd, IC50, EC50). Search by target (UniProt ID), compound (SMILES/name), or pathogen. Essential for drug discovery, lead optimization, polypharmacology analysis, and structure-activity relationship (SAR) studies.
biological-systems-reasoning|