In [1]:
import bokehmol

from bokeh.models import ColumnDataSource
from bokeh.plotting import figure

Let's start with some dummy data. You can provide input as a simple SMILES string, a SMILES string containing multiple fragments, or a list of SMILES to display as a grid.

In [2]:
# example dataset
source = ColumnDataSource(
    data=dict(
        x=[1, 2, 3, 4, 5],
        y=[6, 7, 2, 4, 5],
        SMILES=[
            ["O=C1CCCN1C", "O=C1CC(C)CN1C"],
            "c1ccccc1.c1ccccc1O",
            ["CN1C(=O)N(C)c2ncn(C)c2C1(=O)", "O=C1CCCN1C.O=C1CC(C)CN1C"],
            "C1C(=O)C=C2CCC3C4CCC(C(=O)CO)C4(C)CCC3C2(C)C1",
            "CC(=O)OC1=CC=CC=C1C(=O)O",
        ]
    )
)

The easiest way to use bokehmol is to import the package, run the bokehmol.register_alias() function, and then specify either rdkit_hover or smiles_hover in the tools parameter of the bokeh figure.

In [3]:
bokehmol.register_alias()

This assumes that your ColumnDataSource containing your data has a SMILES column.

You can then hover over any glyph on the figure to reveal the corresponding structure:

In [4]:
plot = figure(
    width=600, height=300,
    title="Basic RDKit Hover",
    background_fill_color="#efefef",
    tools="rdkit_hover,pan,wheel_zoom",
)

plot.scatter("x", "y", size=15, line_width=0, fill_color="firebrick", source=source)

bokehmol.show(plot)
Out[4]:
Bokeh Plot

Note on Jupyter notebooks and JupyterLab:¶

Sometimes the JavaScript dependencies (RDKit or SmilesDrawer) aren't being injected/loaded properly in the notebook when using bokeh.plotting.show.

We provide bokehmol.show instead to fix this issue in notebooks.

In [5]:
plot = figure(
    width=600, height=300,
    title="Basic SmilesDrawer Hover",
    background_fill_color="#efefef",
    tools="smiles_hover,pan,wheel_zoom",
)

plot.scatter("x", "y", size=15, line_width=0, fill_color="firebrick", source=source)

bokehmol.show(plot)
Out[5]:
Bokeh Plot

If your SMILES column has a different name, you can instantiate the molecule hover tool directly and parametrize it further. With this, the bokehmol.register_alias() call in the example above is not necessary.

In [6]:
plot = figure(
    width=600, height=300,
    title="Configured RDKit Hover",
    background_fill_color="#efefef",
    tools="pan,wheel_zoom",
)

mol_hover = bokehmol.hover.rdkit(
    smiles_column="SMILES",
    tooltips=[
        ("smiles", "@SMILES"),
    ],
    draw_options={
        "comicMode": True
    },
    mols_per_row=1,
    width=-1,
    height=-1,
)

plot.add_tools(mol_hover)
plot.scatter("x", "y", size=15, line_width=0, fill_color="firebrick", source=source)

bokehmol.show(plot)
Out[6]:
Bokeh Plot
In [7]:
# options available
bokehmol.hover.rdkit?
Signature:
bokehmol.hover.rdkit(
    smiles_column: str = 'SMILES',
    tooltips: Union[str, List[Tuple[str, str]], NoneType] = None,
    width: int = 160,
    height: int = 120,
    mols_per_row: int = 3,
    remove_hs: bool = True,
    sanitize: bool = True,
    kekulize: bool = True,
    prefer_coordgen: bool = True,
    draw_options: Optional[Dict[str, Any]] = None,
    **kwargs: Any,
) -> 'RDKitHover'
Docstring:
Hover tool that uses RDKit.js and the RDKit's Minimal Lib to depict
SMILES strings on hover.

Notes
-----
See https://www.npmjs.com/package/@rdkit/rdkit for the readme.

Parameters
----------
smiles_column: str = "SMILES"
    Column in the `ColumnDataSource` object containing the SMILES string.
tooltips: t.Union[str, t.List[t.Tuple[str, str]]] = None
    Tooltips to render below the depiction. Can be an HTML string, or a list of
    tuples specifying the display name and column name that you want to display.
    Column names must be prefixed with `@` (or `$` for bokeh's internal
    variables), see bokeh's docs for more info on tooltips formats::

        >>> bokehmol.hover.rdkit(
        ...     tooltips=[
        ...         ("SMILES", "@SMILES"),
        ...         ("Name", "@{Molecule name}"),
        ...     ]
        ... )

width: int = 160
    Image width in pixels
height: int = 120
    Image height in pixels
mols_per_row: int = 3
    Number of molecules to display per row if a list of SMILES is used.
remove_hs: bool = True
    Remove hydrogens from the depiction
sanitize: bool = True
    Sanitize the molecule
