Skip to content

Promote per-source thermodynamics to canonical deltag (+ retrained dGPredictor-ModelSEED source) - #265

Merged
samseaver merged 2 commits into
ModelSEED:devfrom
freiburgermsu:promote-thermodynamics-to-canonical-deltag
Aug 4, 2026
Merged

Promote per-source thermodynamics to canonical deltag (+ retrained dGPredictor-ModelSEED source)#265
samseaver merged 2 commits into
ModelSEED:devfrom
freiburgermsu:promote-thermodynamics-to-canonical-deltag

Conversation

@freiburgermsu

Copy link
Copy Markdown
Member

Summary

Gives 14,141 reactions a canonical free-energy value (deltag/deltagerr/reversibility) that they were missing — purely by re-aggregating estimates that already exist in the additive thermodynamics dict, plus the retrained dGPredictor source that supplies some of them.

Background: the promotion gap

After the additive-thermodynamics refactor, the Update_Reaction_*_Energies.py scripts write only into each reaction's additive thermodynamics dict and no longer populate the canonical top-level deltag/deltagerr. As a result thousands of reactions carried a perfectly good computed energy in thermodynamics while their canonical deltag stayed the 10000000 sentinel (and reversibility "?"), so they read as thermodynamically undefined despite the value already existing.

What this PR does

Two commits:

  1. dGPredictor-ModelSEED source (existing additive work) — the dGPredictor group-contribution model retrained on ModelSEED structures, recorded as its own per-method entry in thermodynamics. Additive; supplies energies for reactions the other sources miss.

  2. Promotion — new Scripts/Thermodynamics/Promote_Reaction_Thermodynamics_to_Canonical.py re-aggregates the stored per-source estimates into the canonical fields. Pure re-aggregation: no new estimation, no external dependencies.

    • Only reactions with a missing canonical deltag are touched; existing canonical values are never overwritten.
    • Selection: prefer the mechanistic/measurement-anchored tier (eQuilibratorGroup contribution) over the ML tier (dGPredictor-ModelSEED, dGPredictor); within the chosen tier take the lowest-uncertainty estimate. The within-tier lowest-error rule stops a wildly-uncertain ML outlier (e.g. -100 ± 71 kcal/mol) being promoted over a tight estimate (-8.6 ± 0.04).
    • Guards reject implausible magnitudes (|dG| > 1000) and useless uncertainties (> 100 kcal/mol), leaving those undefined rather than promoting garbage.
    • reversibility is set to the chosen estimate's own direction operator (same heuristic as Estimate_Reaction_Reversibility.py, already stored with each per-source energy).

Result

14,141 reactions promoted: Group contribution 1,474 · dGPredictor 8,635 · dGPredictor-ModelSEED 4,032.

Verified: every promoted deltag equals one of that reaction's stored per-source energies; zero pre-existing canonical values, thermodynamics dicts, or other fields changed. (.tsv files update because deltag/deltagerr/reversibility are TSV columns.)

The source-precedence policy is a single editable TIERS constant; ~732 reactions have >50 kcal/mol cross-source disagreement and are worth a curator spot-check (the policy resolves them by tier + lowest error, not averaging).

🤖 Generated with Claude Code

freiburgermsu and others added 2 commits June 10, 2026 16:25
…urce

Records the dGPredictor group-contribution model retrained on the ModelSEED
compound structures as its own per-method entry, "dGPredictor-ModelSEED", in
each reaction's `thermodynamics` dict. Purely additive: it sits next to the
Group contribution / eQuilibrator / (original KEGG-based) dGPredictor records,
and the original "dGPredictor" entry is left untouched. The canonical
deltag / deltagerr / reversibility are not changed, and no .tsv or compound
files change.

- New staged predictions: Biochemistry/Thermodynamics/dGPredictor/
  modelseed_retrained_dG.json (31,924 reactions, kJ/mol).
- New writer: Scripts/Thermodynamics/Update_Reaction_dGPredictor_ModelSEED_
  Energies.py (kJ->kcal /4.184; operator via reversibility_from_energy).
- 31,924 reactions gain a dGPredictor-ModelSEED record (incl. ~11,400 the
  original KEGG-based dGPredictor could not reach); 24,088 reactions unchanged.
- Verified: every modified reaction differs from dev ONLY by the added
  dGPredictor-ModelSEED key; added values equal dG_mean/4.184; the writer is
  idempotent.
