Skip to content

Regenerate the pH 7 protonation bundles with Marvin 26.1 - #295

Open
freiburgermsu wants to merge 1 commit into
ModelSEED:devfrom
freiburgermsu:marvin-26.1-pka-regeneration
Open

freiburgermsu wants to merge 1 commit into
ModelSEED:devfrom
freiburgermsu:marvin-26.1-pka-regeneration

Conversation

@freiburgermsu

Copy link
Copy Markdown
Member

Closes the item Marvin_26.1_pKa_Run.md left under "Not done here": protonations/ still held only the 23.4 bundle. Companion to #289 / #292.

53,127 compounds, 141,715 rows — the row count 23.4 shipped, exactly, in every source. ChEBI, KEGG and Rhea cover an identical compound set. MetaCyc swaps one in each direction. Zero unparseable, zero non-standard InChI, zero InChIKeys disagreeing with the InChI beside them.

source compounds rows 23.4 rows
ChEBI 11,544 30,488 30,488
KEGG 16,275 46,911 46,911
MetaCyc 25,071 63,665 63,665
Rhea 237 651 651
total 53,127 141,715 141,715

Two things to weigh before merging

1. The tautomer step is missing

ChargeMol.java took the dominant tautomer at pH 7 before the major microspecies. That needs TautomerizationPlugin, licensed under the Isomers Plugin Group; these regenerations run on a Protonation-group licence. Verified, not assumed:

$ cxcalc "CC(=O)CC(=O)C" majortautomer -H 7
chemaxon.license.api.LicenseException: No valid license has been found.
Product name: Isomers Plugin Group

Net charge at pH 7 is unchanged for 79.7% of shared compounds and different for 20.3%, skewed toward deprotonation (11.8% one unit lower, 4.1% two or more; 3.6% one higher).

That 20.3% is an upper bound on the tautomer effect, not a measurement of it. It also contains the genuine 23.4 → 26.1 engine change, which the pKa work already showed moves site counts on roughly one shared set in seven — a pKa crossing 7 flips the protonation state on its own. The two cannot be separated without an Isomers licence, and the report does not pretend otherwise. Restoring the step is a few lines if that licence is obtained.

2. Marvin's InChI and SMILES importers lose stereochemistry

Likely the most reusable finding here, and not documented anywhere obvious. Round-tripping the source InChI with no protonation at all — import, export, compare:

import path reproduces the source InChI
MolImporter.importMol(<InChI>) 61%
MolImporter.importMol(<SMILES>) 39%
MolImporter.importMol(<RDKit molblock>) 99.6%
RDKit alone (control) 99.7%

The loss is on import, not export — what goes is the /t and /m parity layers. Every structure is therefore bridged through RDKit into a molblock before Marvin sees it, which is what ChargeMol.java was doing when it read args[0] as a mol file rather than a string.

Measured on the compounds where protonation changes nothing, so output should equal input:

source no-op compounds this run 23.4
ChEBI 7,128 99.0% 96.6%
KEGG 8,346 99.0% 97.8%
MetaCyc 13,738 98.6% 96.0%
Rhea 135 98.5% 98.5%

Unbridged this scores 55–61% — and every coverage count still looks perfect. inchi:AuxNone,SAbs on export matters just as much: without SAbs, 30.9%.

