Skip to content

Adapter

In-memory conversion between MolPy objects and an external library's representation — the in-memory half of MolPy's two bridging patterns. The other half is the wrapper, which shells out to a binary instead.

An adapter is a pair of pure functions, to_<lib> / from_<lib>: each builds a new object and leaves its input untouched. MolPy keeps one worked example: to_rdkit / from_rdkit. Packing is not an adapter — use molpack (pip install molcrafts-molpack). An example is not a dependency — RDKit is an optional extra (pip install "molcrafts-molpy[rdkit]"), importing molpy never requires it, and no molpy code path routes through it.

Quick reference

Symbol Summary Preferred for
to_rdkit(atomistic) New sanitized RDKit Mol from an Atomistic Handing a structure to RDKit's own algorithms
from_rdkit(mol, conf_id=-1) New Atomistic from an RDKit Mol Bringing RDKit's result back
generate_3d(atomistic) RDKit ETKDGv3 embedding (+ UFF), as a round trip Comparing against RDKit's embedder
PROP_PREFIX "molpy:", the namespace of carried RDKit properties Reading carried components on the RDKit side

Canonical example

The examples below share this setup:

import molpy as mp

mol = mp.io.smiles.read_smiles("CCO").to_atomistic()
# docs: skip — RDKit optional adapter example; not unit-tested
import molpy as mp
from molpy.adapter import from_rdkit, to_rdkit
from rdkit import Chem
from rdkit.Chem import AllChem

mol = mp.io.smiles.read_smiles("CCO").to_atomistic()

rd_mol = Chem.AddHs(to_rdkit(mol))
AllChem.EmbedMolecule(rd_mol)  # RDKit's algorithm, on RDKit's object
AllChem.MMFFOptimizeMolecule(rd_mol)

optimized = from_rdkit(rd_mol)  # a new molpy Atomistic; `mol` is unchanged

What crosses the boundary

To RDKit Back to MolPy
Element, formal charge, bond type, coordinates RDKit's own fields (one conformer) RDKit's values win
Bracket hydrogen count (h_count, SMILES [nH]) Sets RDKit's H count on that atom Carried back unchanged
Every other atom / bond component (name, res_name, res_id, type, charge, mass, bond_number, a bond's type, …) RDKit property molpy:<key> Restored on the atoms and bonds RDKit kept
Scalar Atomistic.props Mol property molpy:<key> Restored

What does not survive the round trip:

  • Atoms or bonds RDKit removes (RemoveHs, fragment stripping) are absent from the result. Atoms or bonds RDKit creates (AddHs) carry RDKit-owned fields only.
  • Angles, dihedrals, impropers and ports: only atoms and bonds cross. Regenerate the rest with generate_topology.
  • Stereo is not translated. molpy's stereo component does not become RDKit chiral tags or bond stereo, and RDKit's chiral tags, bond stereo and CIP labels do not come back. The stereo component itself rides along untouched, so it is stale if RDKit changed that atom's neighbours.
  • Recomputed facts: when RDKit changes a bond's type, the carried bond_number is replaced by the number the new type implies (none for aromatic). Nothing else is recomputed — an atom whose element RDKit changes keeps its old mass and type.
  • Extra conformers: from_rdkit reads one (conf_id).
  • A graph prop that is not a bool, int, float or str makes to_rdkit raise TypeError rather than drop it silently.

Do not use it for what MolPy already does

The adapter exists to reach algorithms MolPy does not implement. For anything below, the native path is the supported one and needs no third-party install:

Task Native
3D embedding Conformer — ETKDGv3 → torsion refinement → MMFF94 cleanup
Hydrogens / aromaticity / stereo mp.perceive.add_hydrogens(...) / mp.perceive.assign_aromaticity(...)
SMILES / SMARTS mp.io.smiles.read_smiles(...).to_atomistic(), mp.perceive.SmartsPattern — see Notation
Ring queries mp.perceive.perceive_rings(mol) → RingSet
GAFF types AmberTools wrapper — antechamber delegation
mol_3d, report = mp.conformer.Conformer(add_hydrogens=True, seed=42).generate(mol)

Key behavior

  • every function returns a new object and never mutates its input
  • import molpy.adapter works without RDKit; reading to_rdkit, from_rdkit or generate_3d then raises ImportError naming the extra to install
  • an adapter does in-memory conversion only — executing an external binary belongs in a wrapper

Full API

to_rdkit

to_rdkit(atomistic)

Build a sanitized RDKit Mol from atomistic; the input is not touched.

RDKit atom i is atomistic's atom i and RDKit bond k its bond k. A conformer is added when every atom has coordinates. See the module docstring for what is carried and what is lost.

Parameters:

Name Type Description Default
atomistic Atomistic

The structure to convert. Every atom needs an atomic_number.

required

Returns:

Type Description
Mol

A new, sanitized rdkit.Chem.Mol.

Raises:

Type Description
KeyError

If an atom has no atomic_number, or only some atoms have coordinates (a missing coordinate is not 0.0).

ValueError

If a bond type has no RDKit counterpart.

TypeError

If a graph-level prop is not a bool, int, float or str.

RuntimeError

If RDKit cannot sanitize the result.

from_rdkit

from_rdkit(mol, *, conf_id=-1)

Build a new :class:~molpy.Atomistic from mol; the input is not touched.

Atom i of the result is RDKit atom i. Components carried by :func:to_rdkit come back on the atoms and bonds RDKit kept; RDKit's own fields (element, formal charge, bond type, coordinates) override them. See the module docstring for what is lost.

Parameters:

Name Type Description Default
mol Mol

Any RDKit molecule — one from :func:to_rdkit after RDKit worked on it, or one RDKit built itself.

required
conf_id int

The conformer to read coordinates from; -1 is RDKit's default. A mol with no conformer gives atoms without coordinates.

-1

Returns:

Type Description
Atomistic

A new Atomistic with atoms and bonds only.

Raises:

Type Description
ValueError

If a bond type has no molpy counterpart (dative, …).

generate_3d

generate_3d(
    atomistic, *, add_hydrogens=True, optimize=True
)

Embed 3D coordinates with RDKit's ETKDGv3, optionally UFF-relaxed.

A round trip through :func:to_rdkit and :func:from_rdkit: the result is a new Atomistic and atomistic is not touched. Hydrogens RDKit adds carry RDKit-owned fields only. For molpy's native embedder, use :class:molpy.conformer.Conformer instead.

Parameters:

Name Type Description Default
atomistic Atomistic

The structure to embed.

required
add_hydrogens bool

Add explicit hydrogens before embedding.

True
optimize bool

Relax the embedded geometry with UFF.

True

Returns:

Type Description
Atomistic

A new Atomistic with coordinates.

Raises:

Type Description
ValueError

If atomistic has no atoms.

RuntimeError

If RDKit cannot sanitize or embed the molecule.