- Docs: sources.yaml, Scripts/Thermodynamics/README.md, Rerun_Thermodynamics.sh.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…141 reactions)

After the additive-thermodynamics refactor, the Update_Reaction_*_Energies.py
scripts write only into each reaction's additive `thermodynamics` dict and no
longer populate the canonical top-level deltag/deltagerr. As a result 14,141
non-EMPTY reactions carried a perfectly good computed energy in `thermodynamics`
while their canonical deltag stayed the 10000000 sentinel (reversibility "?"),
so they read as thermodynamically undefined despite the value already existing.

New Scripts/Thermodynamics/Promote_Reaction_Thermodynamics_to_Canonical.py
re-aggregates those existing per-source estimates into the canonical fields. It
is pure re-aggregation -- no new estimation, no external dependencies:
- Only reactions whose canonical deltag is missing are touched; existing
  canonical values are never overwritten.
- Selection: prefer the mechanistic/measurement-anchored tier (eQuilibrator,
  then Group contribution) over the ML tier (dGPredictor-ModelSEED, dGPredictor);
  WITHIN the chosen tier take the lowest-uncertainty estimate. The within-tier
  lowest-error rule prevents a wildly-uncertain ML outlier (e.g. -100 +/- 71
  kcal/mol) from being promoted over a tight estimate (-8.6 +/- 0.04).
- Guards reject implausible magnitudes (|dG| > 1000 kcal/mol) and useless
  uncertainties (> 100 kcal/mol), leaving those reactions undefined rather than
  promoting garbage.
- deltagerr is set from the chosen source and reversibility is set to that
  estimate's own direction operator (same heuristic as Estimate_Reaction_
  Reversibility, already stored alongside each per-source energy).

Promoted 14,141 reactions: Group contribution 1,474; dGPredictor 8,635;
dGPredictor-ModelSEED 4,032. Verified: every promoted deltag equals one of the
reaction's stored per-source energies; zero pre-existing canonical values,
thermodynamics dicts, or other fields changed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
samseaver pushed a commit that referenced this pull request Aug 4, 2026
Re-ran Scripts/Biochemistry/Reprint_Biochemistry.py to bring the
equation and definition strings in sync with the newly-promoted
reversibility values from PR #265. Freiburgermsu's promotion
populated the reversibility field for 14,141 reactions but did not
re-render the equation and definition strings, which encode the
same reversibility operator in human-readable form. This commit
does that re-rendering.

Zero data changes beyond the string re-rendering (deltag, deltagerr,
compound_ids, stoichiometry, and all other fields unchanged).

Also resolves the 34 reaction .tsv conflicts that arose during the
PR #265 merge (both dev and freiburgermsu's branch had independently
regenerated TSVs from their respective JSONs; regeneration from the
merged JSONs is the correct post-merge state).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@samseaver
samseaver merged commit da59b2e into ModelSEED:dev Aug 4, 2026
samseaver pushed a commit that referenced this pull request Aug 4, 2026
Fixes eQuilibrator retrieval scripts for equilibrator_api 0.6.x
(API drift; module-level ccache singleton removed, ComponentContribution
no longer takes reaction conditions as constructor kwargs).

Re-runs the pipeline against updated ModelSEED structures. Coverage
expansion in the pre-computed source tables:

- MetaNetX_Compound_Energies.tbl: 20,828 -> 31,219 rows
  (+10,391 compounds)
- MetaNetX_Reaction_Energies.tbl:  22,441 -> 27,022 rows
  (+4,581 reactions)
- 16,412 reactions re-tagged EQP -> EQC / EQC -> EQP in notes to
  reflect the new per-reagent coverage.

Andrew's commit explicitly notes: only the eQuilibrator energy
tables and reaction notes change here; canonical
deltag/deltagerr/reversibility and the additive thermodynamics
dicts are untouched. Propagation into served compound_*.json and
reaction_*.json records is a separate step, run in follow-up
commits.

Directly fills the compound-level coverage gap identified during
audit of the post-#264/#265 dev state (30,479 non-R structured
compounds, only 22,616 with any deltag before this branch).

Conflict resolution: 61 reaction .tsv files conflicted between
dev's TSVs and freiburgermsu's TSVs. Resolved by taking dev's side
then regenerating all TSVs from the merged JSONs via
Reprint_Biochemistry.py in the next commit.

