A small, SLURM-native pipeline for running an AlphaFold 3 "pull-down": one bait protein folded against a list of many target (prey) proteins, then scored for interaction with AFM-LIS (the LIS / iLIS metric). It is similar in spirit to AlphaPulldown, but built directly on native AF3 (no AlphaPulldown layer), and optimised for the case where the bait is fixed and only the prey changes.
The key efficiency trick: the bait's MSA (the slow, CPU-heavy step) is computed once and reused for every target, so an N-protein screen costs 1 bait MSA + N target MSAs + N GPU inferences instead of recomputing the bait every time.
This repo is a clean, portable copy of a working pipeline. You will need to (a) install AF3 + databases + weights yourself, (b) clone AFM-LIS yourself, and (c) edit
config.shplus the#SBATCHresource lines to match your cluster. Everything else should run as-is.
af3_pulldown/
├── README.md ← you are here
├── config.example.sh ← copy to config.sh, edit your paths (git-ignored)
├── .gitignore ← keeps weights / databases / secrets / big data out of git
├── scripts/
│ ├── 00_prepare_inputs.py build AF3 input JSONs from a candidate table
│ ├── 01_run_msa_array.sh MSA / data pipeline (CPU array job)
│ ├── 01_submit_msa.sh launcher: runs stages 00 + 01 in one command
│ ├── 02_merge_msa_jsons.py merge bait MSA + each target MSA
│ ├── 03_run_inference_array.sh structure prediction (GPU array job)
│ ├── 04_run_lis_analysis.py LIS / iLIS scoring + per-complex figures
│ ├── 04_submit_lis_analysis.sh SLURM wrapper for stage 04
│ └── 05_plot_summary.py per-run summary heatmaps
├── examples/brca1/ ← worked example: bait + candidate-table format
└── logs/ ← SLURM logs land here (git-ignored)
Stages run in order 00 → 05. The two *_submit_*.sh / 01_submit_*.sh
files are convenience launchers; everything they do can also be done by hand
(each script's header shows the manual command).
┌─────────────────────────────────────────────┐
candidate table ──00──▶ │ inputs/ individual_jsons/ base_jsons/ │
(gene + UniProt) └─────────────────────────────────────────────┘
│ │
bait MSA│ (1×, CPU, stage 01) │ target MSAs (N×, CPU, stage 01)
▼ ▼
msa_outputs/<bait>/ msa_outputs/targets/
└───────────┬─────────────┘
stage 02 │ merge (reuse bait MSA)
▼
inputs/msa_jsons/<complex>_data.json
│
stage 03 │ AF3 inference (N×, GPU)
▼
predictions/<complex>/
│
stage 04 │ AFM-LIS scoring + figures
▼
results/ all_lis_scores.csv, hits...
stage 05 │ summary heatmaps
▼
figures/summary/
Each complex is a two-chain AF3 job: chain A = bait, chain B = target.
| # | Component | Where to get it | Notes |
|---|---|---|---|
| 1 | AlphaFold 3 code | https://github.com/google-deepmind/alphafold3 → docs/installation.md |
Clone + build the conda/Docker env. Provides run_alphafold.py and src/. |
| 2 | AF3 reference databases (~630 GB) | Run AF3's fetch_databases.sh |
Needed for the MSA / data pipeline (stage 01). Big — put on scratch/project storage. |
| 3 | AF3 model weights | Request access via the Google form linked in the AF3 README (DeepMind approval required) | Not redistributable. Never commit them. You'll get af3.bin.zst. |
| 4 | Conda/mamba with the AF3 env | Created during the AF3 install (its environment.yml) |
Same env runs MSA, inference, and LIS scoring (it has numpy + matplotlib). |
| 5 | AFM-LIS scorer | git clone https://github.com/flyark/AFM-LIS |
Pure-Python (numpy/scipy), no build. Point AF3PD_AFMLIS_DIR at it. |
| 6 | A SLURM cluster with CPU partitions (MSA/scoring) and GPU partitions (inference, ≥40 GB GPUs e.g. A100/H100) | your HPC | Internet access on compute nodes is needed for UniProt fetches in stage 00 or run stage 00 on a login node. |
Python deps beyond the AF3 env: numpy, scipy, matplotlib, pandas
(numpy/scipy/matplotlib ship with the AF3 env; pandas is only needed for the
stage 05 summary — pip install pandas if missing).
git clone <your-fork-url> af3_pulldown
cd af3_pulldown
# 1. Clone the AFM-LIS scorer somewhere (next to this repo is fine)
git clone https://github.com/flyark/AFM-LIS
# 2. Create your private config from the template
cp config.example.sh config.sh
# 3. Edit every line marked <<< EDIT >>> in config.sh:
# - AF3 install dir, databases dir, weights dir
# - conda.sh path + env name
# - AF3PD_AFMLIS_DIR → the AFM-LIS clone from step 1
# - AF3PD_DATA_ROOT → where big run data goes (keep OUTSIDE the repo)
# - bait name / UniProt, and your candidate table
$EDITOR config.sh
# 4. Edit the #SBATCH resource lines (partition / GPU type / mem / time) in:
# scripts/01_run_msa_array.sh (CPU)
# scripts/03_run_inference_array.sh (GPU)
# scripts/04_submit_lis_analysis.sh (CPU)
# Look for the "⚠ EDIT ... FOR YOUR CLUSTER ⚠" banners.config.sh is git-ignored, so your private cluster paths never reach GitHub.
All commands are run from the repo root. Replace run1 with any label you
like for this screen; outputs go to $AF3PD_DATA_ROOT/run1/.
bash scripts/01_submit_msa.sh run1This:
- builds the AF3 input JSONs from your candidate table (stage 00), then
- submits the bait MSA (1 CPU task) and the target MSA array (N CPU tasks). It prints both SLURM job IDs and the exact next commands.
Prefer to drive the stages yourself? See each script's header for the manual
sbatchinvocation. Stage 00 alone is just:conda run -n "$AF3PD_CONDA_ENV" python scripts/00_prepare_inputs.py --bait-name "$AF3PD_BAIT_NAME" --bait-uniprot "$AF3PD_BAIT_UNIPROT" --candidates "$AF3PD_CANDIDATES" --output-root "$AF3PD_DATA_ROOT/run1"
Wait for both MSA jobs to finish (squeue -u $USER).
source config.sh
python scripts/02_merge_msa_jsons.py --run run1Produces one merged <complex>_data.json per target under
$AF3PD_DATA_ROOT/run1/inputs/msa_jsons/. The bait MSA is injected into every
one of them (that's the reuse trick).
source config.sh
ROOT="$AF3PD_DATA_ROOT/run1"
N=$(ls "$ROOT/inputs/msa_jsons/"*.json | wc -l)
sbatch --array=0-$((N-1))%${AF3PD_GPU_CONCURRENCY:-4} \
scripts/03_run_inference_array.sh \
"$ROOT/inputs/msa_jsons" "$ROOT/predictions"One GPU task per complex, capped at AF3PD_GPU_CONCURRENCY concurrent. Each
finished complex appears under predictions/<complex>/ with per-seed/per-sample
CIFs and confidence JSONs. Re-running skips complexes that already have a CIF.
# As a SLURM job (recommended):
bash scripts/04_submit_lis_analysis.sh run1
# …or interactively:
source config.sh
python scripts/04_run_lis_analysis.py --run run1 --workers 8
# add --no-figures for CSV-only (faster); --limit 5 to test on 5 complexessource config.sh
python scripts/05_plot_summary.py --run run1 # needs pandas<run>/
├── inputs/
│ ├── individual_jsons/ bait.json + targets/*.json (single-chain, for MSA)
│ ├── base_jsons/ two-chain complex JSONs (reference)
│ ├── msa_jsons/ merged *_data.json (stage 02 output → stage 03 input)
│ ├── sequence_cache/ cached UniProt FASTAs
│ ├── protein_list.tsv manifest of every complex
│ └── run_metadata.json
├── msa_outputs/
│ ├── <bait>/<bait>/<bait>_data.json bait MSA (computed once)
│ └── targets/<complex>_target/... per-target MSAs
├── predictions/<complex>/ AF3 CIFs + confidence JSONs (per seed/sample)
├── results/
│ ├── <complex>_lis_analysis.csv per-complex scores
│ ├── all_lis_scores.csv master table
│ └── hits_ilis_ge_0.223.csv high-confidence hits
└── figures/
├── <complex>/average.png + sample-N.png 6-panel diagnostics
└── summary/<run>_iLIS_categorical.png … per-run heatmaps
The headline metric is iLIS (integrated Local Interaction Score). Per-model false-positive-rate thresholds used by the figures:
| iLIS (per model) | meaning |
|---|---|
| ≥ 0.551 | hit at 1% FPR |
| ≥ 0.339 | hit at 5% FPR |
| ≥ 0.223 | hit at 10% FPR (default hits cutoff) |
| < 0.223 | below threshold |
See the AFM-LIS repo for the full definition of LIS / cLIS / iLIS and the benchmarking behind these thresholds.
To model the bait carrying a post-translational modification (e.g. a phosphosite), pass it at the merge stage so it's written into chain A of every complex (the bait MSA is always run on the unmodified sequence):
python scripts/02_merge_msa_jsons.py --run run1 \
--bait-modifications '[{"ptmType":"SEP","ptmPosition":75}]'SEP = phosphoserine, TPO = phosphothreonine, PTR = phosphotyrosine (CCD
codes). 00_prepare_inputs.py --bait-modifications ... does the same for the
reference complex JSONs.
- Clone AFM-LIS and set
AF3PD_AFMLIS_DIRinconfig.sh. config.sh— every<<< EDIT >>>line (AF3 paths, conda, data root, bait, candidate table).#SBATCHheaders — in01_run_msa_array.sh,03_run_inference_array.sh,04_submit_lis_analysis.sh: set--partition, GPU--gres=gpu:<type>:1,--mem,--cpus-per-task,--time, and (if your cluster needs it)--account/--qos. Look for the ⚠ banners.- Concurrency —
AF3PD_MSA_CONCURRENCYandAF3PD_GPU_CONCURRENCYinconfig.sh(the%Narray throttles). Set the GPU one to how many GPUs you may use at once. libcifpp— some AF3 builds needLIBCIFPP_DATA_DIR. If yours errors on CCD data, setAF3PD_LIBCIFPP_DATA_DIRinconfig.sh; otherwise leave it empty.- Logs — SLURM
--outputpaths arelogs/...relative to the submit dir, so always submit from the repo root.logs/already exists. - Internet for UniProt — stage 00 fetches missing sequences from
rest.uniprot.org. If compute nodes are offline, run stage 00 on a login node (it's fast), or add asequencecolumn to your candidate table.
See examples/brca1/ for the expected candidate-table format. Start with a
small bait + a handful of targets to smoke-test your cluster wiring before
scaling up.
- No AF3 model weights and no databases — they are large and
non-redistributable; you obtain them yourself (see Requirements).
.gitignoreblocks*.bin.zst,af3_weights/,public_databases/, etc. - No third-party code — AFM-LIS is cloned separately (not bundled), so it stays on its own license/version and isn't re-hosted here.
- No API keys / secrets — this pipeline needs none (UniProt's public REST
endpoint requires no key).
.gitignorestill blocks*.key,*.env,*secret*,*.token, … as a safety net. - No private cluster paths — all live in
config.sh, which is git-ignored. The committedconfig.example.shuses placeholder/path/to/...values. - No large run data —
inputs/,msa_outputs/,predictions/,results/,figures/are git-ignored.
Before the first push, double-check:
git status # config.sh should NOT appear
git ls-files | grep -iE 'weights|\.bin|secret|\.key|config\.sh' || echo "clean"- AlphaFold 3 — Google DeepMind. Code and weights are governed by DeepMind's terms; review them before use/publication.
- AFM-LIS (LIS / iLIS scoring) — Ah-Ram Kim et al., MIT-licensed, used here as an external dependency (clone from https://github.com/flyark/AFM-LIS). Cite Kim et al. (2024, 2026) if you use the LIS/iLIS scores.
- This wrapper pipeline: use/adapt freely for your screens.