Spaces:
Running
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
SupraBenchorg. - Keep
app.py/prompts/builder.pyessentially untouched by preserving theload_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:
inchikeyfor all four. - Storage format: one CSV per dataset (
*.csv) + a generatedREADME.mddataset card. - Fixed pool β fixed row counts.
SupraDB-GEOMandSupraDB-LigandScorecover the entire pool (Group 1 is cheap, precomputed for everything).PoseFeat/CavityScorecover 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_chargelives inLigandScore: it is computed byscore_nodockwith the cavity-dependentcharge_accessterm set to 0, so it is reproducible from SMILES for the whole pool. The pose-enhancedcharge_accessfrom the full run is reflected separately inCavityScore(S_accessibility); we do not overwrite the ligand-scoreS_chargeper-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:
- SMILES is the source of truth (from GEOM, or the seed
guests.csv). - 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. - 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. 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 likeOccupancy/S_occupancy),All 37,Physics,Chemistry,Custom(per-feature). The existing physics/chemistry/combined trajectories become presets of this same control. The selected set drivesprompts/builder.py:_feature_lines()instead of the fixedFEATURESconstant. 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); theinchikeyjoin-key note; provenance (CRC; GLIDE 2025u2 / aISS fallback; pose-collapse rule; row count); and the exactrefresh/publish.pycommand +SupraEngineeringcommit 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 β canonicalguests.csv+SupraDB-GEOMcard;--pushuploads. Seed source = the existing 63-guestSupraEngineering/data/guests.csv; pluggable for a GEOM list. - Phase 1 β CRC compute (two run dirs, because
score_nodockandcompute_all_featuresboth writefeatures/scores.pkland would clobber each other); one SGE wrapperSupraEngineering/scripts/crc_compute.sgeruns 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>thenscripts/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(moduleschrodinger/2025u2). aISS/xtb fallback on GLIDE failure β xtb is not yet on CRC (conda install -c conda-forge xtbfirst).
- whole-pool no-dock run:
- 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.csveach, 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 oninchikey, return the samerecdict. 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(fallbackcrcfe02), usertma2, password-only (no SSH keys). From a Mac session:sshpass -p "$(op read 'op://openclaw/CRC/password')" ssh crc '<cmd>'(opunlocked via Touch ID;sshpass/opvia 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'sGPMconda env);huggingface_hub+HF_TOKENon 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) |