moleculekit.tools.residue_titration module#
Prepare non-standard residues for pKa titration and fold the result back into per-residue build templates.
The public entry points are capNonstandardResiduesForTitration() and
templatesFromTitration(), both dict-in / dict-out ({key: smiles}),
with optional file endpoints for tools that communicate over files:
capNonstandardResiduesForTitration(outfile=...) writes the titration input
as a key,SMILES,base CSV, and templatesFromTitration accepts the pKa
tool’s output CSV path in place of the dict. The only assumption made about
the tool (e.g. AcePka) is that it rewrites the SMILES column and echoes
every other column through, which makes the round-trip self-contained: the
echoed base column guarantees cap-stripping re-derives each anchor from
exactly the base SMILES that was titrated, with no RCSB re-fetch in between.
Each residue is built from its full base SMILES (an RCSB ligand descriptor or a caller override), so it carries the complete chemistry even when the deposited structure has a trimmed sidechain. Every outgoing inter-residue bond is then capped with an inert stand-in for its real partner, so the pKa tool sees a chemically sane molecule that titrates the residue’s own groups in a faithful environment. Most caps are neutral (an amide, a methyl); a phosphodiester partner is kept as a phosphate, so an internal nucleotide carries the real, charged backbone environment a terminal one would not:
a backbone peptide bond gets an amide cap - acetyl on the
Nside, N-methyl on the carbonylCside (the ACE / NME that keep a mid-chain backbone neutral);a sidechain / scaffold crosslink gets an inert cap chosen to keep the junction atom non-titratable: acetyl on a severed nitrogen, N-methyl on an amide carbonyl carbon, and for any other junction a cap reflecting the real partner element (a nitrogen partner gives an amide, an oxygen partner a hydroxyl, a phosphorus partner a phosphate, everything else a methyl). When a condensation crosslink (glycosidic, phosphoester, …) left the junction atom fully valent in the free-form SMILES, the displaced leaving group (the base-SMILES atom absent from the deposited residue) is stripped first;
a genuine free terminus or free-ligand end is left uncapped, so the pKa tool assigns its charge (a real C-terminus deprotonates, an N-terminus protonates).
The backbone atoms are located by their structure names (N / C) mapped
onto the SMILES; crosslink atoms are found by walking mol.bonds and mapped
the same way. Coordinates never affect the returned SMILES - only connectivity
does. After titration, templatesFromTitration() strips the caps back off
(the residue is a subgraph of its capped molecule) to yield one template SMILES
per residue for the builder.
- moleculekit.tools.residue_titration.capNonstandardResiduesForTitration(mol, specs, smiles=None, outfile=None, _logger=True)#
Build per-context pKa-titration input SMILES for the non-standard residues, keyed by
new_resname or resname.Each chain-resident NCAA is capped for its chain context, and every scaffold / covalent-ligand residue has its non-peptide crosslink(s) inert- capped the same way (see
_cap_residue_smiles()); a genuinely free ligand is passed through uncapped, as is any residue whose backbone or crosslink cannot be capped (a warning is logged and it is titrated whole). Entries are deduplicated by key so an NCAA appearing in several places is titrated once per unique (chemistry, context).The result is a plain
{key: smiles}dict. The caller runs its own pKa tool over the values (e.g. AcePka) and passes the protonated result back totemplatesFromTitration()- as a dict of the same keys, or, for a file-based tool, as the path to its output CSV (seeoutfile).- Parameters:
mol (
Molecule) – The molecule the specs were detected in.specs (
list) – The specs returned bymoleculekit.tools.nonstandard_residues.detectNonStandardResidues().smiles (
dict|None) – Optional{resname: smiles}overrides; resnames absent here are fetched from RCSB by their CCD code.outfile (
str|None) – When given, also write the result as a CSV with akey,SMILESandbasecolumn per entry - the input for a file-based pKa tool that rewritesSMILESand echoes the other columns through (e.g. AcePka). The echoedbasecolumn is what letstemplatesFromTitration()re-derive each anchor from exactly the base SMILES that was titrated, with no state carried in between.
- Returns:
titration –
{key: smiles}to titrate, one entry per unique template-requiring residue.- Return type:
- Raises:
RuntimeError – If a residue needing a template has neither an override in
smilesnor a fetchable RCSB SMILES.
- moleculekit.tools.residue_titration.templatesFromTitration(mol, specs, protonated, smiles=None, outfile=None)#
Strip the caps off pKa-titrated SMILES back into per-residue templates.
Inverse of
capNonstandardResiduesForTitration(), driven by the samemolandspecsso no intermediate state has to be carried between the two calls. For each template-requiring chain, scaffold, or covalent- ligand residue, its uncapped anchor is re-derived (_uncapped_residue_smiles()) and used as a relaxed substructure query (_relaxed_query()) to locate that residue’s own atoms inside its protonated, capped SMILES; the matched atoms are extracted (_submol_from_atoms()), dropping the ACE / NME / crosslink caps that fall outside the match. A pKa tool only ever changes protonation state, never the heavy-atom skeleton, so the anchor is guaranteed to be a subgraph of the protonated molecule. Residues titrated whole (genuinely free ligands, or residues whose backbone or crosslink could not be capped) are returned unchanged.- Parameters:
mol (
Molecule) – The molecule the specs were detected in (the same one passed tocapNonstandardResiduesForTitration()).specs (
list) – The specs frommoleculekit.tools.nonstandard_residues.detectNonStandardResidues().protonated (
dict|str|PathLike) –{key: smiles}of the pKa-tool-protonated titration output, keyed exactly ascapNonstandardResiduesForTitration()returned - or the path to the tool’s output CSV (e.g. AcePka’sprotonated.csv). The CSV must carrykeyandSMILEScolumns; when thebasecolumn written bycapNonstandardResiduesForTitration(outfile=...)was echoed through by the tool, each anchor is re-derived from that echoed base - provably the same SMILES that was titrated, with no RCSB re-fetch and nosmiles=overrides to carry between sessions.smiles (
dict|None) – The same{resname: smiles}overrides passed tocapNonstandardResiduesForTitration(), so anchors are re-derived from identical base SMILES. Not needed whenprotonatedis a CSV path with abasecolumn.outfile (
str|None) – When given, also write the templates as JSON mapping each key to{"smiles": template}- the shape residue-template consumers take.
- Returns:
templates –
{key: smiles}, one entry per key, with caps removed and the pKa tool’s protonation applied.- Return type:
- Raises:
RuntimeError – If
protonatedis missing a key, a protonated SMILES cannot be parsed, or a residue’s anchor cannot be located inside its protonated SMILES.