Properties Before Structure: A Three-Stage Campaign Ordered by Cost

Run cheap stability and solubility filters across your full library first. Spend the structural prediction budget only on sequences that survive.




What you'll learn:

  • Why pipeline order matters: cheap predictions first, expensive validation last
  • Filtering a designed library by melting temperature and solubility
  • Using Boltz-2 (no-MSA) to validate fold quality on surviving candidates
  • Interpreting pLDDT and pTM scores from a structure prediction

export BIOLMAI_TOKEN=your-token-here

Note: This notebook requires Boltz-2 access via the BioLM API. Confirm availability at biolm.ai/models.

Setup

import os
from biolmai.pipeline import (
    DataPipeline, DuckDBDataStore,
    ThresholdFilter, RankingFilter,
    ValidAminoAcidFilter, EmbeddingSpec,
    DiversitySamplingFilter,
)

TOKEN = os.environ.get("BIOLMAI_TOKEN", "")
if not TOKEN:
    raise EnvironmentError(
        "Set BIOLMAI_TOKEN before running.\n"
        "Get one at https://biolm.ai/ui/accounts/user-api-tokens/"
    )
import matplotlib.pyplot as plt

Designed library

A mixed library of designed sequences — some will fold well, some won't.

DESIGNED_LIBRARY = [
    # Well-folded scaffolds (expected high pLDDT)
    "MKTAYIAKQRQISFVKSHFSRQLEERVKILEQELEKAKEELKERLEELEKAKEEL",
    "GSHMDELYKAALEKAKQELKEAKQELKEAKQELKEAKQELKEAKQELKEAKQEL",
    "MHHHHHHSSGENLYFQGAEAAAKEAAAKEAAAKEAAAKEAAAKEAAAKEAAAK",
    "EVQLVESGGGLVQPGGSLRLSCAASGFNIKDTYIHWVRQAPGKGLEWVARI",
    "DIQMTQSPSSLSASVGDRVTITCRASQSISSYLNWYQQKPGKAPKLLIY",
    # Likely disordered / low confidence
    "GSGSGSGSGSGSGSGSGSGSGSGSGSGSGSGSGSGSGSGSGSGSGSGSGS",
    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
    "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG",
    "KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK",
    "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE",
    # Mixed
    "GIGKFLHSAKKFGKAFVGEIMNS",
    "KWKLFKKIPKFLHLAKKF",
    "LLGDFFRKSKEKIGKEFKRIVQRIKDFLRNLVPRTES",
]
print(f"{len(DESIGNED_LIBRARY)} sequences in designed library")
13 sequences in designed library

The pipeline

Three gates in order of increasing compute cost:

  1. Melting temperature — fast stability filter across all 13 sequences
  2. Solubility ranking — keep the top 7 most soluble survivors
  3. Boltz-2 structural validation — run no-MSA fold prediction only on sequences that passed both gates
pipeline = DataPipeline(sequences=DESIGNED_LIBRARY, verbose=True)

# Gate 1: thermal stability — cheap, runs on all sequences
pipeline.add_prediction(
    "temberture-regression", extractions="prediction",
    columns="melting_temperature", stage_name="tm",
)
pipeline.add_filter(
    ThresholdFilter("melting_temperature", min_value=50.0),
    stage_name="tm_gate",
)

# Gate 2: solubility ranking — cheap, runs on Tm survivors
pipeline.add_prediction(
    "biolmsol", extractions="solubility_score",
    columns="solubility", stage_name="sol",
    depends_on=["tm_gate"],
)
pipeline.add_filter(
    RankingFilter("solubility", n=7, ascending=False),
    stage_name="sol_gate",
)

# Gate 3: structural validation — expensive, runs only on top 7
pipeline.add_cofolding_prediction(
    "boltz2",
    params={"use_msa": False},
    extractions=["confidence.complex_plddt", "confidence.ptm"],
    columns={"confidence.complex_plddt": "plddt", "confidence.ptm": "ptm"},
    stage_name="fold_validate",
    depends_on=["sol_gate"],
)
pipeline.add_filter(
    ThresholdFilter("plddt", min_value=0.65),
    stage_name="fold_gate",
)

pipeline.run()
Added stage: PredictionStage('tm')
Added stage: FilterStage('tm_gate', depends_on=['tm'])
Added stage: PredictionStage('sol', depends_on=['tm_gate'])
Added stage: FilterStage('sol_gate', depends_on=['sol'])
Added stage: CofoldingPredictionStage('fold_validate', depends_on=['sol_gate'])
Added stage: FilterStage('fold_gate', depends_on=['fold_validate'])
############################################################
# Pipeline: DataPipeline
# Run ID: 20260617_145618_184281fa
# Initial sequences: 13
# Streaming: ENABLED
############################################################

Execution plan: 6 level(s)
  Level 1: tm
  Level 2: tm_gate
  Level 3: sol
  Level 4: sol_gate
  Level 5: fold_validate
  Level 6: fold_gate

[Stage: tm] (streaming to tm_gate)
  Cached: 0/13
  To compute: 13 (streaming)
tm: processed 13 sequences
  tm_gate: 12 passed filter (filtered 1)

============================================================
Stage: sol
Input: 12 sequences
Depends on: tm_gate
  Cached: 0/12
  To compute: 12
  Calling biolmsol.predict...
Completed: 12 sequences in 1 batches (max 5 concurrent)

StageResult(sol: in=12, out=12, cached=0, computed=12, filtered=0, time=10.7s)
============================================================

============================================================
Stage: sol_gate
Input: 12 sequences
Depends on: sol
  Applying filter: RankingFilter(column='solubility', n=7, method='top')
  Filtered out: 5/12
  Remaining: 7

StageResult(sol_gate: in=12, out=7, cached=0, computed=0, filtered=5, time=0.0s)
============================================================

============================================================
Stage: fold_validate
Input: 7 sequences
Depends on: sol_gate
StageResult(fold_validate: in=7, out=7, cached=0, computed=7, filtered=0, time=2.9s)
============================================================

============================================================
Stage: fold_gate
Input: 7 sequences
Depends on: fold_validate
  Applying filter: ThresholdFilter(column='plddt', min=0.65)
  Filtered out: 0/7
  Remaining: 7

StageResult(fold_gate: in=7, out=7, cached=0, computed=0, filtered=0, time=0.0s)
============================================================

############################################################
# Pipeline completed in 54.0s
# Final sequences: 7
############################################################
{'tm': StageResult(tm: in=13, out=13, cached=0, computed=0, filtered=0, time=0.0s),
 'tm_gate': StageResult(tm_gate: in=13, out=12, cached=0, computed=0, filtered=1, time=0.0s),
 'sol': StageResult(sol: in=12, out=12, cached=0, computed=12, filtered=0, time=10.7s),
 'sol_gate': StageResult(sol_gate: in=12, out=7, cached=0, computed=0, filtered=5, time=0.0s),
 'fold_validate': StageResult(fold_validate: in=7, out=7, cached=0, computed=7, filtered=0, time=2.9s),
 'fold_gate': StageResult(fold_gate: in=7, out=7, cached=0, computed=0, filtered=0, time=0.0s)}
pipeline.summary()
Stage Input Output Filtered Cached Computed Time (s)
0 tm 13 13 0 0 0 0.0
1 tm_gate 13 12 1 0 0 0.0
2 sol 12 12 0 0 12 10.7
3 sol_gate 12 7 5 0 0 0.0
4 fold_validate 7 7 0 0 7 2.9
5 fold_gate 7 7 0 0 0 0.0
pipeline.plot("funnel")
No description has been provided for this image

Fold quality scores on final candidates

fold_df = pipeline.query("""
    SELECT s.sequence,
           MAX(CASE WHEN p.prediction_type = 'plddt' THEN ROUND(p.value, 3) END) AS plddt,
           MAX(CASE WHEN p.prediction_type = 'ptm'   THEN ROUND(p.value, 3) END) AS ptm
    FROM sequences s
    JOIN predictions p ON s.sequence_id = p.sequence_id
    WHERE p.prediction_type IN ('plddt', 'ptm')
    GROUP BY s.sequence
    ORDER BY plddt DESC
""")
fold_df
sequence plddt ptm
0 GSHMDELYKAALEKAKQELKEAKQELKEAKQELKEAKQELKEAKQE... 0.978 0.749
1 MKTAYIAKQRQISFVKSHFSRQLEERVKILEQELEKAKEELKERLE... 0.973 0.715
2 KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK... 0.972 0.733
3 GIGKFLHSAKKFGKAFVGEIMNS 0.949 0.511
4 LLGDFFRKSKEKIGKEFKRIVQRIKDFLRNLVPRTES 0.858 0.604
5 MHHHHHHSSGENLYFQGAEAAAKEAAAKEAAAKEAAAKEAAAKEAA... 0.852 0.579
6 KWKLFKKIPKFLHLAKKF 0.840 0.135

When to include a fold validation step

Include it when:

  • The library contains de novo designed sequences where folding is not guaranteed
  • Downstream assays depend on a defined structure (enzymes, binders, scaffolds)
  • You want a confidence check before committing to wet-lab synthesis

Skip it when:

  • The sequences are natural variants of a well-characterised fold
  • The library consists of short peptides where structure predictors are unreliable
  • You are screening intrinsically disordered regions — low pLDDT is expected

Next Steps

Check out additional tutorials at jupyter.biolm.ai, or head over to our BioLM Documentation to explore additional models and functionality.

See more use-cases and APIs on your BioLM Console Catalog.


BioLM hosts deep learning models and runs inference at scale. You do the science.

Contact us to learn more.

Accelerate yourLead generation

BioLM offers tailored AI solutions to meet your experimental needs. We deliver top-tier results with our model-agnostic approach, powered by our highly scalable and real-time GPU-backed APIs and years of experience in biological data modeling, all at a competitive price.

CTA

We speak the language of bio-AI

© 2022 - 2026 BioLM. All Rights Reserved.

Filter Designs by Fold Quality Before Running Stability and Solubility Predictions | BioLM