SupraDashboard / docs /COMPUTE_INTEGRATION.md
Tianyi-Billy-Ma
Deploy: simplify codebase (dead-code removal, behavior-preserving)
1727091
|
Raw
History Blame Contribute Delete
11 kB

Compute Integration β€” live CRC features β†’ 4 HF datasets β†’ dashboard

This document is the contract for replacing the dashboard's single frozen feature table (SupraBench/physics_feature/test_features_table.csv) with features that we compute ourselves from the SupraEngineering pipeline on CRC, served through four Hugging Face datasets.

It is the spec implementation works against. Code is written by Codex; this doc is owned by the planning side and kept in sync as decisions change.


1. Goal

  • Stop reading a hand-authored, third-party feature table.
  • Compute every feature ourselves (SupraEngineering, GLIDE docking on CRC).
  • Serve features to the dashboard via four private datasets under the SupraBench org.
  • Keep app.py / prompts/builder.py essentially untouched by preserving the load_features() / guest_choices() / get_record() API.

A convenient invariant: the dashboard's feature column names already equal the pipeline's constants.POSE_FEATURES and constants.SCORE_NAMES. So as long as the datasets use those exact names, only the loader underneath the app changes.


2. The four datasets (private, SupraBench org)

Dataset Holds Rows Needs docking? Producer
SupraBench/SupraDB-GEOM guest pool: inchikey, name, smiles[, logka] whole pool no Phase 0 pool builder
SupraBench/SupraDB-LigandScore 9 ligand-only mechanism scores whole pool no (rdkit) score_nodock
SupraBench/SupraDB-PoseFeat 24 pose features docked subset yes (GLIDE) compute_all_features
SupraBench/SupraDB-CavityScore 4 cavity scores docked subset yes (GLIDE) compute_all_features
  • Primary / join key: inchikey for all four.
  • Storage format: one CSV per dataset (*.csv) + a generated README.md dataset card.
  • Fixed pool β‡’ fixed row counts. SupraDB-GEOM and SupraDB-LigandScore cover the entire pool (Group 1 is cheap, precomputed for everything). PoseFeat / CavityScore cover only the docked subset (default: the 63 labeled guests).

2.1 Column contracts

SupraDB-GEOM:

inchikey, name, smiles, logka   # logka may be empty for unlabeled (GEOM-only) guests

SupraDB-LigandScore (9 β€” produced by score_nodock, ligand-intrinsic, charge_access=0):

inchikey,
S_charge, S_hydrophobic, S_rigidity, S_desolvation, S_packing,
S_shape, S_conformer_diversity, S_boltzmann_concentration, S_bad

SupraDB-CavityScore (4 β€” cavity terms from the best docked pose):

inchikey, S_occupancy, S_portal, S_accessibility, S_orientation

SupraDB-PoseFeat (24 pose features, constants.POSE_FEATURES order, + provenance):

inchikey,
DockingScore, Pose_Energy, Distance_to_Cavity_Center, Distance_to_Portal,
Insertion_Depth, Packing_Coefficient, Occupancy, Hydrophobic_Occupancy,
Shape_Complementarity, Steric_Clash, Guest_CB7_Min_Distance, Pose_RMSD_to_Template,
Portal_Compatibility, Positive_Center_to_Portal_Distance, Positive_Center_Orientation,
Charge_Accessibility, Portal_Facing_Accessibility, HBond_Count, HBond_Geometry,
Carbonyl_Oxygen_Contact_Count, Hydrophobic_Contact, Polar_Contact_Penalty,
Bad_Group_Portal_Exposure, Desolvation_Penalty,
boltzmann_weight, delta_e          # provenance of the kept (collapsed) pose

Why S_charge lives in LigandScore: it is computed by score_nodock with the cavity-dependent charge_access term set to 0, so it is reproducible from SMILES for the whole pool. The pose-enhanced charge_access from the full run is reflected separately in CavityScore (S_accessibility); we do not overwrite the ligand-score S_charge per-pose. This keeps each dataset's provenance clean.

2.2 Pose collapse

pose_feats.pkl stores up to P poses/guest as float32[P, 24] with per-pose delta_e and boltz. The dashboard shows one row/guest, so publish.py collapses to the single pose with the highest boltzmann_weight (the dominant, lowest-energy geometry β€” a real pose, not an average). boltzmann_weight + delta_e of that pose are carried into the CSV for transparency. (Alternative rules β€” weighted average, lowest GlideScore β€” are documented but not the default.)


3. Identifiers β€” SMILES & InChIKey

The pipeline and dashboard both assume inchikey/smiles are given; neither derives them. We make that explicit in Phase 0:

  1. SMILES is the source of truth (from GEOM, or the seed guests.csv).
  2. Canonicalize + desalt once (RDKit, largest fragment) β€” matches what the pipeline does internally (ligand_descriptors, smiles_to_xyz), so the stored InChIKey is the same key the pipeline computes under.
  3. InChIKey = Chem.MolToInchiKey(Chem.MolFromSmiles(canonical_smiles)) β€” a canonical hash; identical molecules β†’ identical key. This is the join key across all four datasets, the SQLite cache, and the 2D/3D structure fetch.
  4. name: keep any name GEOM/seed provides; else fall back to a short InChIKey label.

Generated in exactly one place (the pool builder) so every downstream piece keys off the same value.


4. Feature selection (compute + inference)

