Skip to content

datamol.viz

Vizualize molecule in 2D or 3D

to_image(mols, legends=None, n_cols=4, use_svg=False, mol_size=(200, 200), highlight_atom=None, highlight_bond=None, outfile=None, max_mols=32, copy=False, indices=False)

Generate an image out of a molecule or a list of molecule.

Parameters:

Name Type Description Default
mols Union[List[rdkit.Chem.rdchem.Mol], rdkit.Chem.rdchem.Mol]

one or a list of molecules.

required
legends Union[List[Optional[str]], str]

a string or a list of string as legend for every molecules.

None
n_cols int

number of molecules per column.

4
use_svg bool

whether to ouput an SVG (or a PNG).

False
mol_size Union[Tuple[int, int], int]

a int or a tuple of int defining the size per molecule.

(200, 200)
highlight_atom List[List[int]]

atom to highlight.

None
highlight_bond List[List[int]]

bonds to highlight.

None
outfile str

path where to save the image (local or remote path).

None
max_mols int

the maximum number of molecules to display.

32
copy bool

whether to copy the molecules or not.

False
indices bool

Whether to draw the atom indices.

False
Source code in datamol/viz/_viz.py
def to_image(
    mols: Union[List[Chem.rdchem.Mol], Chem.rdchem.Mol],
    legends: Union[List[Union[str, None]], str, None] = None,
    n_cols: int = 4,
    use_svg: bool = False,
    mol_size: Union[Tuple[int, int], int] = (200, 200),
    highlight_atom: List[List[int]] = None,
    highlight_bond: List[List[int]] = None,
    outfile: str = None,
    max_mols: int = 32,
    copy: bool = False,
    indices: bool = False,
):
    """Generate an image out of a molecule or a list of molecule.

    Args:
        mols: one or a list of molecules.
        legends: a string or a list of string as legend for every molecules.
        n_cols: number of molecules per column.
        use_svg: whether to ouput an SVG (or a PNG).
        mol_size: a int or a tuple of int defining the size per molecule.
        highlight_atom: atom to highlight.
        highlight_bond: bonds to highlight.
        outfile: path where to save the image (local or remote path).
        max_mols: the maximum number of molecules to display.
        copy: whether to copy the molecules or not.
        indices: Whether to draw the atom indices.
    """

    if isinstance(mol_size, int):
        mol_size = (mol_size, mol_size)

    if isinstance(mols, Chem.rdchem.Mol):
        mols = [mols]

    if isinstance(legends, str):
        legends = [legends]

    if copy:
        mols = [dm.copy_mol(mol) for mol in mols]

    if max_mols is not None:
        mols = mols[:max_mols]

        if legends is not None:
            legends = legends[:max_mols]

    if indices is True:
        [dm.atom_indices_to_mol(mol) for mol in mols]

    _highlight_atom = highlight_atom
    if highlight_atom is not None and isinstance(highlight_atom[0], int):
        _highlight_atom = [highlight_atom]

    _highlight_bond = highlight_bond
    if highlight_bond is not None and isinstance(highlight_bond[0], int):
        _highlight_bond = [highlight_bond]

    # Don't make the image bigger than it
    if len(mols) < n_cols:
        n_cols = len(mols)

    image = Draw.MolsToGridImage(
        mols,
        legends=legends,
        molsPerRow=n_cols,
        useSVG=use_svg,
        subImgSize=mol_size,
        highlightAtomLists=_highlight_atom,
        highlightBondLists=_highlight_bond,
    )

    if outfile is not None:
        with fsspec.open(outfile, "wb") as f:
            if use_svg:
                if isinstance(image, str):
                    # in a terminal process
                    f.write(image.encode())
                else:
                    # in a jupyter kernel process
                    f.write(image.data.encode())  # type: ignore
            else:
                if isinstance(image, PIL.PngImagePlugin.PngImageFile):  # type: ignore
                    # in a terminal process
                    image.save(f)
                else:
                    # in a jupyter kernel process
                    f.write(image.data)  # type: ignore

    return image

conformers(mol, conf_id=-1, n_confs=None, align_conf=True, n_cols=3, sync_views=True, remove_hs=True, width='auto')

Visualize the conformer(s) of a molecule.

Parameters:

Name Type Description Default
mol Mol

a molecule.

required
conf_id int

The ID of the conformer to show. -1 shows the first conformer. Only works if n_confs is None.

-1
n_confs Union[int, List[int]]

Can be a number of conformers to shows or a list of conformer indices. When None, only the first conformer is displayed. When -1, show all conformers.

None
align_conf bool

Whether to align conformers together.

True
n_cols int

Number of columns. Defaults to 3.

3
sync_views bool

Wether to sync the multiple views.

True
remove_hs bool

Wether to remove the hydrogens of the conformers.

True
width str

The width of the returned view. Defaults to "auto".