kekulize: bool = True
    Kekulize the molecule
prefer_coordgen: bool = True
    Prefer the CoordGen library for macrocycle rendering
draw_options: t.Dict[str, t.Any] = None
    RDKit's MolDrawOptions to control the style of the drawing:
    https://www.rdkitjs.com/#drawing-molecules-all-options.::

        >>> bokehmol.hover.rdkit(
        ...     draw_options={
        ...         "addAtomIndices": True,
        ...     }
        ... )

**kwargs: t.Any
    Additional parameters passed to bokeh's Hover tool.

Returns
-------
An RDKit-based hover tool ready to be added to a bokeh plot::

    >>> from bokeh.plotting import figure
    >>> plot = figure(...)
    >>> hover_tool = bokehmol.hover.rdkit()
    >>> plot.add_tools(hover_tool)
File:      ~/dev/bokehmol/.venv/lib/python3.12/site-packages/bokehmol/hover.py
Type:      function

Same with SmilesDrawer:

In [8]:
plot = figure(
    width=600, height=300,
    title="Configured SmilesDrawer Hover",
    background_fill_color="#efefef",
    tools="pan,wheel_zoom",
)

mol_hover = bokehmol.hover.smiles_drawer(
    smiles_column="SMILES",
    tooltips=[
        ("smiles", "@SMILES"),
    ],
    theme="cyberpunk",
    background_colour="#3d3d3b",
    mol_options={
        "atomVisualization": "balls"
    },
    mols_per_row=1,
)

plot.add_tools(mol_hover)
plot.scatter("x", "y", size=15, line_width=0, fill_color="firebrick", source=source)

bokehmol.show(plot)
Out[8]:
Bokeh Plot
In [9]:
# options available
bokehmol.hover.smiles_drawer?
Signature:
bokehmol.hover.smiles_drawer(
    smiles_column: str = 'SMILES',
    tooltips: Union[str, List[Tuple[str, str]], NoneType] = None,
    width: int = 160,
    height: int = 120,
    mols_per_row: int = 3,
    theme: Literal['light', 'dark', 'oldschool', 'solarized', 'solarized-dark', 'matrix', 'github', 'carbon', 'cyberpunk', 'gruvbox', 'gruvbox-dark'] = 'light',
    background_colour: str = 'transparent',
    mol_options: Optional[Dict[str, Any]] = None,
    reaction_options: Optional[Dict[str, Any]] = None,
    **kwargs: Any,
) -> 'SmilesDrawerHover'
Docstring:
Hover tool that uses SmilesDrawer to depict SMILES strings on hover.

Notes
-----
See https://github.com/reymond-group/smilesDrawer#readme for the readme.
Please cite the SmilesDrawer paper doi:10.1021/acs.jcim.7b00425 if you use this
in academic work.

Parameters
----------
smiles_column: str = "SMILES"
    Column in the `ColumnDataSource` object containing the SMILES string.
tooltips: t.Union[str, t.List[t.Tuple[str, str]]] = None
    Tooltips to render below the depiction. Can be an HTML string, or a list of
    tuples specifying the display name and column name that you want to display.
    Column names must be prefixed with `@` (or `$` for bokeh's internal
    variables), see bokeh's docs for more info on tooltips formats::

        >>> bokehmol.hover.smiles_drawer(
        ...     tooltips=[
        ...         ("SMILES", "@SMILES"),
        ...         ("Name", "@{Molecule name}"),
        ...     ]
        ... )

width: int = 160
    Image width in pixels
height: int = 120
    Image height in pixels
mols_per_row: int = 3
    Number of molecules to display per row if a list of SMILES is used.
theme: str = "light"
    Theme used for the rendering. One of the following list: light, dark,
    oldschool, solarized, solarized-dark, matrix, github, carbon, cyberpunk,
    gruvbox, gruvbox-dark.
background_colour: str = "transparent"
    Any valid CSS color specification.
mol_options: t.Dict[str, t.Any] = None
    SmilesDrawer options to control the style of the molecule's drawing:
    https://smilesdrawer.surge.sh/playground.html.::

        >>> bokehmol.hover.smiles_drawer(
        ...     mol_options={
        ...         "atomVisualization": "balls",
        ...     }
        ... )

reaction_options: t.Dict[str, t.Any] = None
    Same as above for reaction's drawing.
**kwargs: t.Any
    Additional parameters passed to bokeh's Hover tool.

Returns
-------
A SmilesDrawer-based hover tool ready to be added to a bokeh plot::

    >>> from bokeh.plotting import figure
    >>> plot = figure(...)
    >>> hover_tool = bokehmol.hover.smiles_drawer()
    >>> plot.add_tools(hover_tool)
File:      ~/dev/bokehmol/.venv/lib/python3.12/site-packages/bokehmol/hover.py
Type:      function