🧠 Key takeaways
Peaks are called separately for each cell type and merged into one set of fixed-width peaks, so that rare cell types contribute their own peaks.
Cell type-specific peaks can be selected quickly by comparing pooled accessibility, whereas significance requires a statistical test.
Motifs enriched in the specific peaks of a cell type point to the transcription factors that regulate it.
⚙️ Environment setup
Install conda:
Before creating the environment, ensure that conda is installed on your system.
Save the yml content:
Copy the content from the yml tab into a file named
environment.yml.
Create the environment:
Open a terminal or command prompt.
Run the following command:
conda env create -f environment.yml
Activate the environment:
After the environment is created, activate it using:
conda activate <environment_name>Replace
<environment_name>with the name specified in theenvironment.ymlfile. In the yml file it will look like this:name: <environment_name>
Verify the installation:
Check that the environment was created successfully by running:
conda env list
name: chromatin-accessibility
channels:
- conda-forge
dependencies:
- conda-forge::ipykernel=7.3.0
- conda-forge::ipywidgets=8.1.9
- conda-forge::python=3.13.15
- conda-forge::scanpy=1.12.4
- pip
- pip:
- lamindb==2.10.0
- macs3==3.0.5
- muon==0.1.9
- snapatac2==2.10.0
🗄️ Get data and notebooks
This book uses lamindb to store, share, and load datasets and notebooks using the theislab/sc-best-practices instance. We acknowledge free hosting from Lamin Labs.
Install lamindb
Install the lamindb Python package:
pip install lamindbOptionally create a lamin account
Sign up and log in following the instructions
Verify your setup
Run the
lamin connectcommand:
import lamindb as ln ln.Artifact.connect("theislab/sc-best-practices").df()You should now see up to 100 of the stored datasets.
Accessing datasets (Artifacts)
Search for the datasets on the Artifacts page
Load an Artifact and the corresponding object:
import lamindb as ln af = ln.Artifact.connect("theislab/sc-best-practices").get(key="key_of_dataset", is_latest=True) obj = af.load()The object is now accessible in memory and is ready for analysis. Adapt the
lamindb.Artifact.connect("theislab/sc-best-practices").get("SOMEIDXXXX")suffix to get respective versions.Accessing notebooks (Transforms)
Search for the notebook on the Transforms page
Load the notebook:
lamin load <notebook url>which will download the notebook to the current working directory. Analogously to
Artifacts, you can adapt the suffix ID to get older versions.
Motivation¶
Tiles are enough to cluster cells, but peaks, the regions with more accessibility than the genomic background, are the candidate regulatory elements that we want to compare between cell types and scan for transcription factor (TF) binding motifs. Peaks called on all cells together are dominated by abundant cell types, so we call peaks separately on the pooled fragments of each cell type and merge them into one set of fixed-width peaks Corces et al., 2018Granja et al., 2021.
import logging
import lamindb as ln
import snapatac2 as snap
for name in ("kaleido", "choreographer"):
logging.getLogger(name).setLevel(logging.WARNING)
ln.connect("theislab/sc-best-practices")
ln.track("wziys4Y5jNux")Output
→ connected lamindb: theislab/sc-best-practices
→ loaded Transform('wziys4Y5jNux0000', key='peaks_motifs.ipynb'), started new Run('oErvc76qTUJM9RFR') at 2026-09-29 15:38:52 UTC
→ notebook imports: lamindb-core==2.10.0 snapatac2==2.10.0
We load the cells annotated in the previous chapter.
adata = ln.Artifact.get(key="chromatin_accessibility/pbmc10k_clustered.h5ad").load()
adataAnnData object with n_obs × n_vars = 9255 × 6062095
obs: 'n_fragment', 'frac_dup', 'frac_mito', 'tsse', 'doublet_probability', 'doublet_score', 'leiden', 'cell_type'
var: 'count', 'selected'
uns: 'TSS_profile', 'cell_type_colors', 'doublet_rate', 'frac_overlap_TSS', 'frag_size_distr', 'leiden_colors', 'library_tsse', 'reference_sequences', 'scrublet_sim_doublet_score', 'spectral_eigenvalue'
obsm: 'X_spectral', 'X_umap', 'fragment_paired'
obsp: 'distances'
layers: None (.X)Peak calling¶
SnapATAC2 calls peaks with MACS3 Zhang et al., 2008 on the fragments of each cell type.
merge_peaks then centers every peak on its summit, extends it to 500 bp and, where peaks overlap, keeps only the most significant one.
snap.tl.macs3(adata, groupby="cell_type")
peaks = snap.tl.merge_peaks(adata.uns["macs3"], snap.genome.hg38.chrom_sizes)
peak_matrix = snap.pp.make_peak_matrix(adata, use_rep=peaks["Peaks"])Output
2026-09-29 17:39:00 - INFO - Exporting fragments...
2026-09-29 17:39:22 - INFO - Calling peaks...
0%| | 0/11 [00:00<?, ?it/s] 9%|▉ | 1/11 [00:12<02:05, 12.50s/it] 18%|█▊ | 2/11 [00:27<02:03, 13.68s/it] 27%|██▋ | 3/11 [00:28<01:03, 7.89s/it] 36%|███▋ | 4/11 [00:28<00:34, 4.97s/it] 45%|████▌ | 5/11 [00:40<00:43, 7.33s/it] 55%|█████▍ | 6/11 [00:46<00:34, 6.88s/it] 64%|██████▎ | 7/11 [00:56<00:31, 7.90s/it] 73%|███████▎ | 8/11 [00:58<00:18, 6.02s/it] 82%|████████▏ | 9/11 [02:06<00:50, 25.40s/it] 91%|█████████ | 10/11 [03:11<00:37, 37.63s/it]100%|██████████| 11/11 [03:52<00:00, 38.67s/it]100%|██████████| 11/11 [03:52<00:00, 21.14s/it]
peak_matrixAnnData object with n_obs × n_vars = 9255 × 201931
obs: 'n_fragment', 'frac_dup', 'frac_mito', 'tsse', 'doublet_probability', 'doublet_score', 'leiden', 'cell_type'
layers: None (.X)Cell type-specific peaks¶
marker_regions quickly finds peaks that are more accessible in one cell type than in the others by comparing their accessibility after pooling the cells of each type.
It does not test for significance, which requires a statistical model such as the one in snap.tl.diff_test, but it is enough to select regions for motif analysis.
markers = snap.tl.marker_regions(peak_matrix, groupby="cell_type", pvalue=0.01)
snap.pl.regions(peak_matrix, groupby="cell_type", peaks=markers, interactive=False)
Motif enrichment¶
TFs bind short sequence motifs, so a motif that is overrepresented in the peaks of a cell type points to TFs that regulate it. We test the marker peaks of each cell type for the TF motifs of CIS-BP Weirauch et al., 2014, keeping the most informative motif per TF, against the marker peaks of all cell types.
fasta = ln.Artifact.get(key="chromatin_accessibility/gencode_v41_GRCh38.fa").cache()
motif_file = ln.Artifact.get(key="chromatin_accessibility/cisBP_human.meme").cache()
cis_bp = {}
for motif in snap.read_motifs(str(motif_file)):
motif.id = motif.name = motif.id.split("+")[0]
if (
motif.name not in cis_bp
or motif.info_content() > cis_bp[motif.name].info_content()
):
cis_bp[motif.name] = motif
enrichment = snap.tl.motif_enrichment(
motifs=list(cis_bp.values()), regions=markers, genome_fasta=fasta
)Output
2026-09-29 17:43:34 - INFO - Fetching 36831 sequences ...
2026-09-29 17:43:34 - INFO - Computing enrichment ...
0%| | 0/1165 [00:00<?, ?it/s] 0%| | 2/1165 [00:00<01:18, 14.80it/s] 0%| | 4/1165 [00:00<01:09, 16.64it/s] 1%| | 7/1165 [00:00<00:55, 20.99it/s] 1%| | 10/1165 [00:00<00:49, 23.42it/s] 1%| | 14/1165 [00:00<00:42, 27.06it/s] 1%|▏ | 17/1165 [00:00<00:45, 25.35it/s] 2%|▏ | 20/1165 [00:00<00:42, 26.64it/s] 2%|▏ | 24/1165 [00:00<00:40, 28.23it/s] 2%|▏ | 27/1165 [00:01<00:45, 25.11it/s] 3%|▎ | 30/1165 [00:01<00:47, 23.85it/s] 3%|▎ | 33/1165 [00:01<00:49, 22.96it/s] 3%|▎ | 36/1165 [00:01<00:48, 23.13it/s] 3%|▎ | 39/1165 [00:01<00:49, 22.53it/s] 4%|▎ | 42/1165 [00:01<00:50, 22.17it/s] 4%|▍ | 45/1165 [00:01<00:51, 21.93it/s] 4%|▍ | 48/1165 [00:02<00:48, 23.26it/s] 4%|▍ | 52/1165 [00:02<00:43, 25.55it/s] 5%|▍ | 55/1165 [00:02<00:42, 25.82it/s] 5%|▌ | 59/1165 [00:02<00:39, 27.98it/s] 5%|▌ | 62/1165 [00:02<00:38, 28.45it/s] 6%|▌ | 65/1165 [00:02<00:40, 27.35it/s] 6%|▌ | 68/1165 [00:02<00:41, 26.19it/s] 6%|▌ | 72/1165 [00:02<00:41, 26.45it/s] 6%|▋ | 75/1165 [00:03<00:43, 25.04it/s] 7%|▋ | 78/1165 [00:03<00:44, 24.64it/s] 7%|▋ | 82/1165 [00:03<00:42, 25.20it/s] 7%|▋ | 85/1165 [00:03<00:46, 23.08it/s] 8%|▊ | 88/1165 [00:03<00:49, 21.85it/s] 8%|▊ | 92/1165 [00:03<00:43, 24.40it/s] 8%|▊ | 96/1165 [00:03<00:39, 26.85it/s] 9%|▊ | 100/1165 [00:04<00:38, 27.79it/s] 9%|▉ | 103/1165 [00:04<00:42, 24.96it/s] 9%|▉ | 106/1165 [00:04<00:47, 22.47it/s] 9%|▉ | 110/1165 [00:04<00:43, 24.41it/s] 10%|▉ | 113/1165 [00:04<00:43, 24.08it/s] 10%|▉ | 116/1165 [00:04<00:43, 24.24it/s] 10%|█ | 119/1165 [00:04<00:49, 20.94it/s] 10%|█ | 122/1165 [00:05<00:49, 21.26it/s] 11%|█ | 125/1165 [00:05<00:46, 22.43it/s] 11%|█ | 128/1165 [00:05<00:49, 21.03it/s] 11%|█ | 131/1165 [00:05<00:55, 18.62it/s] 11%|█▏ | 133/1165 [00:05<00:55, 18.63it/s] 12%|█▏ | 135/1165 [00:05<00:54, 18.90it/s] 12%|█▏ | 137/1165 [00:05<00:53, 19.11it/s] 12%|█▏ | 139/1165 [00:05<00:53, 19.16it/s] 12%|█▏ | 142/1165 [00:06<00:47, 21.48it/s] 13%|█▎ | 146/1165 [00:06<00:40, 25.24it/s] 13%|█▎ | 149/1165 [00:06<00:40, 25.10it/s] 13%|█▎ | 152/1165 [00:06<00:47, 21.42it/s] 13%|█▎ | 155/1165 [00:06<00:48, 20.80it/s] 14%|█▎ | 158/1165 [00:06<00:46, 21.61it/s] 14%|█▍ | 161/1165 [00:06<00:48, 20.81it/s] 14%|█▍ | 164/1165 [00:07<00:45, 22.21it/s] 14%|█▍ | 167/1165 [00:07<00:48, 20.46it/s] 15%|█▍ | 170/1165 [00:07<00:44, 22.34it/s] 15%|█▍ | 173/1165 [00:07<00:48, 20.43it/s] 15%|█▌ | 176/1165 [00:07<00:44, 22.31it/s] 15%|█▌ | 179/1165 [00:07<00:44, 22.01it/s] 16%|█▌ | 182/1165 [00:07<00:52, 18.86it/s] 16%|█▌ | 185/1165 [00:08<00:53, 18.19it/s] 16%|█▌ | 187/1165 [00:08<00:55, 17.69it/s] 16%|█▌ | 189/1165 [00:08<00:55, 17.73it/s] 16%|█▋ | 191/1165 [00:08<00:59, 16.44it/s] 17%|█▋ | 193/1165 [00:08<01:02, 15.63it/s] 17%|█▋ | 195/1165 [00:08<01:04, 15.02it/s] 17%|█▋ | 197/1165 [00:08<01:04, 14.96it/s] 17%|█▋ | 199/1165 [00:09<01:01, 15.79it/s] 17%|█▋ | 202/1165 [00:09<00:52, 18.43it/s] 18%|█▊ | 206/1165 [00:09<00:46, 20.56it/s] 18%|█▊ | 209/1165 [00:09<00:47, 20.31it/s] 18%|█▊ | 212/1165 [00:09<00:46, 20.49it/s] 18%|█▊ | 215/1165 [00:09<00:44, 21.17it/s] 19%|█▊ | 218/1165 [00:09<00:44, 21.27it/s] 19%|█▉ | 221/1165 [00:10<00:44, 21.23it/s] 19%|█▉ | 224/1165 [00:10<00:40, 23.01it/s] 19%|█▉ | 227/1165 [00:10<00:41, 22.88it/s] 20%|█▉ | 230/1165 [00:10<00:38, 24.05it/s] 20%|██ | 233/1165 [00:10<00:37, 24.93it/s] 20%|██ | 236/1165 [00:10<00:39, 23.61it/s] 21%|██ | 240/1165 [00:10<00:40, 22.67it/s] 21%|██ | 243/1165 [00:10<00:42, 21.93it/s] 21%|██ | 246/1165 [00:11<00:55, 16.67it/s] 21%|██▏ | 248/1165 [00:11<00:54, 16.81it/s] 21%|██▏ | 250/1165 [00:11<00:56, 16.26it/s] 22%|██▏ | 252/1165 [00:11<00:57, 15.98it/s] 22%|██▏ | 255/1165 [00:11<00:48, 18.58it/s] 22%|██▏ | 259/1165 [00:11<00:39, 22.73it/s] 22%|██▏ | 262/1165 [00:12<00:40, 22.07it/s] 23%|██▎ | 266/1165 [00:12<00:35, 25.56it/s] 23%|██▎ | 269/1165 [00:12<00:35, 25.32it/s] 23%|██▎ | 272/1165 [00:12<00:34, 25.64it/s] 24%|██▎ | 275/1165 [00:12<00:33, 26.70it/s] 24%|██▍ | 279/1165 [00:12<00:30, 28.64it/s] 24%|██▍ | 282/1165 [00:12<00:36, 24.24it/s] 24%|██▍ | 285/1165 [00:12<00:42, 20.90it/s] 25%|██▍ | 288/1165 [00:13<00:38, 22.83it/s] 25%|██▌ | 292/1165 [00:13<00:35, 24.71it/s] 25%|██▌ | 295/1165 [00:13<00:33, 25.81it/s] 26%|██▌ | 298/1165 [00:13<00:40, 21.34it/s] 26%|██▌ | 301/1165 [00:13<00:41, 20.98it/s] 26%|██▌ | 304/1165 [00:13<00:38, 22.45it/s] 27%|██▋ | 309/1165 [00:13<00:31, 27.02it/s] 27%|██▋ | 313/1165 [00:14<00:28, 29.57it/s] 27%|██▋ | 317/1165 [00:14<00:27, 31.31it/s] 28%|██▊ | 321/1165 [00:14<00:25, 33.15it/s] 28%|██▊ | 325/1165 [00:14<00:26, 31.12it/s] 28%|██▊ | 330/1165 [00:14<00:24, 34.10it/s] 29%|██▊ | 334/1165 [00:14<00:27, 29.68it/s] 29%|██▉ | 338/1165 [00:14<00:27, 30.47it/s] 29%|██▉ | 342/1165 [00:14<00:29, 27.97it/s] 30%|██▉ | 345/1165 [00:15<00:35, 23.12it/s] 30%|██▉ | 348/1165 [00:15<00:41, 19.83it/s] 30%|███ | 352/1165 [00:15<00:36, 22.28it/s] 30%|███ | 355/1165 [00:15<00:37, 21.87it/s] 31%|███ | 358/1165 [00:15<00:45, 17.63it/s] 31%|███ | 360/1165 [00:16<00:48, 16.48it/s] 31%|███ | 362/1165 [00:16<00:49, 16.20it/s] 31%|███ | 364/1165 [00:16<00:48, 16.37it/s] 32%|███▏ | 367/1165 [00:16<00:46, 17.02it/s] 32%|███▏ | 371/1165 [00:16<00:36, 21.95it/s] 32%|███▏ | 374/1165 [00:16<00:36, 21.80it/s] 32%|███▏ | 377/1165 [00:16<00:35, 21.94it/s] 33%|███▎ | 380/1165 [00:17<00:36, 21.22it/s] 33%|███▎ | 383/1165 [00:17<00:36, 21.53it/s] 33%|███▎ | 386/1165 [00:17<00:36, 21.21it/s] 33%|███▎ | 389/1165 [00:17<00:36, 21.11it/s] 34%|███▎ | 392/1165 [00:17<00:34, 22.36it/s] 34%|███▍ | 395/1165 [00:17<00:34, 22.48it/s] 34%|███▍ | 399/1165 [00:17<00:29, 26.11it/s] 35%|███▍ | 403/1165 [00:17<00:26, 28.92it/s] 35%|███▍ | 407/1165 [00:18<00:25, 29.99it/s] 35%|███▌ | 411/1165 [00:18<00:27, 27.51it/s] 36%|███▌ | 414/1165 [00:18<00:26, 27.94it/s] 36%|███▌ | 417/1165 [00:18<00:29, 25.63it/s] 36%|███▌ | 420/1165 [00:18<00:32, 23.25it/s] 36%|███▋ | 423/1165 [00:18<00:39, 19.01it/s] 37%|███▋ | 426/1165 [00:18<00:37, 19.91it/s] 37%|███▋ | 429/1165 [00:19<00:34, 21.11it/s] 37%|███▋ | 432/1165 [00:19<00:36, 20.29it/s] 37%|███▋ | 435/1165 [00:19<00:34, 20.99it/s] 38%|███▊ | 438/1165 [00:19<00:33, 21.78it/s] 38%|███▊ | 441/1165 [00:19<00:34, 20.88it/s] 38%|███▊ | 444/1165 [00:19<00:31, 22.54it/s] 38%|███▊ | 448/1165 [00:19<00:27, 25.70it/s] 39%|███▊ | 451/1165 [00:20<00:28, 24.93it/s] 39%|███▉ | 454/1165 [00:20<00:28, 24.68it/s] 39%|███▉ | 457/1165 [00:20<00:29, 23.80it/s] 39%|███▉ | 460/1165 [00:20<00:33, 21.34it/s] 40%|███▉ | 463/1165 [00:20<00:33, 21.05it/s] 40%|████ | 466/1165 [00:20<00:31, 22.25it/s] 40%|████ | 469/1165 [00:20<00:29, 23.31it/s] 41%|████ | 473/1165 [00:20<00:27, 25.28it/s] 41%|████ | 476/1165 [00:21<00:27, 25.14it/s] 41%|████ | 479/1165 [00:21<00:28, 24.01it/s] 41%|████▏ | 482/1165 [00:21<00:29, 23.44it/s] 42%|████▏ | 485/1165 [00:21<00:32, 21.05it/s] 42%|████▏ | 488/1165 [00:21<00:29, 22.96it/s] 42%|████▏ | 491/1165 [00:21<00:28, 23.66it/s] 42%|████▏ | 494/1165 [00:21<00:28, 23.21it/s] 43%|████▎ | 497/1165 [00:22<00:29, 22.51it/s] 43%|████▎ | 500/1165 [00:22<00:33, 19.87it/s] 43%|████▎ | 503/1165 [00:22<00:38, 17.19it/s] 44%|████▎ | 507/1165 [00:22<00:31, 20.80it/s] 44%|████▍ | 511/1165 [00:22<00:26, 24.86it/s] 44%|████▍ | 515/1165 [00:22<00:25, 25.59it/s] 45%|████▍ | 519/1165 [00:22<00:23, 27.62it/s] 45%|████▍ | 522/1165 [00:23<00:31, 20.64it/s] 45%|████▌ | 525/1165 [00:23<00:37, 16.88it/s] 45%|████▌ | 528/1165 [00:23<00:36, 17.45it/s] 45%|████▌ | 530/1165 [00:23<00:35, 17.85it/s] 46%|████▌ | 533/1165 [00:23<00:34, 18.46it/s] 46%|████▌ | 535/1165 [00:23<00:35, 17.96it/s] 46%|████▌ | 537/1165 [00:24<00:35, 17.66it/s] 46%|████▋ | 540/1165 [00:24<00:30, 20.26it/s] 47%|████▋ | 543/1165 [00:24<00:32, 19.26it/s] 47%|████▋ | 546/1165 [00:24<00:30, 20.55it/s] 47%|████▋ | 549/1165 [00:24<00:28, 21.74it/s] 47%|████▋ | 552/1165 [00:24<00:28, 21.62it/s] 48%|████▊ | 556/1165 [00:24<00:25, 23.93it/s] 48%|████▊ | 559/1165 [00:25<00:27, 22.33it/s] 48%|████▊ | 562/1165 [00:25<00:32, 18.65it/s] 48%|████▊ | 564/1165 [00:25<00:32, 18.33it/s] 49%|████▊ | 566/1165 [00:25<00:32, 18.54it/s] 49%|████▉ | 568/1165 [00:25<00:38, 15.50it/s] 49%|████▉ | 570/1165 [00:25<00:36, 16.11it/s] 49%|████▉ | 573/1165 [00:25<00:31, 19.04it/s] 49%|████▉ | 576/1165 [00:26<00:29, 19.82it/s] 50%|████▉ | 580/1165 [00:26<00:25, 23.38it/s] 50%|█████ | 583/1165 [00:26<00:24, 23.65it/s] 50%|█████ | 587/1165 [00:26<00:22, 25.53it/s] 51%|█████ | 590/1165 [00:26<00:22, 25.60it/s] 51%|█████ | 593/1165 [00:26<00:23, 24.47it/s] 51%|█████ | 596/1165 [00:26<00:25, 22.20it/s] 51%|█████▏ | 599/1165 [00:27<00:28, 19.75it/s] 52%|█████▏ | 602/1165 [00:27<00:28, 19.88it/s] 52%|█████▏ | 605/1165 [00:27<00:33, 16.72it/s] 52%|█████▏ | 608/1165 [00:27<00:31, 17.74it/s] 52%|█████▏ | 611/1165 [00:27<00:31, 17.55it/s] 53%|█████▎ | 613/1165 [00:27<00:33, 16.65it/s] 53%|█████▎ | 615/1165 [00:28<00:36, 15.01it/s] 53%|█████▎ | 618/1165 [00:28<00:31, 17.34it/s] 53%|█████▎ | 622/1165 [00:28<00:28, 19.35it/s] 54%|█████▎ | 624/1165 [00:28<00:30, 17.53it/s] 54%|█████▍ | 627/1165 [00:28<00:27, 19.57it/s] 54%|█████▍ | 630/1165 [00:28<00:26, 20.15it/s] 54%|█████▍ | 633/1165 [00:28<00:25, 20.49it/s] 55%|█████▍ | 636/1165 [00:29<00:28, 18.52it/s] 55%|█████▍ | 638/1165 [00:29<00:30, 17.44it/s] 55%|█████▌ | 641/1165 [00:29<00:26, 19.77it/s] 55%|█████▌ | 645/1165 [00:29<00:22, 23.32it/s] 56%|█████▌ | 648/1165 [00:29<00:25, 20.48it/s] 56%|█████▌ | 651/1165 [00:29<00:27, 18.61it/s] 56%|█████▌ | 653/1165 [00:30<00:28, 17.69it/s] 56%|█████▌ | 655/1165 [00:30<00:28, 17.70it/s] 56%|█████▋ | 658/1165 [00:30<00:25, 20.07it/s] 57%|█████▋ | 661/1165 [00:30<00:25, 19.73it/s] 57%|█████▋ | 664/1165 [00:30<00:27, 17.98it/s] 57%|█████▋ | 667/1165 [00:30<00:24, 20.29it/s] 58%|█████▊ | 670/1165 [00:30<00:22, 21.77it/s] 58%|█████▊ | 673/1165 [00:30<00:22, 21.60it/s] 58%|█████▊ | 676/1165 [00:31<00:22, 21.57it/s] 58%|█████▊ | 679/1165 [00:31<00:21, 23.05it/s] 59%|█████▊ | 683/1165 [00:31<00:19, 25.17it/s] 59%|█████▉ | 686/1165 [00:31<00:20, 23.45it/s] 59%|█████▉ | 689/1165 [00:31<00:21, 22.03it/s] 59%|█████▉ | 692/1165 [00:31<00:21, 22.07it/s] 60%|█████▉ | 695/1165 [00:31<00:21, 22.33it/s] 60%|█████▉ | 698/1165 [00:32<00:19, 23.84it/s] 60%|██████ | 701/1165 [00:32<00:22, 20.31it/s] 60%|██████ | 704/1165 [00:32<00:24, 18.69it/s] 61%|██████ | 706/1165 [00:32<00:25, 18.19it/s] 61%|██████ | 709/1165 [00:32<00:24, 18.84it/s] 61%|██████ | 712/1165 [00:32<00:24, 18.68it/s] 61%|██████▏ | 714/1165 [00:32<00:25, 17.58it/s] 62%|██████▏ | 717/1165 [00:33<00:23, 18.77it/s] 62%|██████▏ | 719/1165 [00:33<00:24, 17.93it/s] 62%|██████▏ | 722/1165 [00:33<00:25, 17.32it/s] 62%|██████▏ | 725/1165 [00:33<00:24, 18.22it/s] 62%|██████▏ | 728/1165 [00:33<00:26, 16.36it/s] 63%|██████▎ | 730/1165 [00:33<00:25, 16.92it/s] 63%|██████▎ | 733/1165 [00:34<00:22, 19.56it/s] 63%|██████▎ | 736/1165 [00:34<00:24, 17.44it/s] 63%|██████▎ | 738/1165 [00:34<00:27, 15.46it/s] 64%|██████▎ | 740/1165 [00:34<00:27, 15.22it/s] 64%|██████▎ | 742/1165 [00:34<00:28, 15.10it/s] 64%|██████▍ | 744/1165 [00:34<00:27, 15.12it/s] 64%|██████▍ | 747/1165 [00:34<00:23, 17.57it/s] 64%|██████▍ | 750/1165 [00:35<00:20, 20.40it/s] 65%|██████▍ | 753/1165 [00:35<00:18, 22.02it/s] 65%|██████▍ | 756/1165 [00:35<00:17, 23.34it/s] 65%|██████▌ | 759/1165 [00:35<00:17, 22.56it/s] 65%|██████▌ | 763/1165 [00:35<00:16, 24.42it/s] 66%|██████▌ | 766/1165 [00:35<00:15, 25.12it/s] 66%|██████▌ | 769/1165 [00:35<00:16, 24.33it/s] 66%|██████▋ | 772/1165 [00:35<00:17, 22.95it/s] 67%|██████▋ | 775/1165 [00:36<00:15, 24.49it/s] 67%|██████▋ | 778/1165 [00:36<00:16, 23.23it/s] 67%|██████▋ | 781/1165 [00:36<00:18, 20.37it/s] 67%|██████▋ | 784/1165 [00:36<00:23, 16.51it/s] 67%|██████▋ | 786/1165 [00:36<00:22, 16.91it/s] 68%|██████▊ | 790/1165 [00:36<00:19, 18.92it/s] 68%|██████▊ | 792/1165 [00:37<00:21, 17.61it/s] 68%|██████▊ | 794/1165 [00:37<00:23, 15.97it/s] 68%|██████▊ | 797/1165 [00:37<00:20, 17.61it/s] 69%|██████▊ | 799/1165 [00:37<00:20, 17.45it/s] 69%|██████▉ | 801/1165 [00:37<00:20, 17.99it/s] 69%|██████▉ | 805/1165 [00:37<00:16, 21.76it/s] 69%|██████▉ | 808/1165 [00:37<00:18, 19.05it/s] 70%|██████▉ | 811/1165 [00:38<00:17, 20.02it/s] 70%|██████▉ | 814/1165 [00:38<00:15, 22.04it/s] 70%|███████ | 817/1165 [00:38<00:17, 20.19it/s] 70%|███████ | 820/1165 [00:38<00:17, 20.15it/s] 71%|███████ | 823/1165 [00:38<00:17, 19.72it/s] 71%|███████ | 826/1165 [00:38<00:17, 18.99it/s] 71%|███████ | 829/1165 [00:38<00:18, 18.48it/s] 71%|███████▏ | 832/1165 [00:39<00:18, 18.22it/s] 72%|███████▏ | 834/1165 [00:39<00:19, 16.96it/s] 72%|███████▏ | 836/1165 [00:39<00:18, 17.40it/s] 72%|███████▏ | 839/1165 [00:39<00:17, 18.48it/s] 72%|███████▏ | 841/1165 [00:39<00:17, 18.18it/s] 72%|███████▏ | 844/1165 [00:39<00:15, 20.46it/s] 73%|███████▎ | 847/1165 [00:39<00:14, 21.60it/s] 73%|███████▎ | 850/1165 [00:40<00:14, 21.74it/s] 73%|███████▎ | 853/1165 [00:40<00:16, 18.42it/s] 73%|███████▎ | 855/1165 [00:40<00:17, 17.36it/s] 74%|███████▎ | 858/1165 [00:40<00:18, 16.88it/s] 74%|███████▍ | 860/1165 [00:40<00:19, 15.47it/s] 74%|███████▍ | 863/1165 [00:40<00:18, 16.59it/s] 74%|███████▍ | 866/1165 [00:41<00:16, 17.64it/s] 75%|███████▍ | 868/1165 [00:41<00:16, 17.62it/s] 75%|███████▍ | 870/1165 [00:41<00:17, 16.83it/s] 75%|███████▍ | 872/1165 [00:41<00:21, 13.62it/s] 75%|███████▌ | 874/1165 [00:41<00:21, 13.84it/s] 75%|███████▌ | 877/1165 [00:41<00:19, 15.12it/s] 76%|███████▌ | 880/1165 [00:41<00:17, 16.29it/s] 76%|███████▌ | 882/1165 [00:42<00:20, 13.49it/s] 76%|███████▌ | 885/1165 [00:42<00:19, 14.20it/s] 76%|███████▌ | 887/1165 [00:42<00:21, 13.10it/s] 76%|███████▋ | 889/1165 [00:42<00:23, 11.61it/s] 76%|███████▋ | 891/1165 [00:42<00:24, 11.14it/s] 77%|███████▋ | 894/1165 [00:43<00:22, 11.98it/s] 77%|███████▋ | 896/1165 [00:43<00:20, 13.31it/s] 77%|███████▋ | 898/1165 [00:43<00:20, 12.78it/s] 77%|███████▋ | 900/1165 [00:43<00:21, 12.39it/s] 77%|███████▋ | 902/1165 [00:43<00:23, 11.13it/s] 78%|███████▊ | 905/1165 [00:43<00:17, 14.55it/s] 78%|███████▊ | 907/1165 [00:44<00:18, 13.89it/s] 78%|███████▊ | 911/1165 [00:44<00:13, 18.77it/s] 78%|███████▊ | 914/1165 [00:44<00:13, 18.75it/s] 79%|███████▉ | 918/1165 [00:44<00:10, 22.55it/s] 79%|███████▉ | 921/1165 [00:44<00:13, 18.19it/s] 79%|███████▉ | 924/1165 [00:44<00:13, 17.95it/s] 79%|███████▉ | 926/1165 [00:45<00:15, 15.69it/s] 80%|███████▉ | 929/1165 [00:45<00:13, 17.69it/s] 80%|███████▉ | 931/1165 [00:45<00:16, 14.13it/s] 80%|████████ | 933/1165 [00:45<00:16, 14.11it/s] 80%|████████ | 935/1165 [00:45<00:16, 14.35it/s] 80%|████████ | 937/1165 [00:45<00:16, 14.23it/s] 81%|████████ | 939/1165 [00:46<00:16, 13.43it/s] 81%|████████ | 941/1165 [00:46<00:18, 12.19it/s] 81%|████████ | 943/1165 [00:46<00:17, 13.00it/s] 81%|████████ | 946/1165 [00:46<00:14, 14.79it/s] 81%|████████▏ | 948/1165 [00:46<00:16, 13.14it/s] 82%|████████▏ | 950/1165 [00:46<00:15, 14.20it/s] 82%|████████▏ | 952/1165 [00:47<00:15, 13.45it/s] 82%|████████▏ | 954/1165 [00:47<00:18, 11.21it/s] 82%|████████▏ | 956/1165 [00:47<00:17, 12.13it/s] 82%|████████▏ | 958/1165 [00:47<00:18, 11.23it/s] 82%|████████▏ | 960/1165 [00:47<00:16, 12.08it/s] 83%|████████▎ | 963/1165 [00:47<00:15, 13.37it/s] 83%|████████▎ | 965/1165 [00:48<00:15, 13.09it/s] 83%|████████▎ | 967/1165 [00:48<00:15, 12.69it/s] 83%|████████▎ | 969/1165 [00:48<00:17, 11.13it/s] 83%|████████▎ | 971/1165 [00:48<00:15, 12.30it/s] 84%|████████▎ | 974/1165 [00:48<00:14, 13.20it/s] 84%|████████▍ | 977/1165 [00:49<00:14, 13.42it/s] 84%|████████▍ | 980/1165 [00:49<00:13, 13.72it/s] 84%|████████▍ | 982/1165 [00:49<00:13, 13.23it/s] 84%|████████▍ | 984/1165 [00:49<00:14, 12.67it/s] 85%|████████▍ | 986/1165 [00:49<00:14, 12.35it/s] 85%|████████▍ | 989/1165 [00:49<00:12, 13.71it/s] 85%|████████▌ | 991/1165 [00:50<00:13, 13.38it/s] 85%|████████▌ | 993/1165 [00:50<00:13, 12.59it/s] 85%|████████▌ | 995/1165 [00:50<00:12, 13.71it/s] 86%|████████▌ | 997/1165 [00:50<00:12, 13.81it/s] 86%|████████▌ | 999/1165 [00:50<00:12, 13.58it/s] 86%|████████▌ | 1001/1165 [00:50<00:11, 14.03it/s] 86%|████████▌ | 1003/1165 [00:51<00:12, 12.89it/s] 86%|████████▋ | 1005/1165 [00:51<00:12, 13.25it/s] 87%|████████▋ | 1008/1165 [00:51<00:11, 13.76it/s] 87%|████████▋ | 1010/1165 [00:51<00:10, 14.74it/s] 87%|████████▋ | 1012/1165 [00:51<00:11, 12.86it/s] 87%|████████▋ | 1014/1165 [00:51<00:12, 12.35it/s] 87%|████████▋ | 1016/1165 [00:52<00:11, 12.54it/s] 87%|████████▋ | 1018/1165 [00:52<00:10, 13.57it/s] 88%|████████▊ | 1020/1165 [00:52<00:10, 14.48it/s] 88%|████████▊ | 1022/1165 [00:52<00:10, 14.04it/s] 88%|████████▊ | 1024/1165 [00:52<00:10, 13.33it/s] 88%|████████▊ | 1027/1165 [00:52<00:08, 16.63it/s] 88%|████████▊ | 1029/1165 [00:52<00:08, 15.56it/s] 88%|████████▊ | 1031/1165 [00:53<00:08, 15.48it/s] 89%|████████▊ | 1033/1165 [00:53<00:08, 14.99it/s] 89%|████████▉ | 1036/1165 [00:53<00:07, 17.56it/s] 89%|████████▉ | 1038/1165 [00:53<00:07, 17.47it/s] 89%|████████▉ | 1040/1165 [00:53<00:08, 14.34it/s] 89%|████████▉ | 1042/1165 [00:53<00:08, 14.24it/s] 90%|████████▉ | 1044/1165 [00:53<00:08, 13.69it/s] 90%|████████▉ | 1046/1165 [00:54<00:08, 13.38it/s] 90%|████████▉ | 1048/1165 [00:54<00:10, 11.32it/s] 90%|█████████ | 1050/1165 [00:54<00:09, 12.23it/s] 90%|█████████ | 1052/1165 [00:54<00:09, 12.12it/s] 90%|█████████ | 1054/1165 [00:54<00:08, 13.49it/s] 91%|█████████ | 1056/1165 [00:54<00:07, 14.41it/s] 91%|█████████ | 1058/1165 [00:54<00:07, 14.42it/s] 91%|█████████ | 1061/1165 [00:55<00:06, 15.87it/s] 91%|█████████ | 1063/1165 [00:55<00:06, 16.37it/s] 91%|█████████▏| 1065/1165 [00:55<00:06, 14.46it/s] 92%|█████████▏| 1067/1165 [00:55<00:06, 14.70it/s] 92%|█████████▏| 1071/1165 [00:55<00:05, 16.03it/s] 92%|█████████▏| 1073/1165 [00:55<00:05, 16.30it/s] 92%|█████████▏| 1075/1165 [00:56<00:05, 15.29it/s] 92%|█████████▏| 1077/1165 [00:56<00:05, 15.55it/s] 93%|█████████▎| 1080/1165 [00:56<00:05, 16.84it/s] 93%|█████████▎| 1082/1165 [00:56<00:05, 14.85it/s] 93%|█████████▎| 1084/1165 [00:56<00:05, 14.67it/s] 93%|█████████▎| 1086/1165 [00:56<00:06, 12.85it/s] 93%|█████████▎| 1089/1165 [00:56<00:04, 15.53it/s] 94%|█████████▎| 1092/1165 [00:57<00:04, 15.42it/s] 94%|█████████▍| 1095/1165 [00:57<00:04, 17.24it/s] 94%|█████████▍| 1097/1165 [00:57<00:03, 17.79it/s] 94%|█████████▍| 1099/1165 [00:57<00:04, 14.97it/s] 95%|█████████▍| 1102/1165 [00:57<00:03, 16.65it/s] 95%|█████████▍| 1104/1165 [00:57<00:03, 17.08it/s] 95%|█████████▌| 1108/1165 [00:57<00:02, 20.89it/s] 95%|█████████▌| 1111/1165 [00:58<00:02, 18.95it/s] 96%|█████████▌| 1113/1165 [00:58<00:02, 19.15it/s] 96%|█████████▌| 1115/1165 [00:58<00:03, 16.31it/s] 96%|█████████▌| 1117/1165 [00:58<00:03, 14.45it/s] 96%|█████████▌| 1119/1165 [00:58<00:03, 14.32it/s] 96%|█████████▌| 1121/1165 [00:58<00:03, 13.92it/s] 96%|█████████▋| 1123/1165 [00:59<00:03, 13.55it/s] 97%|█████████▋| 1125/1165 [00:59<00:03, 12.75it/s] 97%|█████████▋| 1127/1165 [00:59<00:03, 11.84it/s] 97%|█████████▋| 1130/1165 [00:59<00:02, 15.44it/s] 97%|█████████▋| 1132/1165 [00:59<00:02, 15.98it/s] 97%|█████████▋| 1134/1165 [00:59<00:01, 16.73it/s] 98%|█████████▊| 1136/1165 [00:59<00:01, 16.15it/s] 98%|█████████▊| 1138/1165 [01:00<00:02, 13.45it/s] 98%|█████████▊| 1140/1165 [01:00<00:01, 12.81it/s] 98%|█████████▊| 1142/1165 [01:00<00:01, 12.14it/s] 98%|█████████▊| 1144/1165 [01:00<00:01, 12.32it/s] 98%|█████████▊| 1147/1165 [01:00<00:01, 14.17it/s] 99%|█████████▊| 1149/1165 [01:00<00:01, 13.04it/s] 99%|█████████▉| 1151/1165 [01:01<00:01, 12.88it/s] 99%|█████████▉| 1153/1165 [01:01<00:00, 13.95it/s] 99%|█████████▉| 1155/1165 [01:01<00:00, 12.92it/s] 99%|█████████▉| 1157/1165 [01:01<00:00, 13.19it/s]100%|█████████▉| 1160/1165 [01:01<00:00, 14.30it/s]100%|█████████▉| 1162/1165 [01:01<00:00, 14.09it/s]100%|█████████▉| 1164/1165 [01:02<00:00, 13.05it/s]100%|██████████| 1165/1165 [01:02<00:00, 18.75it/s]
snap.pl.motif_enrichment(enrichment, max_fdr=1e-20, height=1200, interactive=False)
The motifs enriched in each cell type match its known regulators: CEBP and AP-1 motifs in CD14+ monocytes, PU.1 (SPI1) motifs in CD16+ monocytes and cDC2, and NR4A motifs in CD16+ monocytes. NK and effector CD8+ T cells are enriched for the T-box motif of EOMES and T-bet, naive T cells for the motif of LEF1 and TCF7, and MAIT cells for the ROR motif. B cells are enriched for EBF1 and octamer motifs, which OCT2 binds together with its coactivator OBF1 (POU2AF1), and pDCs for E-box motifs, which include the motif of TCF4. TFs of one family share nearly identical motifs, so enrichment points to a family rather than a single TF, and the expression of its members shows which of them is active.
Motif enrichment describes groups of peaks, not single cells. chromVAR estimates the accessibility of each motif in every cell against background peaks with matching GC content and accessibility Schep et al., 2017, but its Python port, pychromVAR, has neither been published nor updated since 2023, so we do not use it here.
We store the peak matrix for the gene regulatory network chapter.
ln.Artifact.from_anndata(
peak_matrix,
key="chromatin_accessibility/pbmc10k_peaks.h5ad",
description="PBMC 10k multiome peak matrix of cell type-specific peaks",
).save()Output
→ returning artifact with same hash: Artifact(uid='cVC0NFWH4GNmOHGK0000', key='chromatin_accessibility/pbmc10k_peaks.h5ad', description='PBMC 10k multiome peak matrix of cell type-specific peaks', suffix='.h5ad', kind='dataset', otype='AnnData', size=589440702, hash='LJhJVBzFJWyHV2LgZbZpG-', n_files=None, n_observations=9255, extra_data=None, branch_id=1, created_on_id=1, space_id=1, storage_id=1, run_id=171, schema_id=None, created_by_id=2, created_at=2026-09-29 15:34:35 UTC, is_locked=False, version_tag=None, is_latest=True); to track this artifact as an input, use: ln.Artifact.get()
Artifact(uid='cVC0NFWH4GNmOHGK0000', key='chromatin_accessibility/pbmc10k_peaks.h5ad', description='PBMC 10k multiome peak matrix of cell type-specific peaks', suffix='.h5ad', kind='dataset', otype='AnnData', size=589440702, hash='LJhJVBzFJWyHV2LgZbZpG-', n_files=None, n_observations=9255, extra_data=None, branch_id=1, created_on_id=1, space_id=1, storage_id=1, run_id=171, schema_id=None, created_by_id=2, created_at=2026-09-29 15:34:35 UTC, is_locked=False, version_tag=None, is_latest=True)- Corces, M. R., Granja, J. M., Shams, S., Louie, B. H., Seoane, J. A., Zhou, W., Silva, T. C., Groeneveld, C., Wong, C. K., Cho, S. W., Satpathy, A. T., Mumbach, M. R., Hoadley, K. A., Robertson, A. G., Sheffield, N. C., Felau, I., Castro, M. A. A., Berman, B. P., Staudt, L. M., … Zhu, J. (2018). The chromatin accessibility landscape of primary human cancers. Science, 362(6413), eaav1898. 10.1126/science.aav1898
- Granja, J. M., Corces, M. R., Pierce, S. E., Bagdatli, S. T., Choudhry, H., Chang, H. Y., & Greenleaf, W. J. (2021). ArchR is a scalable software package for integrative single-cell chromatin accessibility analysis. Nature Genetics, 53(3), 403–411. 10.1038/s41588-021-00790-6
- Zhang, Y., Liu, T., Meyer, C. A., Eeckhoute, J., Johnson, D. S., Bernstein, B. E., Nusbaum, C., Myers, R. M., Brown, M., Li, W., & Liu, X. S. (2008). Model-based Analysis of ChIP-Seq (MACS). Genome Biology, 9(9), R137. 10.1186/gb-2008-9-9-r137
- Weirauch, M. T., Yang, A., Albu, M., Cote, A. G., Montenegro-Montero, A., Drewe, P., Najafabadi, H. S., Lambert, S. A., Mann, I., Cook, K., Zheng, H., Goity, A., van Bakel, H., Lozano, J.-C., Galli, M., Lewsey, M. G., Huang, E., Mukherjee, T., Chen, X., … Hughes, T. R. (2014). Determination and Inference of Eukaryotic Transcription Factor Sequence Specificity. Cell, 158(6), 1431–1443. 10.1016/j.cell.2014.08.009
- Schep, A. N., Wu, B., Buenrostro, J. D., & Greenleaf, W. J. (2017). chromVAR: inferring transcription-factor-associated accessibility from single-cell epigenomic data. Nature Methods, 14(10), 975–978. 10.1038/nmeth.4401