'auto'
Source code in datamol/viz/_conformers.py
def conformers(
    mol: Chem.rdchem.Mol,
    conf_id: int = -1,
    n_confs: Union[int, List[int]] = None,
    align_conf: bool = True,
    n_cols: int = 3,
    sync_views: bool = True,
    remove_hs: bool = True,
    width: str = "auto",
):
    """Visualize the conformer(s) of a molecule.

    Args:
        mol: a molecule.
        conf_id: The ID of the conformer to show. -1 shows
            the first conformer. Only works if `n_confs` is None.
        n_confs: Can be a number of conformers
            to shows or a list of conformer indices. When None, only the first
            conformer is displayed. When -1, show all conformers.
        align_conf: Whether to align conformers together.
        n_cols: Number of columns. Defaults to 3.
        sync_views: Wether to sync the multiple views.
        remove_hs: Wether to remove the hydrogens of the conformers.
        width: The width of the returned view. Defaults to "auto".
    """

    widgets = _get_ipywidgets()
    nv = _get_nglview()

    if mol.GetNumConformers() == 0:
        raise ValueError(
            "The molecule has 0 conformers. You can generate conformers with `dm.conformers.generate(mol)`."
        )

    # Clone the molecule
    mol = copy.deepcopy(mol)

    if remove_hs:
        mol = Chem.RemoveHs(mol)  # type: ignore
    else:
        mol = Chem.AddHs(mol)  # type: ignore

    if n_confs is None:
        return nv.show_rdkit(mol, conf_id=conf_id)

    # If n_confs is int, convert to list of conformer IDs
    if n_confs == -1:
        n_confs = [conf.GetId() for conf in mol.GetConformers()]
    elif isinstance(n_confs, int):
        if n_confs > mol.GetNumConformers():
            n_confs = mol.GetNumConformers()
        n_confs = list(range(n_confs))  # type: ignore

    if align_conf:
        rdMolAlign.AlignMolConformers(mol, confIds=n_confs)

    # Get number of rows
    n_rows = len(n_confs) // n_cols
    n_rows += 1 if (len(n_confs) % n_cols) > 0 else 0

    # Create a grid
    grid = widgets.GridspecLayout(n_rows, n_cols)  # type: ignore

    # Create and add views to the grid.
    widget_coords = itertools.product(range(n_rows), range(n_cols))
    views = []
    for i, (conf_id, (x, y)) in enumerate(zip(n_confs, widget_coords)):
        view = nv.show_rdkit(mol, conf_id=conf_id)
        view.layout.width = width
        view.layout.align_self = "stretch"
        grid[x, y] = view
        views.append(view)

    # Sync views
    if sync_views:
        for view in views:
            view._set_sync_camera(views)

    return grid

Specific plotting functions

MolsCircleGrid

__init__(self, center_mol, circle_mols, legend=None, mol_size=(200, 200), circle_margin=50, act_mapper=None) special

Show molecules in concentric rings, with one molecule at the center

Parameters:

Name Type Description Default
center_mol Mol

Molecule at center

required
circle_mols List[List[rdkit.Chem.rdchem.Mol]]

List of molecule for each concentric circle around the center mol

required
mol_size Tuple[int, int]

Tuple of width and height for each molecule

(200, 200)
circle_margin int

Margin between the circle layers

50
act_mapper dict

Map each molecule to a dictionary of activity

None
Source code in datamol/viz/_circle_grid.py
def __init__(
    self,
    center_mol: Chem.rdchem.Mol,
    circle_mols: List[List[Chem.rdchem.Mol]],
    legend: str = None,
    mol_size: Tuple[int, int] = (200, 200),
    circle_margin: int = 50,
    act_mapper: dict = None,
):
    """Show molecules in concentric rings, with one molecule at the center

    Args:
        center_mol: Molecule at center
        circle_mols: List of molecule for each concentric circle around the center mol
        mol_size: Tuple of width and height for each molecule
        circle_margin: Margin between the circle layers
        act_mapper: Map each molecule to a dictionary of activity
    """
    self.circle_mols = circle_mols
    self.circle_count = len(self.circle_mols)
    self.legend = legend or ""
    self.margin = circle_margin
    self.center_mol = center_mol
    self.mol_size = mol_size
    size = (max(mol_size) + self.margin) * (self.circle_count + 1)
    self.size = size
    self.image = Image.new(mode="RGBA", size=(size, size), color=(255, 255, 255, 0))
    self.midpoint = size // 2
    self.draw = None
    self.act_mapper = act_mapper or {}
    self._draw()

circle_grid(center_mol, circle_mols, legend=None, mol_size=(200, 200), circle_margin=50, act_mapper=None)

Show molecules in concentric rings, with one molecule at the center

Parameters:

Name Type Description Default
center_mol Mol

Molecule at center

required
circle_mols List[List[rdkit.Chem.rdchem.Mol]]

List of molecule for each concentric circle around the center mol

required
mol_size Tuple[int, int]

Tuple of width and height for each molecule

(200, 200)
circle_margin int

Margin between the circle layers

50
act_mapper dict

Map each molecule to a dictionary of activity

None
Source code in datamol/viz/_circle_grid.py
def circle_grid(
    center_mol: Chem.rdchem.Mol,
    circle_mols: List[List[Chem.rdchem.Mol]],
    legend: str = None,
    mol_size: Tuple[int, int] = (200, 200),
    circle_margin: int = 50,
    act_mapper: dict = None,
):
    """Show molecules in concentric rings, with one molecule at the center

    Args:
        center_mol (Chem.Mol): Molecule at center
        circle_mols (list of list of <Chem.Mol>): List of molecule for each concentric circle around the center mol
        mol_size (tuple, optional): Tuple of width and height for each molecule
        circle_margin (int, optional): Margin between the circle layers
        act_mapper (dict): Map each molecule to a dictionary of activity
    """
    return MolsCircleGrid(center_mol, circle_mols, legend, mol_size, circle_margin, act_mapper)