Explicitly Defining Ligand Networks#

OpenFE provides utilities for ingesting networks from ordinary Python datastructures like list[tuple[str, str]] and list[tuple[int, int]].

Each string or integer respectively names or indexes a ligand, and tuples represent edges in the network.

This explicit definition of networks supports use-cases where the desired edges are known and may be helpful for loading networks from other tools.

Although this is the most flexible way to define a LigandNetwork, we encourage you to use openfe helper functionality when possible for performance, reproducibility, and ease of use:

Load the ligands#

This cookbook assumes you’ve already loaded a collection of SmallMoleculeComponent objects into an iterable called ligands.

For more information, see Loading Small Molecules.

[1]:
%matplotlib inline
from rdkit import Chem
import openfe

supplier = Chem.SDMolSupplier("assets/somebenzenes.sdf", removeHs=False)
ligands = [openfe.SmallMoleculeComponent(mol) for mol in supplier]

ligands
[1]:
[SmallMoleculeComponent(name=benzene),
 SmallMoleculeComponent(name=toluene),
 SmallMoleculeComponent(name=phenol),
 SmallMoleculeComponent(name=benzonitrile),
 SmallMoleculeComponent(name=anisole),
 SmallMoleculeComponent(name=benzaldehyde),
 SmallMoleculeComponent(name=styrene)]

Select an atom mapper#

As we will only specify the topology of the network, OpenFE must generate atom mappings for us. For this, it needs an atom mapper; for more information, see Choose an Atom Mapper:

[2]:
mapper = openfe.setup.LomapAtomMapper(
    threed=True, # Use atom positions to prune symmetric mappings
    max3d=1.0, # Forbid mapping between atoms more than 1.0 Å apart
    element_change=False, # Forbid mappings that change an atoms element
)

Define the network#

We can inspect the ligands to identify what we’re working with:

[3]:
print(*enumerate(ligands), sep="\n")
(0, SmallMoleculeComponent(name=benzene))
(1, SmallMoleculeComponent(name=toluene))
(2, SmallMoleculeComponent(name=phenol))
(3, SmallMoleculeComponent(name=benzonitrile))
(4, SmallMoleculeComponent(name=anisole))
(5, SmallMoleculeComponent(name=benzaldehyde))
(6, SmallMoleculeComponent(name=styrene))

Then, define the network topology by specifying transformations between ligands, either by name or index:

[4]:
topology_by_names = [
    ("styrene", "toluene"),
    ("benzonitrile", "toluene"),
    ("toluene", "benzene"),
    ("benzene", "phenol"),
    ("phenol", "anisole"),
    ("phenol", "benzaldehyde"),
]

topology_by_indices = [
    (6, 1),
    (3, 1),
    (1, 0),
    (0, 2),
    (2, 4),
    (2, 5),
]

Create the network#

[5]:
from openfe.setup import ligand_network_planning

Now create the LigandNetwork object from the specified edges:

[6]:
ligand_network_from_names = ligand_network_planning.generate_network_from_names(
    ligands=ligands,
    mapper=mapper,
    names=topology_by_names,
)

ligand_network_from_indices = ligand_network_planning.generate_network_from_indices(
    ligands=ligands,
    mapper=mapper,
    indices=topology_by_indices,
)
parallel map scoring
/Users/atravitz/micromamba/envs/openfe-notebooks/lib/python3.13/site-packages/gufe/components/explicitmoleculecomponent.py:74: UserWarning: RDKit does not preserve Mol properties when pickled by default, which may drop e.g. atom charges; consider setting `Chem.SetDefaultPickleProperties(Chem.PropertyPickleOptions.AllProps)`
  warnings.warn(
parallel map scoring
/Users/atravitz/micromamba/envs/openfe-notebooks/lib/python3.13/site-packages/gufe/components/explicitmoleculecomponent.py:74: UserWarning: RDKit does not preserve Mol properties when pickled by default, which may drop e.g. atom charges; consider setting `Chem.SetDefaultPickleProperties(Chem.PropertyPickleOptions.AllProps)`
  warnings.warn(
/Users/atravitz/micromamba/envs/openfe-notebooks/lib/python3.13/site-packages/gufe/components/explicitmoleculecomponent.py:74: UserWarning: RDKit does not preserve Mol properties when pickled by default, which may drop e.g. atom charges; consider setting `Chem.SetDefaultPickleProperties(Chem.PropertyPickleOptions.AllProps)`
  warnings.warn(

Visualise the network#

For more ways to visualize a LigandNetwork, see Visualizing Ligand Networks.

[7]:
from openfe.utils.atommapping_network_plotting import plot_atommapping_network

plot_atommapping_network(ligand_network_from_names)
[7]:
../_images/cookbook_hand_write_ligand_network_19_0.png