Typifier¶
Graph typification and force-field parameter assignment.
The contract¶
A typifier is Atomistic -> Atomistic: it takes a molecular graph and returns a
typed copy whose atoms and links carry force-field types and parameters. Every
typifier runs the same flow — copy, match, write the annotations back and define
the types — so typify() is written once, on the base class, and match() is
the single step a typifier implements.
class Typifier:
def typify(self, mol) -> Atomistic # final: copy, match, write back
def match(self, graph) -> Match # the only thing that differs
def library(self) -> ForceField # optional: what the output declares
def forcefield(self) -> ForceField # the union of every type typify assigned
typify is final — a subclass that defines it raises TypeError at class
creation — and it is the only writer of forcefield().
Typifiers are named after the force field or the tool that decides the types.
Quick reference¶
| Symbol | Summary | Preferred for |
|---|---|---|
Typifier |
The contract: implement match (and optionally library) |
Writing your own |
Match |
What match returns: node and link annotations, styles, pair rows |
Writing your own |
OPLSAATypifier |
Full OPLS-AA typing pipeline (native) | OPLS-AA all-atom force fields |
MMFF94Typifier / MMFF94STypifier |
Full MMFF94 / MMFF94s typing pipeline (native) | MMFF all-atom force fields |
ElementTypifier |
type labels from element symbols; defines no force field |
Writers that need labels on an untyped molecule |
AtdTypifier |
AtdTypifier(parameter_set="gaff2"): antechamber's atom-type tables (gaff, gaff2, amber, bcc, …) evaluated natively — atom types only, no charges or parameters |
GAFF / GAFF2 or BCC atom types without running antechamber |
AntechamberTypifier |
antechamber → parmchk2 → tleap for one complete molecule | GAFF / GAFF2 small molecules and monomers |
TLeapTypifier |
tleap alone over a finished graph that already carries AMBER types and charges (a graph with ports is refused) | Re-parameterising a typed molecule |
The native typifiers are identity re-exports of molrs.ff.typifier. The
AmberTools typifiers shell out through molpy.wrapper; see
Optional external tools.
A GAFF polymer is not typed by joining typed monomers (each join folds the
leaving group's charge onto its anchor): build it with
mp.builder.polymer.AmberPolymerBuilder, which cuts one antechamber-typed
oligomer with prepgen and joins the residues with tleap — see
Builder and the
AmberTools guide.
UFF typing exists in the native core (Rust) but has no Python binding yet; MolPy re-exports it once one is published.
Canonical example¶
import molpy as mp
from molpy.typifier import OPLSAATypifier
mol, _ = mp.Conformer(add_hydrogens=True, seed=42).generate(
mp.io.read_smiles("CCO")
)
typifier = OPLSAATypifier(strict=True)
typed_mol = typifier.typify(mol) # returns a new Atomistic
ff = typifier.forcefield() # the parameters of the types just assigned
frame = typed_mol.to_frame()
Key behavior¶
typify()returns a new graph — the original is not modifiedforcefield()is the union of what everytypifycall assigned, as an independent copy; a definition that contradicts one already held raises- A term the force field does not parameterise is left undecided, never
stamped with
None - SMARTS matching is native; MolPy carries no matcher of its own
Writing a typifier¶
Implement match and stop. It returns a Match: one annotation mapping per
node, positional against graph.atoms, and per link class one mapping per row,
positional against graph.links.exact_bucket(cls). A type annotation is
(style, name, endpoints, params): it stamps name and every param, and
defines the type name on endpoints (atom-type names, empty for an atom
type). The name is never parsed — the endpoints are required. styles declares
each style used; pairs adds (style, name, endpoints, params) pair rows.
class TIP3PTypifier(mp.typifier.Typifier):
"""TIP3P water: OW / HW atoms and one OW-HW bond type."""
SITES = {"O": ("OW", 15.999, -0.834), "H": ("HW", 1.008, 0.417)}
def library(self):
return mp.ForceField("tip3p", units="real") # the output declares real units
def match(self, graph):
nodes = []
for atom in graph.atoms:
name, mass, charge = self.SITES[atom["element"]]
nodes.append({"type": ("full", name, (), {"mass": mass}), "charge": charge})
bonds = [
{"type": ("harmonic", "OW-HW", ["OW", "HW"], {"k": 450.0, "r0": 0.9572})}
for _ in graph.links.exact_bucket(mp.Bond)
]
return mp.typifier.Match(
nodes,
{mp.Bond: bonds},
styles=[("atom", "full", {}), ("bond", "harmonic", {}), ("pair", "lj/cut", {})],
pairs=[
("lj/cut", "OW", ["OW"], {"epsilon": 0.1521, "sigma": 3.1507}),
("lj/cut", "HW", ["HW"], {"epsilon": 0.0, "sigma": 0.0}),
],
)
tip3p = TIP3PTypifier()
water = tip3p.typify(mp.io.read_smiles("[H]O[H]"))
assert [bond["type"] for bond in water.bonds] == ["OW-HW", "OW-HW"]
assert tip3p.forcefield().get_style("bond", "harmonic").get_type_by_name("OW-HW")["k"] == 450.0
Related¶
- Guide: Force Field Typification
- Guide: AmberTools Integration
- Concepts: Force Field
- Extending Typifiers
Full API¶
Typifiers¶
typifier ¶
Force-field typification.
The native typifiers are identity re-exports of :mod:molrs.ff.typifier
(mp.typifier.OPLSAATypifier is molrs.ff.typifier.OPLSAATypifier), listed one
by one. Typifier is the base every typifier extends: a subclass implements
match and the base owns typify and the accumulated forcefield().
:class:AntechamberTypifier and :class:TLeapTypifier type through the
AmberTools executables (:mod:molpy.wrapper).
AntechamberTypifier ¶
AntechamberTypifier(
*,
atom_type="gaff2",
charge_method="bcc",
work_dir="amber_work",
env=None,
env_manager=None,
)
Bases: _AmberLibrary
GAFF / GAFF2 atom types, charges and parameters for a complete molecule.
match runs antechamber (-at atom_type -c charge_method, net charge
from the atoms' formal charges), parmchk2 and tleap in a per-molecule
directory under work_dir, and assigns the prmtop's types, charges and
bonded terms. Ports are allowed; their leaving groups are real atoms.
A polymer chain is not typed here: joining typed monomers folds each
leaving group's charge onto its anchor. Build it with
:class:molpy.builder.polymer.AmberPolymerBuilder, which cuts one
antechamber-typed oligomer with prepgen and sequences it with tleap.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
atom_type
|
Literal['gaff', 'gaff2']
|
The antechamber atom-type set, also the parmchk2 |
'gaff2'
|
charge_method
|
str
|
The antechamber |
'bcc'
|
work_dir
|
str | Path
|
Where the per-molecule directories are created. |
'amber_work'
|
env
|
str | Path | None
|
AmberTools environment (see :class: |
None
|
env_manager
|
str | None
|
Its manager ( |
None
|
match ¶
Type graph with antechamber and assign tleap's prmtop.
Raises:
| Type | Description |
|---|---|
ValueError
|
The prmtop disagrees with the graph. |
RuntimeError
|
An AmberTools step failed. |
AtdTypifier ¶
antechamber atom types — one rule engine over seven ATOMTYPE_*.DEF tables.
parameter_set is the antechamber -at flag and is required: seven
tables exist, they disagree, and there is no default. An atom no rule matches
comes back labelled "DU" — the table's own catch-all row, not a fallback.
ElementTypifier ¶
molrs.ff.typifier.ElementTypifier — type labels from element
symbols alone, with no force field.
Atoms get type = element (e.g. "C"); bonds, angles and dihedrals
get their endpoint elements joined with - in the byte-wise smaller
orientation (bond O–H is "H-O"). :meth:forcefield stays empty.
Exported from :mod:molrs.ff.typifier only.
Raises¶
ValueError
From :meth:typify, when an atom has no string element or the
molecule has impropers.
MMFF94STypifier ¶
MMFF94s (Halgren 1999) — the "static" set, for energy minimization.
Differs from MMFF94Typifier only on delocalised trivalent nitrogen (MMFF
numeric types 10 NC=O / 40 NC=C): 11 out-of-plane rows and 42 torsion
rows are re-parameterised so the nitrogen minimizes planar. typify bakes
koop = +0.015 (type 10) / +0.030 (type 40) mdArad^-2 on those
centres, where the improper kernel reads it as
E_oop = 0.5 * 143.9325 * koop * chi**2 (chi in radians). Every atom type
and every bond / angle / stretch-bend / vdW / charge parameter is shared with
MMFF94.
MMFF94Typifier ¶
MMFF94 (Halgren 1996) atom types, charges and bonded parameters.
The variant is the class, never a flag. See MMFF94STypifier for the
"static" parameter set.
typify labels the graph; PotentialCompiler(forcefield()).compile(frame)
compiles it. There is no one-step build — MMFF walks the same route as every other
force field.
Match ¶
What a typifier's match assigns to one graph.
nodes is positional against graph.atoms; links maps a relation
class (Bond, Angle, Dihedral, Improper) to rows positional
against graph.links.exact_bucket(cls) — the kind's own rows, so an
improper never shifts a dihedral position. An unknown kind raises
TypeError. styles are (category, style, params) to declare, in
order; pairs are (style, name, endpoints, params) pair rows.
TLeapTypifier ¶
TLeapTypifier(
*,
leaprc="gaff2",
forcefield=None,
work_dir="amber_work",
env=None,
env_manager=None,
)
Bases: _AmberLibrary
Parameterise an already typed graph with tleap alone.
The graph's atoms must carry AMBER atom types and charges. match
writes them as mol2, writes forcefield (the templates' parameters) as a
frcmod, runs tleap and assigns the prmtop's bonded terms, so junction terms
come from the leaprc. It never runs antechamber or parmchk2. Types and
charges are left as they are; tleap changing one raises. A graph that
still has ports is refused: joining those ports would fold the
leaving-group charge onto the anchors. A polymer chain is built with
:class:molpy.builder.polymer.AmberPolymerBuilder, whose prepgen step
spreads that charge instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
leaprc
|
Literal['gaff', 'gaff2']
|
The leaprc tleap sources ( |
'gaff2'
|
forcefield
|
ForceField | None
|
Parameters tleap loads on top of the leaprc, written as a
frcmod; |
None
|
work_dir
|
str | Path
|
Where the per-graph directories are created. |
'amber_work'
|
env
|
str | Path | None
|
AmberTools environment (see :class: |
None
|
env_manager
|
str | None
|
Its manager ( |
None
|
match ¶
Run tleap over graph's own types and charges; assign its prmtop.
Raises:
| Type | Description |
|---|---|
ValueError
|
An atom lacks a type or charge, tleap changed one, or the prmtop disagrees with the graph. |
RuntimeError
|
tleap failed. |
Typifier ¶
The base of every graph typifier: one match hook plus the output
force field its typing accumulates.
A subclass implements match (and optionally library) and nothing
else; defining typify on a subclass raises TypeError at class
creation. The native classes extend this base and only construct.
forcefield ¶
The accumulated output — exactly the definitions typify has
assigned — returned as a copy.
Edits to the copy do not reach the typifier; typify is the only
writer. Before the first typify it is the seeded empty output.
library ¶
The force field this typifier matches against, returned as a copy.
The output starts as its empty likeness (name, declared units and
special_bonds). A Python subclass that does not override it raises
NotImplementedError, and its output starts as an empty force field
named after the class.
match ¶
Match graph and return what it assigns.
match may write intermediate results (generated topology, perceived
bond types) onto the graph it is given; typify always gives it a
private copy. The base raises NotImplementedError; a native class
runs its Rust matcher.
typify ¶
Do not override; the only writer of forcefield().
Copies mol, calls match on the copy, and writes the match onto
the copy and the output. Returns the typed copy; mol is untouched.
mol must be an Atomistic (anything else raises TypeError).
Raises NotImplementedError without a match and ValueError
when the match does not fit the graph or contradicts the output (which
is then unchanged).
AmberTools typifiers¶
ambertools ¶
AmberTools typifiers: GAFF / GAFF2 through the AmberTools executables.
Two :class:molrs.ff.typifier.Typifier subclasses drive the
:mod:molpy.wrapper shells and read tleap's prmtop back:
- :class:
AntechamberTypifiertypes a complete molecule from scratch: antechamber (atom types and charges) → parmchk2 (missing parameters) → tleap. - :class:
TLeapTypifierparameterises a finished graph whose atoms already carry AMBER types and charges, with tleap alone. A graph that still has ports is refused. A polymer is built with :class:molpy.builder.polymer.AmberPolymerBuilder: antechamber, parmchk2 and prepgen on one oligomer, then tleapsequence.
Both return the prmtop's assignment as a :class:~molrs.ff.typifier.Match; the
molrs base owns typify and the accumulated forcefield().
AntechamberTypifier ¶
AntechamberTypifier(
*,
atom_type="gaff2",
charge_method="bcc",
work_dir="amber_work",
env=None,
env_manager=None,
)
Bases: _AmberLibrary
GAFF / GAFF2 atom types, charges and parameters for a complete molecule.
match runs antechamber (-at atom_type -c charge_method, net charge
from the atoms' formal charges), parmchk2 and tleap in a per-molecule
directory under work_dir, and assigns the prmtop's types, charges and
bonded terms. Ports are allowed; their leaving groups are real atoms.
A polymer chain is not typed here: joining typed monomers folds each
leaving group's charge onto its anchor. Build it with
:class:molpy.builder.polymer.AmberPolymerBuilder, which cuts one
antechamber-typed oligomer with prepgen and sequences it with tleap.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
atom_type
|
Literal['gaff', 'gaff2']
|
The antechamber atom-type set, also the parmchk2 |
'gaff2'
|
charge_method
|
str
|
The antechamber |
'bcc'
|
work_dir
|
str | Path
|
Where the per-molecule directories are created. |
'amber_work'
|
env
|
str | Path | None
|
AmberTools environment (see :class: |
None
|
env_manager
|
str | None
|
Its manager ( |
None
|
match ¶
Type graph with antechamber and assign tleap's prmtop.
Raises:
| Type | Description |
|---|---|
ValueError
|
The prmtop disagrees with the graph. |
RuntimeError
|
An AmberTools step failed. |
TLeapTypifier ¶
TLeapTypifier(
*,
leaprc="gaff2",
forcefield=None,
work_dir="amber_work",
env=None,
env_manager=None,
)
Bases: _AmberLibrary
Parameterise an already typed graph with tleap alone.
The graph's atoms must carry AMBER atom types and charges. match
writes them as mol2, writes forcefield (the templates' parameters) as a
frcmod, runs tleap and assigns the prmtop's bonded terms, so junction terms
come from the leaprc. It never runs antechamber or parmchk2. Types and
charges are left as they are; tleap changing one raises. A graph that
still has ports is refused: joining those ports would fold the
leaving-group charge onto the anchors. A polymer chain is built with
:class:molpy.builder.polymer.AmberPolymerBuilder, whose prepgen step
spreads that charge instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
leaprc
|
Literal['gaff', 'gaff2']
|
The leaprc tleap sources ( |
'gaff2'
|
forcefield
|
ForceField | None
|
Parameters tleap loads on top of the leaprc, written as a
frcmod; |
None
|
work_dir
|
str | Path
|
Where the per-graph directories are created. |
'amber_work'
|
env
|
str | Path | None
|
AmberTools environment (see :class: |
None
|
env_manager
|
str | None
|
Its manager ( |
None
|
match ¶
Run tleap over graph's own types and charges; assign its prmtop.
Raises:
| Type | Description |
|---|---|
ValueError
|
An atom lacks a type or charge, tleap changed one, or the prmtop disagrees with the graph. |
RuntimeError
|
tleap failed. |