MCPcopy Index your code
hub / github.com/SantiagoMille/germinal

github.com/SantiagoMille/germinal @main

Chat with this repo
repository ↗ · DeepWiki ↗ · + Follow
1,153 symbols 3,280 edges 120 files 553 documented · 48% updated 2mo ago★ 25010 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Germinal: Efficient generation of epitope-targeted de novo antibodies

Germinal Banner

Germinal is a pipeline for designing de novo antibodies against specified epitopes on target proteins. The pipeline follows a 3-step process: hallucination based on ColabDesign, selective sequence redesign with AbMPNN, and cofolding with a structure prediction model. Germinal is capable of designing both nanobodies and scFvs against user-specified residues on target proteins.

We describe Germinal in the preprint: "Efficient generation of epitope-targeted de novo antibodies with Germinal"

⚠️ We are still actively working on code improvements See our recommendations/tips. The Protenix and AbLang integrations are under active development — if you run into any issues please open a GitHub issue.

Last user-validated commit: 2c0a13b (PR #61 "Fix tokenizer for IgLM"). Commits after this point have been runtime- and review-validated separately on branch fix/post-pr67-review.

Important changes since 2c0a13b

The commits below are bundled in PRs #55, #64, #67, #68, #69, #70 (merged) plus the in-flight branch fix/post-pr67-review (~22 follow-up fixes). User-visible behavior changes you should know about:

New features / config knobs

  • Protenix structure model (PR #55): structure_model: "protenix" is now fully supported alongside af3 and chai. Set protenix_conda_env and protenix_model_name in your run config.
  • AbLang language model (PR #55, #64, #68): ablm_model: "ablang" is now available alongside iglm. Method controlled by ablm_method ("pll" default, or "unmasked").
  • MSA mode "target" is the default for AF3/Protenix runs — MSA generated only for the target. Use msa_mode: "colabfold" for a real binder MSA.
  • Binder MSA caching (cache_binder_msa: true) — reuses the first binder's ColabFold MSA across all subsequent designs by rewriting only the query line. Requires msa_mode: "colabfold"; raises ValueError otherwise.
  • AF3/Protenix sample selection (af3_structure_select_mode): pick the "best" (highest ranking_score) or "worst" AF3/Protenix sample.
  • Multi-relax ensemble (multi_relax: true, n_relax: 5, relax_score_mode: "average"|"best"): post-prediction PyRosetta relax can now spawn N parallel relaxes and aggregate their interface scores.
  • VL-first scFv (PR #67): scFv runs with vh_first: false now correctly identify H-CDR3 from the last CDR (was previously mis-sliced into VL).

Behavior changes / safer defaults

  • evaluate_filters fail-loud on None metrics: any filter whose metric is None (e.g. Protenix without full_data) now FAILS the filter loudly instead of silently passing. If you relied on the old silent-pass, either fix the upstream metric or remove the filter.
  • AbMPNN pipeline failures abort the run: previously, an AbMPNN worker crash returned ([], False) and the trajectory loop continued silently. Now a [ABMPNN PIPELINE FATAL] message is printed and the job exits so the underlying issue can be diagnosed.
  • Parallel-relax worker exceptions are surfaced: _relax_worker now writes a traceback to {pdb}.err; pr_relax_parallel reads and prints it inside a [RELAX ERROR] block.
  • Unknown grad_merge_method defaults to pcgrad with a [CONFIG WARNING] (was: silent drop of the AbLang/IgLM gradient).
  • get_grad_mlm removed from colabdesign.ablang (CUDA RNG state leak; callers should use method="pll" or method="unmasked").

Bug fixes (silent correctness issues)

  • Chai cdr3_idx now uses the correct H3 residue (PR #67 + follow-up): both the CDR-position selection (PR #67) and the 0→1-indexed PDB residue number conversion are now correct. scFv × Chai × VL-first × hotspot runs were previously pinned one residue away from H3.
  • Protenix binder MSA: _get_or_generate_msas now generates a real binder MSA when msa_mode in {"local", "colabfold"} (was target-only regardless).
  • _unwrap recursion: handles arbitrary depth of single-element list wrapping in Protenix's tensor serialization (was: [[scalar]][scalar]).
  • interface_cdrs zero-division guard: empty interface no longer kills the trajectory after structure prediction completed.
  • idx_from_ranges empty input: returns [] instead of IndexError.
  • lm_ll = -100 sentinel for unknown ablm_model (was -1, easily confused with a real bad pseudolikelihood).
  • Chai tmp_dir mkdir(exist_ok=True) to survive hash collisions.
  • pDockQ2 chain-keying (drop buggy per-chain aggregation, use ipsae's scalar pdockq2/LIS directly).
  • AbLang+IgLM ablm_method AttributeError (PR #69 follow-up): defensive getattr(..., None) for models that don't set this attribute.

Config additions you should review

All five tracked configs in configs/run/ now expose: - multi_relax, n_relax, relax_score_mode (only scfv_pdl1.yaml had these before) - cache_binder_msa (was missing everywhere) - ablm_model is now present in vhh_il3.yaml (was missing → KeyError)

Contents

Setup

Requirements

Prerequisites: - PyRosetta (academic license required) - ColabDesign/AlphaFold-Multimer parameters (click link for download or see below for cli) - AlphaFold3 parameters (optional) - JAX with GPU support

System Requirements: - GPU: NVIDIA GPU with CUDA support - Memory: 40GB+ VRAM - Storage (recommended)*: 50GB+ space for results

*The pipeline has been tested on: A100 40GB, H100 40GB MIG, L40S 48GB, A100 80GB, and H100 80GB. These runs tested a 130 amino acid target with a 131 amino acid nanobody. For larger runs, we recommend 60GB+ VRAM.

Installation

  1. Ensure you have an NVIDIA GPU with a recent driver (recommended CUDA 12+). You can verify with: bash nvidia-smi
  2. Install Miniconda or Anaconda if not already available.

  3. Follow the instructions in environment_setup.md

  4. Copy AlphaFold-Multimer parameters to params/ and untar them. Alternatively, you can run the following lines inside params/ to download and untar: bash aria2c -x 16 https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar tar -xf alphafold_params_2022-12-06.tar -C .

  5. Activate the environment: bash conda activate germinal

  6. (Optional) Run validation at any time to ensure all packages have installed correctly: bash python validate_install.py

Notes: - AlphaFold-Multimer and AlphaFold3 parameters are large and must be downloaded manually.

Docker

Germinal can be run using Docker:

docker build -t germinal .
docker run -it --rm --gpus all \
  -v "$PWD/results:/workspace/results" \
  -v "$PWD/pdbs:/workspace/pdbs" \
  germinal bash

and Singularity (shown)/Apptainer:

mkdir -p results
singularity pull germinal.sif docker://jwang003/germinal:latest
singularity shell --nv \
  --bind "$PWD/results:/workspace/results" \
  --bind "$PWD/pdbs:/workspace/pdbs" \
  --pwd /workspace \
  germinal.sif

Note: Pulling may hang on Creating SIF file... If so, check if the command is done with singularity exec germinal.sif python -c "print('ok')"

Volumes are mounted to save generated input complexes and results from sampling.

Once inside the container you can test:

python run_germinal.py

Usage

Quick Start

The main entry point to the pipeline is run_germinal.py. Germinal uses Hydra for orchestrating different configurations. An example main configuration file is located in configs/config.yaml. This yaml file contains high level run parameters as well as pointers to more granular configuration settings.

These detailed options are stored in four main settings files:

  • Main run settings: configs/run/vhh.yaml
  • Target settings: configs/target/[your_target].yaml
  • Post-hallucination (initial) filters: configs/filter/initial/[vhh/scfv].yaml
  • Final filters: configs/filters/final/[vhh/scfv].yaml

Configuration Structure (example)

configs/
├── config.yaml              # Main configuration yaml
├── run/                     # Main run settings
│   ├── vhh.yaml             # Example VHH (nanobody) settings
│   └── ...                  # Other settings
├── target/                  # Target protein configurations
│   ├── pdl1.yaml            # PDL1 target example
│   └── ...                  # other targets
└── filter/                  # Filter configurations
    ├── initial/
    │   ├── vhh.yaml         # Post-hallucination (initial) filters
    │   └── ...
    └── final/
        ├── vhh.yaml         # Final acceptance filters
        └── ...        

To design nanobodies targeting PD-L1 using default configs (with chai as the default structure predictor):

python run_germinal.py

To design scFvs targeting PD-L1 using default configs:

python run_germinal.py run=scfv filter/initial=scfv filter/final=scfv

Note: Default configs are not meant to work well out of the box but rather be a set of reasonable default parameters that we used as a starting point for parameter exploration and sweep experiments.

If you wish to change the configuration of runs, you can:

  • create an entirely new config yaml
  • swap one of the four main settings files
  • pass specific overrides

Basic Usage

Run with defaults:

python run_germinal.py

Switch to a different run config (e.g., new_config):

python run_germinal.py run=new_config

Use different target:

python run_germinal.py target=my_target

Use a different config file with Hydra:

python run_germinal.py --config_name new_config.yaml

Use different filters:

python run_germinal.py filter/initial=new_init_filter filter/final=new_final_filter

CLI Overrides

Hydra provides powerful CLI override capabilities. You can override any parameter in any configuration file.

!NOTE Settings in configs/run/ folder use the global namespace and do not need a run prefix before overriding. See example below.

Basic parameter overrides:

# Override trajectory limits
python run_germinal.py max_trajectories=100 max_passing_designs=50

# Override experiment settings
python run_germinal.py experiment_name=my_experiment run_config=test_run

# Override loss weights. Note: no run prefix since run settings are global
python run_germinal.py weights_plddt=1.5 weights_iptm=0.8 

Filter threshold overrides:

# Make initial filters less stringent
python run_germinal.py filter.initial.clashes.value=2

# Adjust final filter thresholds
python run_germinal.py filter.final.external_plddt.value=0.9 filter.final.external_iptm.value=0.8

# Change filter operators
python run_germinal.py filter.final.sc_rmsd.operator='<=' filter.final.sc_rmsd.value=5.0

Target configuration overrides:

# Change target hotspots
python run_germinal.py target.target_hotspots=\'A26,A30,A36,A44\'

# Use different PDB file
python run_germinal.py target.target_pdb_path=\'pdbs/my_target.pdb\' target.target_name=\'my_target\'

Complex multi-parameter overrides:

# Complete scFv run with custom settings
python run_germinal.py \
  run=scfv \
  target=pdl1 \
  max_trajectories=500 \
  experiment_name=\'scfv_pdl1_test\' \
  target.target_hotspots=\'A37,A39,A41\' \
  filter.final.external_plddt.value=0.85 \
  weights_iptm=1.0

Target Configuration

For each new target, you will need to define a target settings yaml file which contains all relevant information about the target protin. Here is an example:

target_name: "pdl1"
target_pdb_path: "pdbs/pdl1.pdb"
target_chain: "A"
binder_chain: "B"
target_hotspots: "25,26,39,41"
dimer: false  # support coming soon!
length: 133

Filters Configuration

There are two sets of filters: post-hallucination (initial) filters and final filters. The post-hallucination filters are applied after the hallucination step to determine which sequences to proceed to the redesign step. This filter set is a

Core symbols most depended-on inside this repo

get
called by 166
colabdesign/colabdesign/shared/utils.py
zeros
called by 150
colabdesign/colabdesign/af/alphafold/model/geometry/vector.py
split
called by 81
colabdesign/colabdesign/shared/prng.py
split
called by 49
colabdesign/colabdesign/af/alphafold/model/prng.py
get
called by 46
colabdesign/colabdesign/af/alphafold/model/prng.py
add
called by 39
colabdesign/colabdesign/tr/legacy/utils.py
norm
called by 22
colabdesign/colabdesign/af/alphafold/model/geometry/vector.py
cross
called by 20
colabdesign/colabdesign/af/alphafold/model/geometry/vector.py

Shape

Function 567
Method 461
Class 125

Languages

Python99%
TypeScript1%

Modules by API surface

colabdesign/colabdesign/af/alphafold/model/modules.py80 symbols
colabdesign/colabdesign/mpnn/legacy/modules.py34 symbols
colabdesign/colabdesign/af/alphafold/model/folding_multimer.py34 symbols
colabdesign/colabdesign/af/loss.py33 symbols
colabdesign/colabdesign/mpnn/modules.py32 symbols
colabdesign/colabdesign/af/alphafold/model/modules_multimer.py30 symbols
colabdesign/colabdesign/af/design.py29 symbols
colabdesign/colabdesign/af/alphafold/model/r3.py29 symbols
colabdesign/colabdesign/af/alphafold/model/folding.py29 symbols
colabdesign/colabdesign/af/alphafold/model/all_atom_multimer.py29 symbols
colabdesign/colabdesign/tr/legacy/utils.py27 symbols
colabdesign/colabdesign/af/alphafold/model/geometry/vector.py27 symbols

For agents

$ claude mcp add germinal \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page