Skip to content

Commit

Permalink
Fixed plotting bug (#107)
Browse files Browse the repository at this point in the history

* Fixed plotting and added tutorial

Co-authored-by: Heta Gandhi <[email protected]>
  • Loading branch information
whitead and hgandhi2411 authored Jun 4, 2022
1 parent 08c40ff commit ae692fd
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 4 deletions.
4 changes: 4 additions & 0 deletions docs/source/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ Change Log

v2.1.1 (2022-6-03)
------------
* Fixed plotting bug in `plot_descriptors`

v2.1.0 (2022-6-03)
------------
* `plot_descriptors` will no longer save to file without filename

v2.0.1 (2022-5-31)
Expand Down
1 change: 1 addition & 0 deletions docs/source/toc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ exmol
index.md
changelog.rst
api.rst
paper2_LIME/Tutorial.ipynb
paper1_CFs/Schematic.ipynb
paper1_CFs/RF.ipynb
paper1_CFs/GNN.ipynb
Expand Down
7 changes: 4 additions & 3 deletions exmol/exmol.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from tkinter.messagebox import RETRY
from typing import *
import io
import math
Expand Down Expand Up @@ -889,7 +890,7 @@ def plot_descriptors(
figure_kwargs: Dict = None,
title: str = None,
multiple_bases: Optional[bool] = None,
return_svg: bool = True,
return_svg: bool = False,
):
"""Plot descriptor attributions from given set of Examples.
Expand All @@ -907,12 +908,12 @@ def plot_descriptors(
import pickle # type: ignore

# infer descriptor_type from examples
descriptor_type = examples[0].descriptors.descriptor_type
descriptor_type = examples[0].descriptors.descriptor_type.lower()

if multiple_bases is None:
multiple_bases = _check_multiple_bases(examples)

if output_file is None and descriptor_type == "ecfp":
if output_file is None and descriptor_type == "ecfp" and not return_svg:
raise ValueError("No filename provided to save the plot")

space_tstats = list(examples[0].descriptors.tstats)
Expand Down
2 changes: 1 addition & 1 deletion exmol/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "2.1.0"
__version__ = "2.1.1"
211 changes: 211 additions & 0 deletions paper2_LIME/Tutorial.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "268aa5bd",
"metadata": {},
"source": [
"## Tutorial\n",
"\n",
"We'll show here how to explain molecular property prediction tasks without access to the gradients or any properties of a molecule. To set-up this activity, we need a black box model. We'll use something simple here -- the model is classifier that says if a molecule as an alcohol (1) or not (0). Let's implement this model first"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6c4df8f8",
"metadata": {},
"outputs": [],
"source": [
"from rdkit import Chem\n",
"from rdkit.Chem.Draw import IPythonConsole\n",
"\n",
"# set-up rdkit drawing preferences\n",
"IPythonConsole.ipython_useSVG = True\n",
"IPythonConsole.drawOptions.drawMolsSameScale = False\n",
"\n",
"\n",
"def model(smiles):\n",
" mol = Chem.MolFromSmiles(smiles)\n",
" match = mol.GetSubstructMatches(Chem.MolFromSmarts(\"[O;!H0]\"))\n",
" return 1 if match else 0"
]
},
{
"cell_type": "markdown",
"id": "3db1a8b9",
"metadata": {},
"source": [
"Let's now try it out on some molecules"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b159d717",
"metadata": {},
"outputs": [],
"source": [
"smi = \"CCCCCCO\"\n",
"print(\"f(s)\", model(smi))\n",
"Chem.MolFromSmiles(smi)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e43dfad4",
"metadata": {},
"outputs": [],
"source": [
"smi = \"OCCCCCCO\"\n",
"print(\"f(s)\", model(smi))\n",
"Chem.MolFromSmiles(smi)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "755e9d8b",
"metadata": {},
"outputs": [],
"source": [
"smi = \"c1ccccc1\"\n",
"print(\"f(s)\", model(smi))\n",
"Chem.MolFromSmiles(smi)"
]
},
{
"cell_type": "markdown",
"id": "98567bf6",
"metadata": {},
"source": [
"### Counterfacutal explanations\n",
"\n",
"Let's now explain the model - pretending we don't know how it works - using counterfactuals"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "04ff227e",
"metadata": {
"tags": [
"remove-output"
]
},
"outputs": [],
"source": [
"import exmol\n",
"\n",
"instance = \"CCCCCCO\"\n",
"space = exmol.sample_space(instance, model, batched=False)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9c4438b3",
"metadata": {},
"outputs": [],
"source": [
"cfs = exmol.cf_explain(space, 1)\n",
"exmol.plot_cf(cfs)"
]
},
{
"cell_type": "markdown",
"id": "07be4df9",
"metadata": {},
"source": [
"We can see that removing the alcohol is the smallest change to affect the prediction of this molecule. Let's see the space and look at where these counterfactuals are."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "41349ccc",
"metadata": {},
"outputs": [],
"source": [
"exmol.plot_space(space, cfs)"
]
},
{
"cell_type": "markdown",
"id": "4ee39b33",
"metadata": {},
"source": [
"### Explain using substructures\n",
"\n",
"Now we'll try to explain our model using substructures."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ed252205",
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"exmol.lime_explain(space)\n",
"exmol.plot_descriptors(space)"
]
},
{
"cell_type": "markdown",
"id": "c406b957",
"metadata": {},
"source": [
"This seems like a pretty clear explanation. Let's take a look at using substructures that are present in the molecule"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0326fc65",
"metadata": {},
"outputs": [],
"source": [
"import skunk\n",
"\n",
"exmol.lime_explain(space, descriptor_type=\"ECFP\")\n",
"svg = exmol.plot_descriptors(space, return_svg=True)\n",
"skunk.display(svg)\n",
"exmol.plot_utils.similarity_map_using_tstats(space[0])"
]
},
{
"cell_type": "markdown",
"id": "2834e1bc",
"metadata": {},
"source": [
"We can see that most of the model is explained from the presence of the alcohol group - as expected"
]
}
],
"metadata": {
"celltoolbar": "Tags",
"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": 5
}

0 comments on commit ae692fd

Please sign in to comment.