Co-Authored-By: Andrew Freiburger <freiburgermsu@aol.com>

# Conflicts:
#	Biochemistry/reaction_00.tsv
#	Biochemistry/reaction_01.tsv
#	Biochemistry/reaction_02.tsv
#	Biochemistry/reaction_03.tsv
#	Biochemistry/reaction_04.tsv
#	Biochemistry/reaction_05.tsv
#	Biochemistry/reaction_06.tsv
#	Biochemistry/reaction_07.tsv
#	Biochemistry/reaction_08.tsv
#	Biochemistry/reaction_09.tsv
#	Biochemistry/reaction_10.tsv
#	Biochemistry/reaction_11.tsv
#	Biochemistry/reaction_12.tsv
#	Biochemistry/reaction_13.tsv
#	Biochemistry/reaction_14.tsv
#	Biochemistry/reaction_15.tsv
#	Biochemistry/reaction_16.tsv
#	Biochemistry/reaction_17.tsv
#	Biochemistry/reaction_18.tsv
#	Biochemistry/reaction_19.tsv
#	Biochemistry/reaction_20.tsv
#	Biochemistry/reaction_21.tsv
#	Biochemistry/reaction_22.tsv
#	Biochemistry/reaction_23.tsv
#	Biochemistry/reaction_24.tsv
#	Biochemistry/reaction_25.tsv
#	Biochemistry/reaction_26.tsv
#	Biochemistry/reaction_27.tsv
#	Biochemistry/reaction_28.tsv
#	Biochemistry/reaction_29.tsv
#	Biochemistry/reaction_30.tsv
#	Biochemistry/reaction_31.tsv
#	Biochemistry/reaction_32.tsv
#	Biochemistry/reaction_33.tsv
#	Biochemistry/reaction_34.tsv
#	Biochemistry/reaction_35.tsv
#	Biochemistry/reaction_36.tsv
#	Biochemistry/reaction_37.tsv
#	Biochemistry/reaction_38.tsv
#	Biochemistry/reaction_39.tsv
#	Biochemistry/reaction_40.tsv
#	Biochemistry/reaction_41.tsv
#	Biochemistry/reaction_42.tsv
#	Biochemistry/reaction_43.tsv
#	Biochemistry/reaction_44.tsv
#	Biochemistry/reaction_45.tsv
#	Biochemistry/reaction_46.tsv
#	Biochemistry/reaction_47.tsv
#	Biochemistry/reaction_48.tsv
#	Biochemistry/reaction_49.tsv
#	Biochemistry/reaction_50.tsv
#	Biochemistry/reaction_51.tsv
#	Biochemistry/reaction_52.tsv
#	Biochemistry/reaction_53.tsv
#	Biochemistry/reaction_54.tsv
#	Biochemistry/reaction_55.tsv
#	Biochemistry/reaction_56.tsv
#	Biochemistry/reaction_57.tsv
#	Biochemistry/reaction_58.tsv
#	Biochemistry/reaction_59.tsv
#	Biochemistry/reaction_60.tsv
samseaver pushed a commit that referenced this pull request Aug 4, 2026
Two sub-steps run in sequence:

1. Update_Reaction_eQuilibrator_Energies.py
   Folds the freshly-computed eQuilibrator reaction values (from
   the +4,581-reaction rerun in Andrew's branch, merged at c1149b7)
   into each reaction's additive 'thermodynamics' dict as an
   'eQuilibrator' entry.

2. Promote_Reaction_Thermodynamics_to_Canonical.py
   Re-runs the promotion policy from PR #265 against the now-updated
   thermodynamics dicts. Promotes an additional 150 reactions to
   canonical deltag (all from eQuilibrator; the previous run had
   already caught the promotable candidates from GC + dGPredictor).

Coverage state after this commit:
  Total reactions:                          56,012
  Per-source entries:
    eQuilibrator (post-rerun):              25,028
    Group contribution:                     55,999
    dGPredictor (KEGG-trained):             27,715
    dGPredictor-ModelSEED (retrained):      31,924
  Canonical deltag:              39,051 -> 39,201 (+150)
  Unpromotable:                             16,801
    (no source estimate, or all fail the >100 kcal/mol
    uncertainty guard)

Reaction JSONs+TSVs regenerated via Reprint_Biochemistry.py for
consistency (equation/definition strings reflect any updated
reversibility operators).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants