vibesketch.chem.mapping

Which reactant atom becomes which product atom: an atom mapping for a reaction (#29).

A reaction path between two sketches needs both endpoints’ atoms in the same order, so every reactant atom must be paired with one product atom of the same element. The pairing chosen is the one that changes the fewest bonds, the principle of minimum chemical distance (I. Ugi et al., Angew. Chem. Int. Ed. 18, 111-123 (1979); J. Jauffret, C. Tonnelier, J.-E. Dubois, Tetrahedron Comput. Methodol. 3, 335-349 (1990)):

  • the cost of a pairing of the heavy atoms is the number of bonds between them it forms and breaks, plus two for every hydrogen that has to move to another atom (one bond broken, one formed);

  • every cheapest pairing is found by a depth-first branch and bound over the heavy atoms, element by element, breadth first through each molecule, so a partial pairing’s cost prunes early; a search that grows too large stops and asks for pinned atoms instead of guessing;

  • pairings that cost the same and differ only by the molecules’ own symmetry describe the same reaction. When the cheapest pairings describe different reactions (which oxygen leaves in an esterification; a [3,3] or a [1,3] shift in a Claisen rearrangement, which break and form the same number of bonds), the mapping is ambiguous: no writer guesses, and the user pins atoms. Of the cheapest, the one changing the fewest bond orders is shown first; that is a presentation order, not a chemical argument.

Hydrogens are paired here by the heavy atoms they sit on; where several are equivalent, the reaction-path endpoints pair them by position (vibesketch.chem.endpoints). RXNMapper (MIT) maps from learned attention, but needs torch, too heavy for a core dependency.

Functions

balance_problems(reactants, products)

Why the two sides cannot be paired atom for atom; empty if they can.

map_reaction(reactants, products[, pinned])

The cheapest pairing of the reactants' atoms with the products'.

side(species)

The side made of (id, SMILES) species, each once, in order.

Classes

AtomMapping(reactants, products, pairs, cost)

A pairing of every reactant atom with a product atom.

Side(mol, owners, species)

One side of a reaction: its species as one molecule, with explicit hydrogens.

Exceptions

MappingFailed

The reaction's atoms cannot be paired; the message says why.

class vibesketch.chem.mapping.AtomMapping(reactants, products, pairs, cost, alternatives=(), pinned=<factory>)[source]

Bases: object

A pairing of every reactant atom with a product atom.

Parameters:
reactants: Side
products: Side
pairs: tuple[int, ...]

pairs[i] is the product atom reactant atom i becomes.

cost: int

Bonds formed and broken, and hydrogens moved, as the cost counts them.

alternatives: tuple[tuple[int, ...], ...] = ()

Other cheapest pairings that describe a different reaction, as pairs.

pinned: tuple[tuple[int, int], ...]

Atoms the user pinned, as (reactant, product) indices.

property ambiguous: bool[source]
changes(pairs=None)[source]

What the pairing does, one line per bond formed, broken or changed.

Parameters:

pairs (Sequence[int] | None)

Return type:

list[str]

centre(pairs=None)[source]

The reaction centre: heavy reactant atoms with a bond formed, broken or changed.

A hydrogen that moves puts the heavy atoms it leaves and joins in the centre.

Parameters:

pairs (Sequence[int] | None)

Return type:

set[int]

exception vibesketch.chem.mapping.MappingFailed[source]

Bases: ValueError

The reaction’s atoms cannot be paired; the message says why.

class vibesketch.chem.mapping.Side(mol, owners, species)[source]

Bases: object

One side of a reaction: its species as one molecule, with explicit hydrogens.

Each species contributes its atoms in the order of its 3D structure (vibesketch.chem.embed.embed_3d()): its SMILES atoms, then the hydrogens RDKit adds.

Parameters:
mol: Any
owners: tuple[tuple[str, int], ...]

the species id and the atom’s index within that species.

Type:

Per atom

species: tuple[tuple[str, str, int], ...]

its id, SMILES and first atom index here.

Type:

Per species, in order

label(atom)[source]

m1:C3: the species, the element and the 1-based atom number within it.

Parameters:

atom (int)

Return type:

str

vibesketch.chem.mapping.balance_problems(reactants, products)[source]

Why the two sides cannot be paired atom for atom; empty if they can.

Parameters:
Return type:

list[str]

vibesketch.chem.mapping.map_reaction(reactants, products, pinned=())[source]

The cheapest pairing of the reactants’ atoms with the products’.

pinned holds (reactant atom, product atom) pairs the pairing must keep: heavy atoms of the same element. Raises MappingFailed when the sides are not balanced or a pin is impossible.

Parameters:
Return type:

AtomMapping

vibesketch.chem.mapping.side(species)[source]

The side made of (id, SMILES) species, each once, in order.

Parameters:

species (Sequence[tuple[str, str]])

Return type:

Side