ColabDesign

repository·main·Indexed 21 days ago

https://github.com/sokrypton/colabdesign

A protein design framework featuring AfDesign, built on AlphaFold to enable fixed backbone design, protein hallucination, binder design, and partial scaffolding/loop extension. The library includes a JAX implementation of ProteinMPNN for sequence sampling and scoring, as well as a work-in-progress JAX implementation of the MSA Transformer. It supports various optimization methods, including continuous, discrete, and hybrid gradient-based pipelines, and integrates with Optax for optimizer configuration.

Tokens
35.1K
Snippets
103
Records
119
Agent score
76%

What's inside colabdesign

  1. Overview of AfDesign core modules

    main

    AfDesign is organized into several functional modules that handle different stages of the protein design pipeline. Understanding these modules helps in navigating the codebase for customization or debugging:

    • model.py: Used to configure the model architecture and parameters.
    • inputs.py: Used to configure the input data and features.
    • loss.py: Used to configure the loss functions used during optimization.
    • prep.py: Handles the preparation of features.
    • design.py: Implements the gradient update loop for protein design.
    • utils.py: Contains various utility tools for saving results and plotting data.
  2. Revert to legacy settings (pre-June 2022)

    main

    If you require the default weights and settings used before the June 19, 2022 update, use the following configurations after prepping your model. These settings adjust the weights for various loss components (like pae, plddt, con, i_pae, i_con) and optimization parameters.

    # For fixbb:
    model.set_weights(dgram_cce=1, pae=0.1, plddt=0.1)
    model.design_3stage()
    
    # For hallucination:
    model.set_seq(mode="gumbel")
    model.set_weights(pae=1, plddt=1, con=0.5)
    model.set_opt("con", binary=True, cutoff=21.6875, num=model._len, seqsep=0)
    model.design_2stage(100, 100, 10)
    
    # For binder hallucination:
    model.set_weights(plddt=0.1, pae=0.1, i_pae=1.0, con=0.1, i_con=0.5)
    model.set_opt("con", binary=True, cutoff=21.6875, num=model._binder_len, seqsep=0)
    model.set_opt("i_con", binary=True, cutoff=21.6875, num=model._target_len)
    model.design_3stage(100, 100, 10)
  3. Evaluate ProteinMPNN sequences with AlphaFold

    main

    To validate sequences generated by ProteinMPNN, you can use the AlphaFold model (mk_af_model).

    1. Download AlphaFold parameters:
    mkdir params
    curl -fsSL https://storage.googleapis.com/alphafold/alphafold_params_2022-03-02.tar | tar x -C params
    1. Run prediction loop:
    from colabdesign.af import mk_af_model
    
    # Initialize AF model
    af_model = mk_af_model()
    af_model.prep_inputs(pdb_filename="tmp.pdb")
    
    # Iterate through samples from MPNN
    for n, S in enumerate(samples["S"]):
        # S.argmax(-1) converts logits to sequence
        af_model.predict(seq=S.argmax(-1))
        af_model.save_current_pdb(f"{n}.pdb")
    from colabdesign.af import mk_af_model
    af_model = mk_af_model()
    af_model.prep_inputs(pdb_filename="tmp.pdb")
    for n,S in enumerate(samples["S"]):
      af_model.predict(seq=S.argmax(-1))
      af_model.save_current_pdb(f"{n}.pdb")
  4. Run a basic ProteinMPNN sequence sampling workflow

    main

    To perform basic protein sequence redesign using ProteinMPNN, initialize the model with mk_mpnn_model, prepare the inputs using a PDB file, and then sample sequences.

    from colabdesign.mpnn import mk_mpnn_model
    mpnn_model = mk_mpnn_model()
    mpnn_model.prep_inputs(pdb_filename="tmp.pdb")
    samples = mpnn_model.sample_parallel()
  5. Use the MSA TRANSFORMER in JAX via Colab

    main

    The esm_msa module provides a JAX implementation of the MSA (Multiple Sequence Alignment) Transformer. Note that this code is currently a work-in-progress. You can access a functional example and notebook via Google Colab to explore the implementation and its usage.

    https://colab.research.google.com/github/sokrypton/ColabDesign/blob/v1.1.1/esm_msa/example.ipynb
  6. Install AfDesign (ColabDesign)

    main

    To use AfDesign, you must first install JAX with CUDA support, then install the colabdesign package from GitHub. You also need to download the AlphaFold weights into a params directory.

    By default, mk_afdesign_model() expects the weights to be in the current directory (data_dir="."). You can override this by providing a specific data_dir path during model initialization.

    # 1. Install JAX with CUDA support
    pip install "jax[cuda]" -f https://storage.googleapis.com/jax-releases/jax_cuda_releases.html
    
    # 2. Install colabdesign
    pip install git+https://github.com/sokrypton/ColabDesign.git@v1.1.1
    
    # 3. Download AlphaFold weights
    mkdir params
    curl -fsSL https://storage.googleapis.com/alphafold/alphafold_params_2022-12-06.tar | tar x -C params
    # Overriding the default data directory
    model = mk_afdesign_model(..., data_dir="/location/of")
  7. Choose an AfDesign optimization strategy

    main

    AfDesign supports several optimization methods for sequence design. The choice of optimizer affects whether the output is a valid discrete sequence or a continuous probability profile (PSSM).

    Optimization Types

    • pssm_semigreedy (Recommended): Uses a designed PSSM to bias a semi-greedy optimization.
    • 3stage: A gradient-based optimization (GD) following the sequence: logits $\rightarrow$ soft $\rightarrow$ hard.
    • pssm: GD optimization (logits $\rightarrow$ soft) to generate a sequence profile (PSSM).
    • semigreedy: Attempts random mutations and accepts those that decrease loss.
    • logits: GD optimization of continuous logits.
    • soft: GD optimization of softmax(logits) (probabilities).
    • hard: GD optimization of one_hot(logits) (discrete).

    WARNING: Optimizers like pssm, logits, and soft do not produce a valid one-hot sequence directly. To obtain a valid sequence, use the other optimizers or redesign the output backbone using a tool like ProteinMPNN.

  8. Generate RFdiffusion blueprints (Manual vs Automated)

    main

    RFdiffusion requires a 'blueprint' to define the desired secondary structure elements (SSEs) and their interactions. You can generate these in two ways:

    1. Manual Mode: You define the number of SSE elements. You then specify the type for each element (Diagonal: H for helix, E for sheet, C for coil, ? for undefined) and the interactions between them (Off-diagonal: 0 for no contact, 1 for contact, ? for undefined). You also specify the length of each SSE and a buff_length (buffer) between them.
    2. Automated Mode: You provide an existing PDB file. The system extracts the secondary structure and contact map from the PDB to create the blueprint automatically.

    SSE Types:

    • H: Helix
    • E: Sheet
    • C: Coil
    • ?: Undefined
    # Automated mode example
    # blueprint_mode = "automated"
    # pdb = "6MRR"
    # chain = "A"
    # trim_loops = True
    
    # Manual mode example
    # blueprint_mode = "manual"
    # elements = 5
  9. Configure RFdiffusion contigs for different design modes

    main

    RFdiffusion uses contigs strings to define the structural constraints of the design. The syntax uses : to separate multiple contigs and / to define segments within a single contig.

    Unconditional Design

    • Monomer: contigs='100' (diffuse a single chain of length 100).
    • Hetero-oligomer: contigs='50:100' (diffuse two chains of lengths 50 and 100).
    • Homo-oligomer: contigs='50' with copies=2 (diffuse two copies of a 50-residue chain with symmetry).

    Binder Design

    • Targeted Binder: contigs='A:50' with pdb='4N5T' (diffuse a 50-residue binder to chain A of the provided PDB).
    • Hotspot-targeted Binder: contigs='E6-155:70-100' with pdb='5KQV' and hotspot='E64,E88,E96' (diffuse a binder of length 70-100 to chain E, targeting specific residues).

    Motif Scaffolding

    • Loop Scaffolding: contigs='40/A163-181/40' with pdb='5TPN' (diffuse a 40-residue loop between two segments of the PDB).
    • Segment Scaffolding: contigs='A3-30/36/A33-68' with pdb='6MRR' (diffuse a 36-residue loop between two specific PDB ranges).

    Partial Diffusion

    • Full Noise: contigs='' with pdb='6MRR' (noise all coordinates).
    • Fixed Segment: contigs='A1-10' with pdb='6MRR' (keep first 10 positions fixed, noise the rest).
    • Fixed Chain: contigs='A' with pdb='1SSC' (fix chain A, noise the rest).

    Tips

    • Use a dash for ranges: contigs='50-100' samples lengths within that range.
    • Leave pdb='' blank to trigger an upload prompt.
    # Examples of contig syntax
    contigs='100'           # Monomer
    contigs='50:100'       # Hetero-oligomer
    contigs='A:50'         # Binder to chain A
    contigs='40/A163-181/40' # Motif scaffolding
    contigs='A1-10'        # Partial diffusion (fixed residues)
  10. Partial Hallucination with Custom Loss

    main

    Partial hallucination mixes supervised (fixbb) and unsupervised (hallucination) losses. This allows you to constrain parts of the sequence/structure while allowing others to be hallucinated.

    Key features:

    • loss_callback: Pass a function to define custom losses (e.g., Radius of Gyration).
    • pos: Define specific residue positions to constrain in prep_inputs.
    • rewire: Define loop lengths between constrained segments.
    • restart(mode=["soft", "gumbel", "wildtype"]): A hybrid initialization mode.
    import jax
    import jax.numpy as jnp
    from colabdesign import mk_afdesign_model, clear_mem
    from colabdesign.af.alphafold.common import residue_constants
    
    # Define a custom Radius of Gyration (rg) loss
    def rg_loss(inputs, outputs):
        positions = outputs["structure_module"]["final_atom_positions"]
        ca = positions[:, residue_constants.atom_order["CA"]]
        center = ca.mean(0)
        rg = jnp.sqrt(jnp.square(ca - center).sum(-1).mean() + 1e-8)
        rg_th = 2.38 * ca.shape[0] ** 0.365
        rg = jax.nn.elu(rg - rg_th)
        return {"rg": rg}
    
    clear_mem()
    # Initialize partial model
    af_model = mk_afdesign_model(
        protocol="partial",
        loss_callback=rg_loss,
        use_templates=False
    )
    
    # Set weight for the custom loss
    af_model.opt["weights"]["rg"] = 0.1
    
    # Prepare inputs with constraints
    af_model.prep_inputs(
        pdb_filename="6MRR",
        chain="A",
        pos="3-30,33-68",  # Constrain these positions
        length=100
    )
    
    # Set loop length between segments
    af_model.rewire(loops=[36])
    
    # Hybrid initialization and design
    af_model.restart(mode=["soft", "gumbel", "wildtype"])
    af_model.design_3stage(100, 100, 10)
  11. Design Heterodimeric Protein Complexes

    main

    To design heterodimers (two different chains), use a custom loss_callback to penalize the radius of gyration (rg) of each chain independently. This ensures both protomers are compact. After design, use a 'Homooligomer Filter' to verify that each protomer can fold independently and that they correctly form the intended heterodimer without unintended homooligomerization.

    # 1. Define heterodimer loss
    def hd_loss(inputs, outputs):
        positions = outputs["structure_module"]["final_atom_positions"]
        ca1 = positions[:LENGTH1, residue_constants.atom_order["CA"]]
        ca2 = positions[LENGTH2:, residue_constants.atom_order["CA"]]
        # ... calculate rg for ca1 and ca2 ...
        return {"hd": rg1 + rg2}
    
    # 2. Initialize and design
    clear_mem()
    af_model = mk_afdesign_model(protocol="hallucination", loss_callback=hd_loss)
    af_model.prep_inputs(length=LENGTH1 + LENGTH2)
    af_model.restart(mode=["gumbel", "soft"])
    af_model.opt["weights"]["hd"] = 0.1
    af_model.design_logits(100)