{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from openff.toolkit import Molecule"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Note**: The content below demonstrates usage of `nglview` with `openforcefield`. This can be tricky to get working. Install with:\n",
"\n",
" conda install -c conda-forge nglview\n",
" \n",
"And configure for use with Jupyter with:\n",
"\n",
" jupyter-nbextension enable nglview --py --sys-prefix\n",
" \n",
"To use with Jupyterlab, configure with:\n",
"\n",
" jupyter labextension install nglview-js-widgets\n",
" jupyter-labextension install @jupyter-widgets/jupyterlab-manager"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Built-in visualizations in `openff-toolkit`\n",
"\n",
"PR [#560](https://github.com/openforcefield/openforcefield/pull/560) introduced rich representation for the `Molecule` objects. This means you can visualize them in your Jupyter Notebooks.\n",
"\n",
"We have implemented three backends:\n",
"- rdkit\n",
"- openeye\n",
"- nglview (requires conformers)\n",
"\n",
"There are two ways to invoke the visualization:\n",
"- implicitly, by _evaluating_ the object in a cell\n",
"- explicitly, by calling `Molecule.visualize()`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"_Implicit_ visualization will try to use `nglview` if there are conformers and fall back to `rdkit` and `openeye` (in that order) if they are not available."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "eb5ef9732d0b469abefa109be1c2553c",
"version_major": 2,
"version_minor": 0
},
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"m = Molecule.from_smiles(\"CCCCOCC\")\n",
"m"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The regular `display()` call works on `Molecule` objects too."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"display(m) # noqa"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"_Explicit_ visualization works as one would expect:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"m.visualize()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This method can take a `backend` parameter, which defaults to `rdkit`:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"m.visualize(backend=\"rdkit\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`openeye` can also be used, if available:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"try:\n",
" from openeye import oechem\n",
"\n",
" assert oechem.OEChemIsLicensed()\n",
"\n",
" m.visualize(backend=\"openeye\")\n",
"except (ImportError, AssertionError):\n",
" print('Visualizing with `backend=\"openeye\"` requires the OpenEye Toolkits')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`nglview`, if installed, can only be used if conformers have been generated:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"tags": [
"nbval-skip"
]
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Visualizing with NGLview requires that the molecule has conformers.\n"
]
}
],
"source": [
"try:\n",
" m.visualize(backend=\"nglview\") # this will fail because we have no conformers yet\n",
"except ValueError as excinfo:\n",
" # Catch the exception and print its message\n",
" print(str(excinfo))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"But, once you generate them, it works! You can zoom in/out, rotate and translate the molecule. You can even inspect the different conformers (if available) using the trajectory player:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"tags": [
"nbval-skip"
]
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "6fcbd2baf38244cba5ba31cf0bd86f14",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"NGLWidget(max_frame=2)"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"m.generate_conformers()\n",
"m.visualize(backend=\"nglview\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For example, a benzene ring will not have multiple conformers, so you won't see the trajectory player."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"tags": [
"nbval-skip"
]
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "041384084ceb41fcb23c677e445eaa6a",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"NGLWidget()"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"n = Molecule.from_smiles(\"c1ccccc1\")\n",
"n.generate_conformers()\n",
"n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notice that, once conformers are available, the implicit representation will use `nglview` to provide a 3D visualization."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.8.12"
}
},
"nbformat": 4,
"nbformat_minor": 4
}