All 37 features are stored. Selection is a choice, defaulting to a recommendation.

  • At inference (drives the LLM prompt): a UI selector with presets β€” Recommended (default, the curated ~22: strongest pose features + meaningful scores, dropping redundant pairs like Occupancy/S_occupancy), All 37, Physics, Chemistry, Custom (per-feature). The existing physics/chemistry/combined trajectories become presets of this same control. The selected set drives prompts/builder.py:_feature_lines() instead of the fixed FEATURES constant. The choice is recorded with each sample and folded into the cache key so different feature sets don't collide.
  • At compute: the meaningful choice is which of the three groups to (re)compute (docking is the expensive step; once docked, all pose features are free). Default: all.

The Recommended preset = the current 22-feature FEATURES list in data/loader.py.


5. Dataset cards (README.md per dataset)

Every SupraDB-* dataset ships a generated HF dataset card:

  • YAML frontmatter: license, pretty_name, tags, configs (point at the CSV).
  • Body: what it is + pipeline position; full schema (column, dtype, units, meaning from DEFINITIONS.md / features_lib); the inchikey join-key note; provenance (CRC; GLIDE 2025u2 / aISS fallback; pose-collapse rule; row count); and the exact refresh/publish.py command + SupraEngineering commit that produced it.

Cards are generated by the scripts (Phase 0 writes the GEOM card; publish.py writes the three feature cards) so they never drift from the data.


6. Pipeline (Phases)

GEOM SMILES (or seed guests.csv)
   β”‚  Phase 0: pool_builder.py  (RDKit canonicalize+desalt β†’ InChIKey)
   β–Ό
SupraDB-GEOM  ◄── source of truth (guest list, names, SMILES, logka)
   β”‚
   β”œβ”€ Group 1: score_nodock (rdkit, whole pool) ─────► SupraDB-LigandScore
   └─ Groups 2+3: dock_glide β†’ compute_all_features ─► SupraDB-PoseFeat + SupraDB-CavityScore
      (CRC, GLIDE 2025u2; docked subset)                       β”‚
                                       all four joined on inchikey
                                                               β–Ό
                                            data/loader.py β†’ app.py (unchanged)
  • Phase 0 β€” Pool builder (SupraEngineering/src/pool_builder.py): SMILES source β†’ canonical guests.csv + SupraDB-GEOM card; --push uploads. Seed source = the existing 63-guest SupraEngineering/data/guests.csv; pluggable for a GEOM list.
  • Phase 1 β€” CRC compute (two run dirs, because score_nodock and compute_all_features both write features/scores.pkl and would clobber each other); one SGE wrapper SupraEngineering/scripts/crc_compute.sge runs both:
    • whole-pool no-dock run: scripts/score_nodock.sh <pool_dir> β†’ <pool_dir>/features/scores.pkl (13-d, cavity terms = 0). Source of LigandScore (the 9 ligand cols).
    • docked-subset run: scripts/dock_glide.sh <dock_dir> then scripts/compute_all_features.sh <dock_dir> β†’ <dock_dir>/features/scores.pkl (full 13-d) + pose_feats.pkl. Source of CavityScore (the 4 cavity cols) and PoseFeat (24-d).
    • GLIDE confirmed at /opt/crc/s/schrodinger/2025u2 (module schrodinger/2025u2). aISS/xtb fallback on GLIDE failure β€” xtb is not yet on CRC (conda install -c conda-forge xtb first).
  • Phase 2 β€” Publish (SupraEngineering/src/publish.py, runs on CRC, HF_TOKEN present): inputs --pool-scores <pool_dir>/features/scores.pkl, --dock-scores <dock_dir>/features/scores.pkl, --pose-feats <dock_dir>/features/pose_feats.pkl. Splits into 3 feature CSVs (features.csv each, full named columns) + cards, collapses poses by Boltzmann weight, uploads to the three feature repos.
  • Phase 3 β€” Loader (src/data/loader.py): read the 4 datasets, LEFT-join on inchikey, return the same rec dict. Env: 4 repo ids + HF_TOKEN; LOCAL_* CSV fallbacks for offline dev; lru_cache. Report which datasets loaded (health strip).
  • Phase 4 β€” UI + automation: feature-selection control; one-command refresh (ssh CRC β†’ qsub β†’ wait β†’ publish); finalize this runbook.

7. CRC connection (runbook)

  • Host crc β†’ crcfe01.crc.nd.edu (fallback crcfe02), user tma2, password-only (no SSH keys). From a Mac session: sshpass -p "$(op read 'op://openclaw/CRC/password')" ssh crc '<cmd>' (op unlocked via Touch ID; sshpass/op via Homebrew).
  • Scheduler: SGE (qsub/qstat/qdel); never run docking interactively on a login node for the full pool.
  • GLIDE: module load schrodinger/2025u2; $SCHRODINGER=/opt/crc/s/schrodinger/2025u2.
  • Env: a Python env with rdkit, numpy, pandas, scipy (the project's GPM conda env); huggingface_hub + HF_TOKEN on CRC for the publish step.

8. Decision ledger

Decision Status
4 datasets SupraDB-GEOM/-LigandScore/-PoseFeat/-CavityScore locked
inchikey = sole join key, derived once in Phase 0 from SMILES locked
Store all 37 features; inference set selectable; Recommended default locked
Each dataset ships a generated README.md card locked
publish.py runs on CRC (HF_TOKEN already there) locked
GLIDE 2025u2 default (confirmed on CRC); aISS/xtb fallback (xtb needs install) locked
Pose collapse = highest Boltzmann weight default (flag to change)
GEOM Group-1 scope = CB[7]-plausible subset (not all ~430k) default (flag to change)
Docking subset = 63 labeled guests; GEOM-only guests prediction-only default (flag to change)