{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Custom Modifiers" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "> ### In this tutorial we will cover:\n", "> - how we can define our own modifier functions like `carboxylate`\n", "> - how we can define other modifier functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Building molecules is a straightforward task in BuildAMol. A \"modifier\" function is essentially any function that will take a molecule as argument and return a modified version thereof. There is technically nothing special about this process, so you can write any function that performs some action on the molecule and you have a working modifier. Why this tutorial then? You may have been using the available modifiers such as `hydroxylate` or `carboxylate` that can add functional groups to one or more positions in a molecule. This tutorial explains how they work so that you can more efficiently make your own modifiers. \n", "\n", "Let's dive in!" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ " \n", " " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import plotly\n", "plotly.offline.init_notebook_mode()" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "import buildamol as bam" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Functional Group Modifiers\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All the default modifiers share the same architecture actually. They take one molecule as argument alongside with information on where to modify, then they obtain a reference molecule for the respective functional group they want to add, then they call the `_modify` function which provides a generic implementation for attaching one molecule (the functional group) to multiple locations of a target molecule.\n", "\n", "To illustrate this, let's remake our own `carboxylate` function!" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[Molecule(CBX), Molecule(FMT)]" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# first we need to get a suitable reference molecule for the carboxyl group. \n", "# Formic Acid should be the best choice. Let's see if we have that in the database\n", "bam.load_small_molecules()\n", "bam.get_compound(\"formic acid\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So we have even two! `CBX` is officially called `carboxy group` in the database while `FMT` is `formic acid`, but structurally they are identical. Let's use `CBX` for our function. Now that we know which reference molecule to use for our carboxyl group we can do additional preprocessing steps. For instance, it is common to call the carbonyl-carbon `C` and the hydroxyl-Oxygen `OXT`. If we want our carboxyl group to adhere to these conventions we will have to rename the atoms accordingly. " ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/noahhk/anaconda3/envs/glyco2/lib/python3.11/site-packages/plotly/express/_core.py:1985: FutureWarning:\n", "\n", "When grouping with a length-1 list-like, you will need to pass a length-1 tuple to get_group in a future version of pandas. Pass `(name,)` instead of `name` to silence this warning.\n", "\n" ] }, { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "customdata": [ [ "C", 1, 1, "CBX", "A" ] ], "hovertemplate": "atom_element=C
x=%{x}
y=%{y}
z=%{z}
__marker_size=%{marker.size}
atom_id=%{customdata[0]}
atom_serial=%{customdata[1]}
residue_serial=%{customdata[2]}
residue_name=%{customdata[3]}
chain_id=%{customdata[4]}", "legendgroup": "C", "marker": { "color": "darkslategray", "opacity": 1, "size": [ 5 ], "sizemode": "area", "sizeref": 0.0125, "symbol": "circle" }, "mode": "markers", "name": "C", "scene": "scene", "showlegend": true, "type": "scatter3d", "x": [ -0.097 ], "y": [ 0.421 ], "z": [ 0 ] }, { "customdata": [ [ "O", 2, 1, "CBX", "A" ], [ "OXT", 3, 1, "CBX", "A" ] ], "hovertemplate": "atom_element=O
x=%{x}
y=%{y}
z=%{z}
__marker_size=%{marker.size}
atom_id=%{customdata[0]}
atom_serial=%{customdata[1]}
residue_serial=%{customdata[2]}
residue_name=%{customdata[3]}
chain_id=%{customdata[4]}", "legendgroup": "O", "marker": { "color": "red", "opacity": 1, "size": [ 5, 5 ], "sizemode": "area", "sizeref": 0.0125, "symbol": "circle" }, "mode": "markers", "name": "O", "scene": "scene", "showlegend": true, "type": "scatter3d", "x": [ -1.125, 1.085 ], "y": [ -0.214, -0.215 ], "z": [ 0, 0 ] }, { "customdata": [ [ "H", 4, 1, "CBX", "A" ], [ "HXT", 5, 1, "CBX", "A" ] ], "hovertemplate": "atom_element=H
x=%{x}
y=%{y}
z=%{z}
__marker_size=%{marker.size}
atom_id=%{customdata[0]}
atom_serial=%{customdata[1]}
residue_serial=%{customdata[2]}
residue_name=%{customdata[3]}
chain_id=%{customdata[4]}", "legendgroup": "H", "marker": { "color": "lightgray", "opacity": 1, "size": [ 5, 5 ], "sizemode": "area", "sizeref": 0.0125, "symbol": "circle" }, "mode": "markers", "name": "H", "scene": "scene", "showlegend": true, "type": "scatter3d", "x": [ -0.129, 1.908 ], "y": [ 1.501, 0.293 ], "z": [ 0, 0 ] }, { "hoverinfo": "skip", "line": { "color": "black", "width": 5.76 }, "mode": "lines", "showlegend": false, "type": "scatter3d", "x": [ -0.097, -1.125 ], "y": [ 0.421, -0.214 ], "z": [ 0, 0 ] }, { "hoverinfo": "skip", "line": { "color": "black", "width": 1.44 }, "mode": "lines", "showlegend": false, "type": "scatter3d", "x": [ -0.097, 1.085 ], "y": [ 0.421, -0.215 ], "z": [ 0, 0 ] }, { "hoverinfo": "skip", "line": { "color": "black", "width": 1.44 }, "mode": "lines", "showlegend": false, "type": "scatter3d", "x": [ -0.097, -0.129 ], "y": [ 0.421, 1.501 ], "z": [ 0, 0 ] }, { "hoverinfo": "skip", "line": { "color": "black", "width": 1.44 }, "mode": "lines", "showlegend": false, "type": "scatter3d", "x": [ 1.085, 1.908 ], "y": [ -0.215, 0.293 ], "z": [ 0, 0 ] } ], "layout": { "scene": { "xaxis": { "showgrid": false, "showline": false, "showticklabels": false }, "yaxis": { "showgrid": false, "showline": false, "showticklabels": false }, "zaxis": { "showgrid": false, "showline": false, "showticklabels": false } }, "template": { "data": { "bar": [ { "error_x": { "color": "rgb(36,36,36)" }, "error_y": { "color": "rgb(36,36,36)" }, "marker": { "line": { "color": "white", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "white", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "rgb(36,36,36)", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "rgb(36,36,36)" }, "baxis": { "endlinecolor": "rgb(36,36,36)", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "rgb(36,36,36)" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" }, "colorscale": [ [ 0, "#440154" ], [ 0.1111111111111111, "#482878" ], [ 0.2222222222222222, "#3e4989" ], [ 0.3333333333333333, "#31688e" ], [ 0.4444444444444444, "#26828e" ], [ 0.5555555555555556, "#1f9e89" ], [ 0.6666666666666666, "#35b779" ], [ 0.7777777777777778, "#6ece58" ], [ 0.8888888888888888, "#b5de2b" ], [ 1, "#fde725" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" }, "colorscale": [ [ 0, "#440154" ], [ 0.1111111111111111, "#482878" ], [ 0.2222222222222222, "#3e4989" ], [ 0.3333333333333333, "#31688e" ], [ 0.4444444444444444, "#26828e" ], [ 0.5555555555555556, "#1f9e89" ], [ 0.6666666666666666, "#35b779" ], [ 0.7777777777777778, "#6ece58" ], [ 0.8888888888888888, "#b5de2b" ], [ 1, "#fde725" ] ], "type": "heatmap" } ], "heatmapgl": [ { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" }, "colorscale": [ [ 0, "#440154" ], [ 0.1111111111111111, "#482878" ], [ 0.2222222222222222, "#3e4989" ], [ 0.3333333333333333, "#31688e" ], [ 0.4444444444444444, "#26828e" ], [ 0.5555555555555556, "#1f9e89" ], [ 0.6666666666666666, "#35b779" ], [ 0.7777777777777778, "#6ece58" ], [ 0.8888888888888888, "#b5de2b" ], [ 1, "#fde725" ] ], "type": "heatmapgl" } ], "histogram": [ { "marker": { "line": { "color": "white", "width": 0.6 } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" }, "colorscale": [ [ 0, "#440154" ], [ 0.1111111111111111, "#482878" ], [ 0.2222222222222222, "#3e4989" ], [ 0.3333333333333333, "#31688e" ], [ 0.4444444444444444, "#26828e" ], [ 0.5555555555555556, "#1f9e89" ], [ 0.6666666666666666, "#35b779" ], [ 0.7777777777777778, "#6ece58" ], [ 0.8888888888888888, "#b5de2b" ], [ 1, "#fde725" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" }, "colorscale": [ [ 0, "#440154" ], [ 0.1111111111111111, "#482878" ], [ 0.2222222222222222, "#3e4989" ], [ 0.3333333333333333, "#31688e" ], [ 0.4444444444444444, "#26828e" ], [ 0.5555555555555556, "#1f9e89" ], [ 0.6666666666666666, "#35b779" ], [ 0.7777777777777778, "#6ece58" ], [ 0.8888888888888888, "#b5de2b" ], [ 1, "#fde725" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "fillpattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" } }, "marker": { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" } }, "type": "scattergl" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" }, "colorscale": [ [ 0, "#440154" ], [ 0.1111111111111111, "#482878" ], [ 0.2222222222222222, "#3e4989" ], [ 0.3333333333333333, "#31688e" ], [ 0.4444444444444444, "#26828e" ], [ 0.5555555555555556, "#1f9e89" ], [ 0.6666666666666666, "#35b779" ], [ 0.7777777777777778, "#6ece58" ], [ 0.8888888888888888, "#b5de2b" ], [ 1, "#fde725" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "rgb(237,237,237)" }, "line": { "color": "white" } }, "header": { "fill": { "color": "rgb(217,217,217)" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 1, "tickcolor": "rgb(36,36,36)", "ticks": "outside" } }, "colorscale": { "diverging": [ [ 0, "rgb(103,0,31)" ], [ 0.1, "rgb(178,24,43)" ], [ 0.2, "rgb(214,96,77)" ], [ 0.3, "rgb(244,165,130)" ], [ 0.4, "rgb(253,219,199)" ], [ 0.5, "rgb(247,247,247)" ], [ 0.6, "rgb(209,229,240)" ], [ 0.7, "rgb(146,197,222)" ], [ 0.8, "rgb(67,147,195)" ], [ 0.9, "rgb(33,102,172)" ], [ 1, "rgb(5,48,97)" ] ], "sequential": [ [ 0, "#440154" ], [ 0.1111111111111111, "#482878" ], [ 0.2222222222222222, "#3e4989" ], [ 0.3333333333333333, "#31688e" ], [ 0.4444444444444444, "#26828e" ], [ 0.5555555555555556, "#1f9e89" ], [ 0.6666666666666666, "#35b779" ], [ 0.7777777777777778, "#6ece58" ], [ 0.8888888888888888, "#b5de2b" ], [ 1, "#fde725" ] ], "sequentialminus": [ [ 0, "#440154" ], [ 0.1111111111111111, "#482878" ], [ 0.2222222222222222, "#3e4989" ], [ 0.3333333333333333, "#31688e" ], [ 0.4444444444444444, "#26828e" ], [ 0.5555555555555556, "#1f9e89" ], [ 0.6666666666666666, "#35b779" ], [ 0.7777777777777778, "#6ece58" ], [ 0.8888888888888888, "#b5de2b" ], [ 1, "#fde725" ] ] }, "colorway": [ "#1F77B4", "#FF7F0E", "#2CA02C", "#D62728", "#9467BD", "#8C564B", "#E377C2", "#7F7F7F", "#BCBD22", "#17BECF" ], "font": { "color": "rgb(36,36,36)" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "white", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "white", "polar": { "angularaxis": { "gridcolor": "rgb(232,232,232)", "linecolor": "rgb(36,36,36)", "showgrid": false, "showline": true, "ticks": "outside" }, "bgcolor": "white", "radialaxis": { "gridcolor": "rgb(232,232,232)", "linecolor": "rgb(36,36,36)", "showgrid": false, "showline": true, "ticks": "outside" } }, "scene": { "xaxis": { "backgroundcolor": "white", "gridcolor": "rgb(232,232,232)", "gridwidth": 2, "linecolor": "rgb(36,36,36)", "showbackground": true, "showgrid": false, "showline": true, "ticks": "outside", "zeroline": false, "zerolinecolor": "rgb(36,36,36)" }, "yaxis": { "backgroundcolor": "white", "gridcolor": "rgb(232,232,232)", "gridwidth": 2, "linecolor": "rgb(36,36,36)", "showbackground": true, "showgrid": false, "showline": true, "ticks": "outside", "zeroline": false, "zerolinecolor": "rgb(36,36,36)" }, "zaxis": { "backgroundcolor": "white", "gridcolor": "rgb(232,232,232)", "gridwidth": 2, "linecolor": "rgb(36,36,36)", "showbackground": true, "showgrid": false, "showline": true, "ticks": "outside", "zeroline": false, "zerolinecolor": "rgb(36,36,36)" } }, "shapedefaults": { "fillcolor": "black", "line": { "width": 0 }, "opacity": 0.3 }, "ternary": { "aaxis": { "gridcolor": "rgb(232,232,232)", "linecolor": "rgb(36,36,36)", "showgrid": false, "showline": true, "ticks": "outside" }, "baxis": { "gridcolor": "rgb(232,232,232)", "linecolor": "rgb(36,36,36)", "showgrid": false, "showline": true, "ticks": "outside" }, "bgcolor": "white", "caxis": { "gridcolor": "rgb(232,232,232)", "linecolor": "rgb(36,36,36)", "showgrid": false, "showline": true, "ticks": "outside" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "rgb(232,232,232)", "linecolor": "rgb(36,36,36)", "showgrid": false, "showline": true, "ticks": "outside", "title": { "standoff": 15 }, "zeroline": false, "zerolinecolor": "rgb(36,36,36)" }, "yaxis": { "automargin": true, "gridcolor": "rgb(232,232,232)", "linecolor": "rgb(36,36,36)", "showgrid": false, "showline": true, "ticks": "outside", "title": { "standoff": 15 }, "zeroline": false, "zerolinecolor": "rgb(36,36,36)" } } } } }, "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# do some atom renaming \n", "# (call the `show` method to see \n", "# the molecule before renaming if \n", "# you want to check the atom names beforehand)\n", "carboxyl = bam.Molecule.from_compound(\"CBX\")\n", "carboxyl.rename_atom(\"O1\", \"O\")\\\n", " .rename_atom(\"O2\", \"OXT\")\\\n", " .rename_atom(\"HO2\", \"HXT\")\n", "\n", "carboxyl.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Great! Now that we have our \"final\" carboxyl group molecule we can think about making our actual modifier function. To do that we simply define a function with the following signature:\n", "\n", "```python\n", "def add_carboxyl(mol, at_atom, delete, inplace):\n", " # get and preprocess the carboxyl group molecule\n", " carboxyl = ...\n", " # then call _modify with the following arguments\n", " return _modify(\n", " mol=mol, \n", " modifier=carboxyl, \n", " at_atom=at_atom, \n", " delete=delete, \n", " modifier_at_atom=, \n", " modifier_deletes=,\n", " inplace=inplace\n", " )\n", "```\n", "\n", "> Note: `_modify` will create linkages automatically and the default rule of removing a hydrogen neighbor if no deleting atoms are specified still applies. So we don't necessarily have to specifiy deleter atoms!\n", "\n", "Or fully implemented:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "# import the _modify function\n", "from buildamol.core.Molecule import _modify\n", "\n", "def add_carboxyl(mol, at_atom, delete=None, inplace=True):\n", " # prepare our carboxyl group\n", " carboxyl = bam.Molecule.from_compound(\"CBX\")\n", " carboxyl.rename_atom(\"O1\", \"O\")\\\n", " .rename_atom(\"O2\", \"OXT\")\\\n", " .rename_atom(\"HO2\", \"HXT\")\n", " # we want to attach the carboxyl group at the \"C\" atom (carbonyl carbon)\n", " # and remove the \"H\" atom (hydrogen from the \"C\" atom)\n", " return _modify(\n", " mol, carboxyl,\n", " at_atom=at_atom, delete=delete, inplace=inplace,\n", " modifier_at_atom=\"C\", modifier_deletes=[\"H\"]\n", " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And that's it! Let's test our function:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "application/3dmoljs_load.v0": "
\n

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n jupyter labextension install jupyterlab_3dmol

\n
\n", "text/html": [ "
\n", "

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n", " jupyter labextension install jupyterlab_3dmol

\n", "
\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# let's carboxylate a benzene molecule\n", "benzene = bam.get_compound(\"benzene\")\n", "\n", "for carbon in benzene.get_atoms(\"C\", by=\"element\"):\n", " # since we are removing a hydrogen atom, \n", " # we don't have to specify the delete parameter\n", " benzene = add_carboxyl(benzene, carbon)\n", "\n", "benzene.py3dmol().show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But since we are using `_modify` the automatic casting also works so we don't have to bother with writing our own loop to iterate over multiple atoms. We can simply pass a list of target atoms to attach to like so:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "application/3dmoljs_load.v0": "
\n

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n jupyter labextension install jupyterlab_3dmol

\n
\n", "text/html": [ "
\n", "

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n", " jupyter labextension install jupyterlab_3dmol

\n", "
\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "benzene = bam.get_compound(\"benzene\")\n", "# we pass a list of atom identifiers (ids in this case)\n", "benzene = add_carboxyl(benzene, [\"C1\", \"C3\", \"C5\"])\n", "\n", "benzene.py3dmol().show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Other Modifiers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Of course \"modifiers\" don't necessarily have to add functional groups onto a molecule, any function that will alter something in a molecule's structure is a modifier, after all! \n", "\n", "Let's make a second example that will invert all double bonds in a molecule from cis to trans or vice versa!" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "application/3dmoljs_load.v0": "
\n

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n jupyter labextension install jupyterlab_3dmol

\n
\n", "text/html": [ "
\n", "

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n", " jupyter labextension install jupyterlab_3dmol

\n", "
\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# let's start by making a testing molecule\n", "# using the polycarbon extension\n", "from buildamol.extensions.polymers import linear_alkene\n", "\n", "alkene = linear_alkene(10)\n", "\n", "# and make two double bonds into cis double bonds\n", "alkene.cis(\"C3\", \"C4\").cis(\"C7\", \"C8\")\n", "\n", "alkene.py3dmol().show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cool, so you may have noticed that I called `alkene.cis(...)` just now. We can modify the stereochemistry of double bonds using the methods `Molecule.cis` and `Molecule.trans` and we can check if a specific bond is in cis or trans configuration using `Molecule.is_cis` and `Molecule.is_trans`, respectively. \n", "\n", "Hopefully, by this point you already have an idea of how our \"bond inversion\" modifier function could look like. Here's the architecture:\n", "- get all double bonds\n", "- assert for each if they are in trans or cis\n", "- apply the inverse operation cis->trans / trans->cis on each double bond\n", "\n", "There is no pre-made function like `_modify` that we can (or need to) use here. It's just a standard function like so:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "def invert_stereo(mol):\n", " # get all double bonds\n", " double_bonds = (i for i in mol.get_bonds() if i.order == 2)\n", " # now split them up in cis and trans\n", " cis_bonds = []\n", " trans_bonds = []\n", " for bond in double_bonds:\n", " if mol.is_cis(bond):\n", " cis_bonds.append(bond)\n", " elif mol.is_trans(bond):\n", " trans_bonds.append(bond)\n", " \n", " # now we can invert the stereochemistry\n", " for bond in cis_bonds:\n", " mol.trans(bond)\n", " for bond in trans_bonds:\n", " mol.cis(bond)\n", " \n", " return mol\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Great! Let's see if it works:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "application/3dmoljs_load.v0": "
\n

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n jupyter labextension install jupyterlab_3dmol

\n
\n", "text/html": [ "
\n", "

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n", " jupyter labextension install jupyterlab_3dmol

\n", "
\n", "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "alkene_inverted = invert_stereo(alkene.copy())\n", "\n", "alkene_inverted.py3dmol().show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cool, there we have the middle bond in cis and the two others in trans!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That's it for this tutorial! We saw that we can quite easily make functions to add specific functional groups in a versatile way. So, if your projects involve often doing the same kinds of steps, maybe try making some modifiers in a separate python module and thereby develop your own little BuildAMol extension!\n", "\n", "Thanks for checking out this tutorial and good luck with your projects using BuildAMol!" ] } ], "metadata": { "kernelspec": { "display_name": "glyco2", "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.11.0" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 }