Smaller notes

  • InChIKey is derived from the InChI actually written. Marvin's inchikey export ignores SAbs and disagrees with its own inchi export — for POLYMER_10033 it emits ...-ARPYZQPTNA-N where the InChI it just wrote hashes to ...-VFUOTHLCSA-N, which is what 23.4 shipped. 0 disagreements across all 44,294 InChI rows.
  • One engine, not the CLI. Plugin and cxcalc majorms agree on 296/300 ChEBI compounds; all 4 exceptions are organometallics where cxcalc silently drops the metal fragment (C35H34MgN4O5C35H34N4O5). Same reason ChargeMol.java fragmented and re-fused.
  • Query molecules are recovered, not dropped. aromatize() on query atoms leaves bonds no SMILES writer can express, and MetaCyc spells its protein-bound cofactors with ~ any-bonds. Without handling both, 156 MetaCyc compounds would have been lost silently.
  • Charge on wildcard-adjacent atoms is inherited. 23.4 wrote *[NH2+][C@@H](... for POLYMER_12621; so does this. Correcting it is a curation decision about what * means, so it is recorded and left alone.
  • Failures, by id. Four compounds yield no row; three are H⁺ (InChI=1S/p+1, no heavy atom — 23.4 has no row either, so agreeing is correct). The one real failure is MetaCyc HypC-Dimer-Fe-CO2, an ArrayIndexOutOfBoundsException in PkaPlugin.run() — one row out of 141,715.
  • Re-running rewrites a bundle byte for byte.

Not done here

  • Compound records untouched — Update_Compound_Structures_Formulas_Charge.py is the step that rewrites them.
  • Print_Structure_Formula_Charge.py has not been re-run over these files; the formula/charge columns are Marvin's own.
  • ChEBI keeps bare ids in this bundle, matching the 23.4 protonation file (the pKa bundles use CHEBI_). The id-format migration stays separate.

Full detail in Biochemistry/Structures/_reports/Marvin_26.1_Protonation_Run.md.


Generated by Claude Code

Closes the item Marvin_26.1_pKa_Run.md left under "Not done here":
protonations/ still held only the 23.4 bundle.

53,127 compounds, 141,715 rows -- the row count 23.4 shipped, exactly, in
every source. ChEBI, KEGG and Rhea cover an identical compound set; MetaCyc
swaps one (loses HypC-Dimer-Fe-CO2 to a PkaPlugin crash, gains
A-DNA-WITH-OPPOSING-AP-SITE). Zero unparseable, zero non-standard InChI,
zero InChIKeys disagreeing with the InChI beside them.

Two things a reviewer should weigh before merging.

THE TAUTOMER STEP IS MISSING. ChargeMol.java took the dominant tautomer at
pH 7 before the major microspecies. That needs TautomerizationPlugin, which
is licensed under the Isomers Plugin Group; these regenerations run on a
Protonation-group licence, and cxcalc majortautomer returns a
LicenseException. Net charge is unchanged for 79.7% of shared compounds and
different for 20.3%, skewed toward deprotonation. That 20.3% is an upper
bound on the tautomer effect, not a measurement of it -- it also contains
the genuine 23.4 -> 26.1 engine change, which the pKa work already showed
moves site counts on one shared set in seven. The two cannot be separated
without that licence. Restoring the step is a few lines if it is obtained.

MARVIN'S InChI AND SMILES IMPORTERS LOSE STEREOCHEMISTRY. Round-tripping
the source InChI with no protonation at all reproduces it 61% of the time
through the InChI importer and 39% through SMILES, against 99.6% through an
RDKit-built molblock and 99.7% for RDKit alone. The loss is on import, not
export. Every structure is therefore bridged through RDKit into a molblock
before Marvin sees it -- which is what ChargeMol.java was doing when it read
args[0] as a mol file rather than a string. On the compounds where
protonation changes nothing, and the output should equal the input, this run
scores 98.6-99.0% against 23.4's 96.0-98.5%; unbridged it scores 55-61% and
every coverage count still looks perfect.

Also: the InChIKey is derived from the InChI actually written, because
Marvin's inchikey export ignores SAbs and disagrees with its own inchi
export. Charge on wildcard-adjacent atoms is inherited from 23.4, not
introduced, and is left alone as a curation question. Re-running rewrites a
bundle byte for byte.

Compound records are untouched; Update_Compound_Structures_Formulas_Charge.py
is the step that rewrites them, and Print_Structure_Formula_Charge.py has not
been re-run over these files.

Co-Authored-By: Claude Opus 5 (1M context) <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.

1 participant