Research prototype · Not yet benchmarked

Quantum Data
Decoder

Predicting protein stability and enzyme kinetics through the physics of molecular vibrations. A multimodal deep learning framework combining vibrational spectroscopy, graph neural networks, and protein language models.

scroll
10,100+
Lines of Python
232
Tests
3
Neural Encoders
8
Notebooks
Pending
Benchmark

Proteins are vibrating machines.
We decode their frequencies.

Traditional models treat proteins as static structures. But catalysis depends on dynamics — the collective vibrations that gate conformational changes. QDD explicitly encodes the Vibrational Density of States (VDOS) as a predictive feature — and tests whether it actually helps.

✨

Physics-Informed

Normal Mode Analysis extracts vibrational frequencies from protein structures. The hypothesis: they encode the thermodynamic landscape that governs stability and function. A controlled test has not yet supported it.

📈

Spectral Fingerprints

Each protein has a unique VDOS spectrum — a 1D signal encoding all vibrational modes. A 1D CNN encodes it as its own branch, so the model can test whether it adds signal beyond sequence.

🔄

Tri-Modal Fusion

VibroPredict fuses sequence (ProtT5), spectral (CNN on VDOS), and chemical (ChemBERTa + DRFP) encodings with learned attention gating.

Three branches. One prediction.

The VibroPredict hybrid model processes protein sequence, vibrational spectrum, and substrate chemistry in parallel, then fuses them through learned attention gates.

Sequence
ProtT5 Encoder
→ 1024-dim
Structure → NMA → VDOS
SpectralCNN
→ 128-dim
Substrate SMILES
ChemBERTa + DRFP
→ 1024-dim
➡
Attention Gating
TriModal
Fusion
→ 512-dim
➡
Prediction
log₁₀(kcat)
scalar

Explore the Vibrational Spectrum

Adjust the broadening parameter to see how Lorentzian convolution transforms discrete normal modes into a continuous Density of States. The spectrum uses the same 1000-point, 0–500 cm⁻¹ format the CNN encoder takes as input.

VDOS — 50 vibrational modes
5.0 cm¹
Peak: —
Centroid: —
Peaks detected: —

Benchmark plan

VibroPredict targets R² > 0.75 on the KinHub-27k benchmark. That target has not been measured yet: no VibroPredict R² has been produced on a public split, and the benchmark file in the repo is a dry run.

Published baselines (reported on their own datasets/splits)

ModelYearR²Features
TurNuP20220.62Seq + FP
DLKcat20210.64Seq + Graph
UniKP20230.68ProtT5 + SMILES
MPEK20230.70ESM-2 + SMILES
CatPred20250.79Seq + SMILES
VibroPredict2025target > 0.75 — not measuredSeq + VDOS + Chem

Literature values, not a head-to-head comparison: each model was evaluated on its own data and split.

Physics-signal test: negativen = 27 pairs

Does vibrational physics separate thermostable proteins? We compared 27 thermophile/mesophile enzyme homolog pairs (X-ray ≤ 2.5 Å, first chain) on each feature’s predicted direction.

Feature (hypothesis)Pairs matchingWilcoxon p
Entropy/res — thermo lower12 / 270.83
Softest mode — thermo stiffer13 / 270.47
Mean MSF — thermo more rigid14 / 270.46
Mean VDOS freq — thermo higher13 / 270.39
Contact density — thermo denser13 / 270.81

Every feature sits at chance (44–52 %); none approaches significance. An earlier n = 8 pilot was also negative. The physics branch is unproven, not validated. Read the full write-up →

Minimal code. Maximum insight.

predict_kcat.py
from vibropredict.models import VibroPredictHybrid

model = VibroPredictHybrid(fusion_dim=512)

logkcat, gates = model(
    sequences=["MKTIIALSYIF..."],
    vdos=vdos_tensor,        # (1, 1, 1000)
    substrate_smiles=["CC(=O)O"],
)

print(f"k_cat = {10**logkcat.item():.1f} s⁻¹")
print(f"Attention: seq={gates[0,0]:.2f} "
      f"spec={gates[0,1]:.2f} "
      f"chem={gates[0,2]:.2f}")
train.py
from vibropredict.training import (
    TrainerWithMMDrop,
    MutantRankingLoss,
)

trainer = TrainerWithMMDrop(
    model=model,
    optimizer=optimizer,
    device="cuda",
)

# MM-Drop: randomly drops spectral
# branch 25% of the time for robustness
best_loss = trainer.fit(
    train_loader, val_loader,
    loss_fn=MutantRankingLoss(lambda_rank=0.1),
    epochs=50, p_drop=0.25,
)

End-to-end walkthroughs