Inside every cell, long DNA molecules are organised into 3D structures by cohesin, a ring-shaped protein that pulls DNA through itself, extruding a growing loop. CTCF proteins act as roadblocks — cohesin stops when it runs into a CTCF site from the correct direction. The pattern of where cohesin stops determines which genomic regions contact each other, measurable by Hi-C.
ChromSimPipe is a physics-based polymer simulation framework for testing mechanistic hypotheses about 3D chromatin organisation. Given CTCF binding data (CUT&Tag or ChIP-seq peaks) and Hi-C maps as input, it simulates cohesin loop extrusion under different parameter conditions and compares the resulting contact maps to your experimental Hi-C.
Included example. The default configuration ships with an example from the STRS project (Flores et al. 2026): HEK293T cells under hyperosmotic stress (sorbitol treatment), comparing control vs. sorbitol CTCF CUT&Tag peaks against matched Hi-C maps. Swap in your own data and the pipeline runs the same way.
If you want a line-by-line walkthrough of every script, read
CODE_GUIDE.md or CODE_GUIDE.pdf.
CTCF peaks (CUT&Tag / ChIP-seq) Experimental Hi-C (.hic maps)
condition A + condition B condition A + condition B
│ │
▼ ▼
data/ctcf_beds/*.bed data/mcool/*.cool
(oriented CTCF sites, (1 kb contact maps; converted by hic2cool)
from FIMO JASPAR MA0139.1)
│ │
└──────────────┬────────────────────────┘
▼
configs/parameters.py
(N conditions × active locus)
│
▼
GPU polymer simulation (polychrom / OpenMM)
SLURM jobs: N conditions × reps × shards
│
▼
results/polychrom_3d/merged_*/
│
▼
scripts/run_analysis_all.py
(contact map, P(s), APA, MSD,
experimental Hi-C comparison)
│
▼
results/analysis/*.npy, *.png
The default configs/parameters.py defines five conditions for the STRS
hyperosmotic-stress example (HEK293T cells, hg38). To define your own
conditions, edit SIMULATION_CONDITIONS in configs/parameters.py.
| # | Name | Cohesin params | CTCF sites | Compare vs | Question |
|---|---|---|---|---|---|
| 1 | control_ctcf-control |
Gabriele 2022 | Control CUT&Tag | Control Hi-C | Baseline: can we reproduce untreated Hi-C? |
| 2 | control_ctcf-sorbitol |
Gabriele 2022 | Sorbitol CUT&Tag | Sorbitol Hi-C | Does CTCF loss alone explain sorbitol Hi-C? |
| 3 | weak_ctcf-sorbitol |
Gabriele 2022 (0.5× CTCF capture) | Sorbitol CUT&Tag | Sorbitol Hi-C | Weaker CTCF stalling at retained sites? |
| 4 | sorbitol_promoter-stall |
Gabriele 2022 | Sorbitol + promoter (SP/KLF) | Sorbitol Hi-C | Key test: promoter-anchored cohesin? |
| 5 | sorbitol_promoter-stall_long |
Gabriele 2022 (2× processivity) | Sorbitol + promoter | Sorbitol Hi-C | Same + longer processivity? |
The default configuration ships four ~2 Mb loci from the STRS paper figures.
Change ACTIVE_LOCUS in configs/parameters.py to switch loci, or add your own.
| Key | Chrom | Window | Genes |
|---|---|---|---|
chr1_fig1 |
chr1 | 64.2 – 66.2 Mb | JAK1 / AK4 / LEPR |
chr4_fig1 |
chr4 | 1.7 – 3.7 Mb | RNF4 / ADD1 / HTT |
chr6_fig1 |
chr6 | 124.1 – 126.1 Mb | NKAIN2 / RNF217 |
chr16_sox8 |
chr16 | 0.4 – 2.3 Mb | SOX8 |
- Longleaf HPC account with access to
rc_dphansti_piallocation .hicHi-C maps and CTCF peak.narrowPeakfiles for your experiment (the defaults point to~/projects/STRSfor the included example)module load anaconda/2024.02available (already on Longleaf)- GPU partition access (
general+gpu)
cd ~/projects/ChromSimPipe # or wherever you cloned it
# 1. Edit config/ChromSimConfig.yaml to point at your Hi-C and CTCF data.
nano config/ChromSimConfig.yaml
# 2. Edit ChromSimSamplesheet.txt with your CTCF peak file paths.
nano ChromSimSamplesheet.txt
# 3. Edit profiles/slurm/config.yaml to set your SLURM account.
nano profiles/slurm/config.yaml # change slurm_account
# 4. Optionally change the locus in ChromSimConfig.yaml (default: chr1_fig1)bash setup_data.shThis script reads all paths from config/ChromSimConfig.yaml and
ChromSimSamplesheet.txt, then:
- Creates
cohesin_simconda env (polychrom, cooler, hic2cool, numpy, scipy, matplotlib) - Creates
ctcf_extractionconda env (MEME/FIMO, bedtools, samtools) - Converts input
.hicfiles →.coolat 1 kb resolution (single-resolution cooler) - Extracts and orients CTCF sites from CUT&Tag peaks via FIMO
- Validates the resulting BED files
Takes ~20–30 minutes total (mostly conda + FIMO).
sbatch ChromSimPipe.shThat's it. ChromSimPipe.sh submits itself as a SLURM job, sets up a Python venv
with Snakemake, and launches the full DAG via snakemake-executor-plugin-slurm.
Each rule becomes its own SLURM job with the right resources (GPU for
simulation, CPU for everything else).
convert_hic (×2)
→ extract_ctcf (×2)
→ validate_ctcf
→ simulate_shard (×60: 5 cond × 3 rep × 4 shards, GPU)
→ merge_shards (×15: 5 cond × 3 rep)
→ analyze_all (×5: one per condition)
bash ChromSimPipe.sh --dry-runPrints all rules and shell commands that would be submitted — nothing runs.
# Edit configs/parameters.py:
ACTIVE_LOCUS = "chr4_fig1" # or chr6_fig1, chr16_sox8
# Re-run setup for the new locus CTCF beds, then relaunch:
bash setup_data.sh --skip-envs # skips conda env creation
sbatch ChromSimPipe.shbash unlock.sh # release Snakemake lock
sbatch ChromSimPipe.sh --rerun-incomplete # (--rerun-incomplete is the default)data/
├── hic/ # symlinks to input .hic files
├── mcool/
│ ├── condition_A.cool # converted by convert_hic rule (single-resolution)
│ └── condition_B.cool
└── ctcf_beds/
├── ctcf_oriented_hg38_condA_{chrom}_{start}_{end}.bed
└── ctcf_oriented_hg38_condB_{chrom}_{start}_{end}.bed
results/
├── polychrom_3d/
│ ├── {params}_ctcf-{type}_rep{N}_shard{M}/ # raw GPU output (per shard)
│ │ ├── params.json
│ │ └── blocks_*.h5
│ └── merged_{params}_ctcf-{type}_rep{N}/ # merged by merge_shards rule
│ ├── params.json
│ └── blocks_*.h5
│
├── analysis/{condition}/ # per-condition analysis outputs
│ ├── *_contact_map.npy
│ ├── *_ps_curve.npz
│ ├── *_sim_vs_exp_map.png
│ ├── *_msd_*.png / .npz
│ └── ...
│
├── figures/ # contact map panels
│
└── .sentinels/ # Snakemake tracking files (safe to ignore)
| File | Purpose |
|---|---|
ChromSimPipe.sh |
sbatch entry point — run this to launch the pipeline |
unlock.sh |
Release Snakemake lock after a failed run |
workflows/ChromSimPipe.snakefile |
Full DAG definition (6 rules) |
profiles/slurm/config.yaml |
SLURM executor defaults (account, partitions, memory) |
config/ChromSimConfig.yaml |
Path + condition configuration (edit before first run) |
ChromSimSamplesheet.txt |
CTCF peak file paths (one row per condition) |
The default parameter set is derived from Gabriele et al. 2022 (Science)
single-molecule imaging in mESCs. Adjust SIMULATION_CONDITIONS in
configs/parameters.py for your biological context.
| Parameter | Default value | Meaning |
|---|---|---|
lifetime |
75 steps | ~150 kb processivity at 1 kb/monomer |
separation |
240 monomers | ~8 cohesin rings per 2 Mb locus |
ctcf_capture |
0.125 | 12.5% stalling probability per CTCF encounter |
ctcf_release |
0.0033 | Stalled cohesin lives ~4× longer than free cohesin |
The 2 Mb locus (~2000 monomers) is simulated as 28 tiled copies on a 70,000-monomer "chromosome" (2500 monomers/tile = 2000 locus + 250 padding each side). This gives 28× more contact statistics per GPU run. Reference: Yang et al. 2023 Nat Commun.
| Symptom | Likely cause | Fix |
|---|---|---|
ImportError: polychrom |
cohesin_sim env not built |
Run bash setup_data.sh |
CUDA not available |
Wrong SLURM partition | GPU jobs need --partition=gpu --gpus=1 (set automatically by Snakemake) |
| Snakemake lock error | Previous run crashed | Run bash unlock.sh then resubmit |
| CTCF BED file not found | setup_data.sh not run or CTCF extraction failed |
Check logs/setup_data*.log |
| No peaks file in samplesheet | Wrong data path | Edit ChromSimSamplesheet.txt with correct absolute paths |
KeyError: 'CTCF_Type' in samplesheet |
TSV format issue | File must be tab-separated with headers CTCF_Type and CTCF_Peaks_Path |
hic2cool fails |
.hic file not found |
Check config/ChromSimConfig.yaml paths for hic_control/hic_sorbitol |
| Analysis fails with "No results found" | Merge step incomplete | Check results/polychrom_3d/ for merged_* directories |
For the full codebase walkthrough, see CODE_GUIDE.md.
- Flores et al. 2026 — STRS paper. GEO: GSE310051 (Hi-C), GSE310047 (CUT&Tag).
- Fudenberg et al., Cell Reports 15:2038–2049 (2016). Canonical loop-extrusion model.
- Banigan et al., eLife 9:e53558 (2020). LEF dynamics and CTCF barriers.
- Gabriele et al., Science 376:496–501 (2022). Live-cell cohesin imaging in mESCs (parameter source).
- Yang et al., Nat Commun 14:1913 (2023). Tiling trick for convergence.
- Amat et al., Genome Res 29:18–28 (2019). Hi-C under NaCl osmotic stress.
- Rao et al., Cell 171:305–320 (2017). Acute cohesin loss abolishes loops.