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 |
-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)