{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import bokehmol\n", "\n", "from bokeh.models import ColumnDataSource\n", "from bokeh.plotting import figure" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's start with some dummy data. You can provide input as a simple SMILES string,\n", "a SMILES string containing multiple fragments, or a list of SMILES to display as a grid." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# example dataset\n", "source = ColumnDataSource(\n", " data=dict(\n", " x=[1, 2, 3, 4, 5],\n", " y=[6, 7, 2, 4, 5],\n", " SMILES=[\n", " [\"O=C1CCCN1C\", \"O=C1CC(C)CN1C\"],\n", " \"c1ccccc1.c1ccccc1O\",\n", " [\"CN1C(=O)N(C)c2ncn(C)c2C1(=O)\", \"O=C1CCCN1C.O=C1CC(C)CN1C\"],\n", " \"C1C(=O)C=C2CCC3C4CCC(C(=O)CO)C4(C)CCC3C2(C)C1\",\n", " \"CC(=O)OC1=CC=CC=C1C(=O)O\",\n", " ]\n", " )\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "bokehmol.register_alias()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This assumes that your `ColumnDataSource` containing your data has a `SMILES` column.\n", "\n", "You can then hover over any glyph on the figure to reveal the corresponding structure:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", " \n", " \n", " Bokeh Plot\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " \n", " \n", "" ], "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "plot = figure(\n", " width=600, height=300,\n", " title=\"Basic RDKit Hover\",\n", " background_fill_color=\"#efefef\",\n", " tools=\"rdkit_hover,pan,wheel_zoom\",\n", ")\n", "\n", "plot.scatter(\"x\", \"y\", size=15, line_width=0, fill_color=\"firebrick\", source=source)\n", "\n", "bokehmol.show(plot)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Note on Jupyter notebooks and JupyterLab:\n", "\n", "Sometimes the JavaScript dependencies (RDKit or SmilesDrawer) aren't being injected/loaded properly in the notebook when using `bokeh.plotting.show`.\n", "\n", "We provide `bokehmol.show` instead to fix this issue in notebooks." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", " \n", " \n", " Bokeh Plot\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " \n", " \n", "" ], "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "plot = figure(\n", " width=600, height=300,\n", " title=\"Basic SmilesDrawer Hover\",\n", " background_fill_color=\"#efefef\",\n", " tools=\"smiles_hover,pan,wheel_zoom\",\n", ")\n", "\n", "plot.scatter(\"x\", \"y\", size=15, line_width=0, fill_color=\"firebrick\", source=source)\n", "\n", "bokehmol.show(plot)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", " \n", " \n", " Bokeh Plot\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " \n", " \n", "" ], "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "plot = figure(\n", " width=600, height=300,\n", " title=\"Configured RDKit Hover\",\n", " background_fill_color=\"#efefef\",\n", " tools=\"pan,wheel_zoom\",\n", ")\n", "\n", "mol_hover = bokehmol.hover.rdkit(\n", " smiles_column=\"SMILES\",\n", " tooltips=[\n", " (\"smiles\", \"@SMILES\"),\n", " ],\n", " draw_options={\n", " \"comicMode\": True\n", " },\n", " mols_per_row=1,\n", " width=-1,\n", " height=-1,\n", ")\n", "\n", "plot.add_tools(mol_hover)\n", "plot.scatter(\"x\", \"y\", size=15, line_width=0, fill_color=\"firebrick\", source=source)\n", "\n", "bokehmol.show(plot)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[31mSignature:\u001b[39m\n", "bokehmol.hover.rdkit(\n", " smiles_column: str = \u001b[33m'SMILES'\u001b[39m,\n", " tooltips: Union[str, List[Tuple[str, str]], NoneType] = \u001b[38;5;28;01mNone\u001b[39;00m,\n", " width: int = \u001b[32m160\u001b[39m,\n", " height: int = \u001b[32m120\u001b[39m,\n", " mols_per_row: int = \u001b[32m3\u001b[39m,\n", " remove_hs: bool = \u001b[38;5;28;01mTrue\u001b[39;00m,\n", " sanitize: bool = \u001b[38;5;28;01mTrue\u001b[39;00m,\n", " kekulize: bool = \u001b[38;5;28;01mTrue\u001b[39;00m,\n", " prefer_coordgen: bool = \u001b[38;5;28;01mTrue\u001b[39;00m,\n", " draw_options: Optional[Dict[str, Any]] = \u001b[38;5;28;01mNone\u001b[39;00m,\n", " **kwargs: Any,\n", ") -> \u001b[33m'RDKitHover'\u001b[39m\n", "\u001b[31mDocstring:\u001b[39m\n", "Hover tool that uses RDKit.js and the RDKit's Minimal Lib to depict\n", "SMILES strings on hover.\n", "\n", "Notes\n", "-----\n", "See https://www.npmjs.com/package/@rdkit/rdkit for the readme.\n", "\n", "Parameters\n", "----------\n", "smiles_column: str = \"SMILES\"\n", " Column in the `ColumnDataSource` object containing the SMILES string.\n", "tooltips: t.Union[str, t.List[t.Tuple[str, str]]] = None\n", " Tooltips to render below the depiction. Can be an HTML string, or a list of\n", " tuples specifying the display name and column name that you want to display.\n", " Column names must be prefixed with `@` (or `$` for bokeh's internal\n", " variables), see bokeh's docs for more info on tooltips formats::\n", "\n", " >>> bokehmol.hover.rdkit(\n", " ... tooltips=[\n", " ... (\"SMILES\", \"@SMILES\"),\n", " ... (\"Name\", \"@{Molecule name}\"),\n", " ... ]\n", " ... )\n", "\n", "width: int = 160\n", " Image width in pixels\n", "height: int = 120\n", " Image height in pixels\n", "mols_per_row: int = 3\n", " Number of molecules to display per row if a list of SMILES is used.\n", "remove_hs: bool = True\n", " Remove hydrogens from the depiction\n", "sanitize: bool = True\n", " Sanitize the molecule\n", "kekulize: bool = True\n", " Kekulize the molecule\n", "prefer_coordgen: bool = True\n", " Prefer the CoordGen library for macrocycle rendering\n", "draw_options: t.Dict[str, t.Any] = None\n", " RDKit's MolDrawOptions to control the style of the drawing:\n", " https://www.rdkitjs.com/#drawing-molecules-all-options.::\n", "\n", " >>> bokehmol.hover.rdkit(\n", " ... draw_options={\n", " ... \"addAtomIndices\": True,\n", " ... }\n", " ... )\n", "\n", "**kwargs: t.Any\n", " Additional parameters passed to bokeh's Hover tool.\n", "\n", "Returns\n", "-------\n", "An RDKit-based hover tool ready to be added to a bokeh plot::\n", "\n", " >>> from bokeh.plotting import figure\n", " >>> plot = figure(...)\n", " >>> hover_tool = bokehmol.hover.rdkit()\n", " >>> plot.add_tools(hover_tool)\n", "\u001b[31mFile:\u001b[39m ~/dev/bokehmol/.venv/lib/python3.12/site-packages/bokehmol/hover.py\n", "\u001b[31mType:\u001b[39m function" ] } ], "source": [ "# options available\n", "bokehmol.hover.rdkit?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Same with SmilesDrawer:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", " \n", " \n", " Bokeh Plot\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
\n", " \n", " \n", " \n", " \n", "" ], "text/plain": [ "" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "plot = figure(\n", " width=600, height=300,\n", " title=\"Configured SmilesDrawer Hover\",\n", " background_fill_color=\"#efefef\",\n", " tools=\"pan,wheel_zoom\",\n", ")\n", "\n", "mol_hover = bokehmol.hover.smiles_drawer(\n", " smiles_column=\"SMILES\",\n", " tooltips=[\n", " (\"smiles\", \"@SMILES\"),\n", " ],\n", " theme=\"cyberpunk\",\n", " background_colour=\"#3d3d3b\",\n", " mol_options={\n", " \"atomVisualization\": \"balls\"\n", " },\n", " mols_per_row=1,\n", ")\n", "\n", "plot.add_tools(mol_hover)\n", "plot.scatter(\"x\", \"y\", size=15, line_width=0, fill_color=\"firebrick\", source=source)\n", "\n", "bokehmol.show(plot)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[31mSignature:\u001b[39m\n", "bokehmol.hover.smiles_drawer(\n", " smiles_column: str = \u001b[33m'SMILES'\u001b[39m,\n", " tooltips: Union[str, List[Tuple[str, str]], NoneType] = \u001b[38;5;28;01mNone\u001b[39;00m,\n", " width: int = \u001b[32m160\u001b[39m,\n", " height: int = \u001b[32m120\u001b[39m,\n", " mols_per_row: int = \u001b[32m3\u001b[39m,\n", " theme: Literal[\u001b[33m'light'\u001b[39m, \u001b[33m'dark'\u001b[39m, \u001b[33m'oldschool'\u001b[39m, \u001b[33m'solarized'\u001b[39m, \u001b[33m'solarized-dark'\u001b[39m, \u001b[33m'matrix'\u001b[39m, \u001b[33m'github'\u001b[39m, \u001b[33m'carbon'\u001b[39m, \u001b[33m'cyberpunk'\u001b[39m, \u001b[33m'gruvbox'\u001b[39m, \u001b[33m'gruvbox-dark'\u001b[39m] = \u001b[33m'light'\u001b[39m,\n", " background_colour: str = \u001b[33m'transparent'\u001b[39m,\n", " mol_options: Optional[Dict[str, Any]] = \u001b[38;5;28;01mNone\u001b[39;00m,\n", " reaction_options: Optional[Dict[str, Any]] = \u001b[38;5;28;01mNone\u001b[39;00m,\n", " **kwargs: Any,\n", ") -> \u001b[33m'SmilesDrawerHover'\u001b[39m\n", "\u001b[31mDocstring:\u001b[39m\n", "Hover tool that uses SmilesDrawer to depict SMILES strings on hover.\n", "\n", "Notes\n", "-----\n", "See https://github.com/reymond-group/smilesDrawer#readme for the readme.\n", "Please cite the SmilesDrawer paper doi:10.1021/acs.jcim.7b00425 if you use this\n", "in academic work.\n", "\n", "Parameters\n", "----------\n", "smiles_column: str = \"SMILES\"\n", " Column in the `ColumnDataSource` object containing the SMILES string.\n", "tooltips: t.Union[str, t.List[t.Tuple[str, str]]] = None\n", " Tooltips to render below the depiction. Can be an HTML string, or a list of\n", " tuples specifying the display name and column name that you want to display.\n", " Column names must be prefixed with `@` (or `$` for bokeh's internal\n", " variables), see bokeh's docs for more info on tooltips formats::\n", "\n", " >>> bokehmol.hover.smiles_drawer(\n", " ... tooltips=[\n", " ... (\"SMILES\", \"@SMILES\"),\n", " ... (\"Name\", \"@{Molecule name}\"),\n", " ... ]\n", " ... )\n", "\n", "width: int = 160\n", " Image width in pixels\n", "height: int = 120\n", " Image height in pixels\n", "mols_per_row: int = 3\n", " Number of molecules to display per row if a list of SMILES is used.\n", "theme: str = \"light\"\n", " Theme used for the rendering. One of the following list: light, dark,\n", " oldschool, solarized, solarized-dark, matrix, github, carbon, cyberpunk,\n", " gruvbox, gruvbox-dark.\n", "background_colour: str = \"transparent\"\n", " Any valid CSS color specification.\n", "mol_options: t.Dict[str, t.Any] = None\n", " SmilesDrawer options to control the style of the molecule's drawing:\n", " https://smilesdrawer.surge.sh/playground.html.::\n", "\n", " >>> bokehmol.hover.smiles_drawer(\n", " ... mol_options={\n", " ... \"atomVisualization\": \"balls\",\n", " ... }\n", " ... )\n", "\n", "reaction_options: t.Dict[str, t.Any] = None\n", " Same as above for reaction's drawing.\n", "**kwargs: t.Any\n", " Additional parameters passed to bokeh's Hover tool.\n", "\n", "Returns\n", "-------\n", "A SmilesDrawer-based hover tool ready to be added to a bokeh plot::\n", "\n", " >>> from bokeh.plotting import figure\n", " >>> plot = figure(...)\n", " >>> hover_tool = bokehmol.hover.smiles_drawer()\n", " >>> plot.add_tools(hover_tool)\n", "\u001b[31mFile:\u001b[39m ~/dev/bokehmol/.venv/lib/python3.12/site-packages/bokehmol/hover.py\n", "\u001b[31mType:\u001b[39m function" ] } ], "source": [ "# options available\n", "bokehmol.hover.smiles_drawer?" ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.11" } }, "nbformat": 4, "nbformat_minor": 4 }