From 820c9c8aabc04a3c664ca81918350cac624a6e3d Mon Sep 17 00:00:00 2001 From: Christopher Zou Date: Tue, 11 Aug 2020 17:23:04 -0400 Subject: [PATCH 1/7] Add hashes, molecule registration, and update create-write documentation --- ...ng and Writing to MongoDB-checkpoint.ipynb | 528 ++++++++++++++++-- .../Creating and Writing to MongoDB.ipynb | 521 +++++++++++++++-- mongordkit/Database/registration.py | 93 +++ mongordkit/Database/tests/test_write.py | 70 ++- mongordkit/Database/utils.py | 2 +- mongordkit/Database/write.py | 117 ++-- mongordkit/Search/tests/test_similarity.py | 12 +- mongordkit/Search/tests/test_substructure.py | 4 +- 8 files changed, 1171 insertions(+), 176 deletions(-) create mode 100644 mongordkit/Database/registration.py diff --git a/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb b/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb index 0dd6819..cdd4ad1 100644 --- a/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb +++ b/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb @@ -6,7 +6,7 @@ "source": [ "# Creating and Writing to MongoDB\n", "\n", - "Last updated: 7/12/20\n", + "Last updated: 8/10/20\n", "\n", "Methods that directly modify MongoDB database instances are included in the `mongordkit.Database` module.\n", "\n", @@ -16,11 +16,12 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ - "from mongordkit.Database import create, write, utils\n", + "from mongordkit.Database import create, write, utils, registration\n", + "from rdkit import Chem\n", "import pymongo" ] }, @@ -29,26 +30,25 @@ "metadata": {}, "source": [ "## Reset Cells\n", - "Run the contents of this cell to reset the local MongoDB database used in this notebook." + "Run the contents of this cell to reset the local MongoDB database, `demo_db`, used in this notebook." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "client = pymongo.MongoClient()\n", - "print(client.list_database_names())\n", - "client.drop_database('TestDatabase')\n", - "print(client.list_database_names())" + "client.drop_database('demo_db')\n", + "demo_db = client.demo_db" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Creating Databases\n", + "## Creating Databases (DEPRECATED for now)\n", "Users can opt to bring their own database instances, but `Database.create` provides methods that will create ready-made MongoDB instances, defaulting to your local MongoDB:" ] }, @@ -58,11 +58,11 @@ "metadata": {}, "outputs": [], "source": [ - "# Return a database using a host port, such as the local port:\n", - "TestDB = create.createFromHostPort('TestDatabase', host='localhost', port=27017)\n", + "# # Return a database using a host port, such as the local port:\n", + "# db = create.createFromHostPort('demo_db', host='localhost', port=27017)\n", "\n", - "# Return a database using a MongoDB URI, such as that provided by Atlas:\n", - "TestDB = create.createFromURL('TestDatabase', url=None)" + "# # Return a database using a MongoDB URI, such as that provided by Atlas:\n", + "# TestDB = create.createFromURL('demo_db', url=None)" ] }, { @@ -78,7 +78,134 @@ "metadata": {}, "outputs": [], "source": [ - "print(utils.STANDARD_SETTING)" + "# print(utils.STANDARD_SETTING)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Data Registration\n", + "`Database.registration` constructs document representations of molecules according to configurable schemes and handles data registration settings.\n", + "\n", + "It does this in two parts. First, it defines the global variables `RDKIT_HASH_FUNCTIONS` and `HASH_FUNCTIONS` as dictionaries that hold map hash function names to methods. It also defines the global variables `DEFAULT_SCHEME_NAME`, `DEFAULT_AUTHOR`, `DEFAULT_PREPROCESS`, and `DEFAULT_INDEX`, which are used in scheme creation and are thus defined for easy configuration. \n", + "\n", + "Second, the file defines the `MolDocScheme` object, which stores scheme information in its instance variables and is passed into `.write` methods in order to specify molecule document format. By default, `MolDocScheme` includes scheme name, author, whether or not the molecule has been pre-processed, an index option, hashes, fingerprints, and value fields. All of the information contained in a `MolDocScheme` object can be used directly to generate documents for molecules:" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'rdmol': Binary(b'\\xef\\xbe\\xad\\xde\\x00\\x00\\x00\\x00\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x80\\x01\\x06\\x00`\\x00\\x00\\x00\\x01\\x03\\x06@(\\x00\\x00\\x00\\x03\\x04\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x0b\\x00\\x01\\x00\\x01\\x02h\\x0c\\x02\\x03h\\x0c\\x03\\x04h\\x0c\\x04\\x05h\\x0c\\x05\\x06h\\x0c\\x06\\x01h\\x0c\\x14\\x01\\x06\\x01\\x06\\x05\\x04\\x03\\x02\\x17\\x00\\x00\\x00\\x00\\x16', 0),\n", + " 'index': 'YXFVVABEGXRONW-UHFFFAOYSA-N',\n", + " 'smiles': 'Cc1ccccc1',\n", + " 'scheme': 'default',\n", + " 'hashes': {'inchi_standard': 'InChI=1S/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", + " 'inchikey_KET_15T': 'YXFVVABEGXRONW-UHFFFAOYNA-N',\n", + " 'noiso_smiles': 'Cc1ccccc1',\n", + " 'MoleculeHashString': '100-7-7-SaZjmQ-zcSDYw-aXeP/g-122pug-haQS5A-qxXe4Q',\n", + " 'inchi_KET_15T': 'InChI=1/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", + " 'inchikey_standard': 'YXFVVABEGXRONW-UHFFFAOYSA-N',\n", + " 'cx_smiles': 'Cc1ccccc1'},\n", + " 'rdkit_hashes': {'Mesomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", + " 'HetAtomProtomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", + " 'Regioisomer': '*C.c1ccccc1',\n", + " 'MurckoScaffold': 'c1ccccc1',\n", + " 'ArthorSubstructureOrder': '00070007010007000000002a000000',\n", + " 'ExtendedMurcko': '*c1ccccc1',\n", + " 'DegreeVector': '0,1,5,1',\n", + " 'RedoxPair': 'C[C]1[CH][CH][CH][CH][CH]1',\n", + " 'SmallWorldIndexBR': 'B7R1',\n", + " 'MolFormula': 'C7H8',\n", + " 'AtomBondCounts': '7,7',\n", + " 'ElementGraph': 'CC1CCCCC1',\n", + " 'CanonicalSmiles': 'Cc1ccccc1',\n", + " 'SmallWorldIndexBRL': 'B7R1L5',\n", + " 'HetAtomTautomer': 'C[C]1[CH][CH][CH][CH][CH]1_0_0',\n", + " 'NetCharge': '0',\n", + " 'AnonymousGraph': '**1*****1'},\n", + " 'fingerprints': {},\n", + " 'value_data': {}}" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rdmol = Chem.MolFromSmiles('Cc1ccccc1')\n", + "scheme = registration.MolDocScheme()\n", + "scheme.generate_mol_doc(rdmol)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `MolDocScheme` class also defines a series of instance methods, such as `MolDocScheme.set_index` and `MolDocScheme.remove_field`, that can be used to modify document schemes:" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'rdmol': Binary(b'\\xef\\xbe\\xad\\xde\\x00\\x00\\x00\\x00\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x80\\x01\\x06\\x00`\\x00\\x00\\x00\\x01\\x03\\x06@(\\x00\\x00\\x00\\x03\\x04\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x0b\\x00\\x01\\x00\\x01\\x02h\\x0c\\x02\\x03h\\x0c\\x03\\x04h\\x0c\\x04\\x05h\\x0c\\x05\\x06h\\x0c\\x06\\x01h\\x0c\\x14\\x01\\x06\\x01\\x06\\x05\\x04\\x03\\x02\\x17\\x00\\x00\\x00\\x00\\x16', 0),\n", + " 'index': 'C7H8',\n", + " 'smiles': 'Cc1ccccc1',\n", + " 'scheme': 'default',\n", + " 'hashes': {'inchi_standard': 'InChI=1S/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", + " 'inchikey_KET_15T': 'YXFVVABEGXRONW-UHFFFAOYNA-N',\n", + " 'noiso_smiles': 'Cc1ccccc1',\n", + " 'MoleculeHashString': '100-7-7-SaZjmQ-zcSDYw-aXeP/g-122pug-haQS5A-qxXe4Q',\n", + " 'inchi_KET_15T': 'InChI=1/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", + " 'inchikey_standard': 'YXFVVABEGXRONW-UHFFFAOYSA-N',\n", + " 'cx_smiles': 'Cc1ccccc1'},\n", + " 'rdkit_hashes': {'Mesomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", + " 'HetAtomProtomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", + " 'Regioisomer': '*C.c1ccccc1',\n", + " 'MurckoScaffold': 'c1ccccc1',\n", + " 'ArthorSubstructureOrder': '00070007010007000000002a000000',\n", + " 'ExtendedMurcko': '*c1ccccc1',\n", + " 'DegreeVector': '0,1,5,1',\n", + " 'RedoxPair': 'C[C]1[CH][CH][CH][CH][CH]1',\n", + " 'SmallWorldIndexBR': 'B7R1',\n", + " 'MolFormula': 'C7H8',\n", + " 'AtomBondCounts': '7,7',\n", + " 'ElementGraph': 'CC1CCCCC1',\n", + " 'CanonicalSmiles': 'Cc1ccccc1',\n", + " 'SmallWorldIndexBRL': 'B7R1L5',\n", + " 'HetAtomTautomer': 'C[C]1[CH][CH][CH][CH][CH]1_0_0',\n", + " 'NetCharge': '0'},\n", + " 'fingerprints': {},\n", + " 'value_data': {}}" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "scheme.remove_field('AnonymousGraph')\n", + "scheme.set_index('MolFormula')\n", + "scheme.generate_mol_doc(rdmol)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Because `MolDocScheme` objects contain no functions—only references to functions—they can be pickled. In fact, the methods in `write` can save `MolDocSchemes` so that custom schemes are retrievable for later use." ] }, { @@ -86,47 +213,289 @@ "metadata": {}, "source": [ "## Writing to a Database\n", - "`Database.write` provides write functionality. Its core method is `writeFromSDF`, which relies on rdkit's `ForwardSDMolSupplier` to write data from an SDF file into a specified database.\n", + "`Database.write` provides write functionality. Its core method is `WriteFromSDF`, which relies on rdkit's `ForwardSDMolSupplier` to write data from an SDF file into a specified database.\n", "\n", - "For each molecule in the SDF, `writeFromSDF` inserts a document containing at the minimum a unique identifying index, that molecule's SMILES, a pickle of the molecule's rdmol, and a field that specifies the registration option used to store the molecule." + "For each molecule in the SDF, `WriteFromSDF` inserts a document whose fields are specified by the `MolDocScheme` object passed into the function (one with default settings is created if the `scheme` argument is left blank)." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 28, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "populating mongodb collection with compounds from SDF...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:51] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:03:51] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [22:05:23] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "200 molecules successfully imported\n", + "0 duplicates skipped\n" + ] + }, + { + "data": { + "text/plain": [ + "200" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "# Write the contents of first_200_props.sdf, a test dataset, into the TestDatabase created above. \n", + "# Write the contents of first_200_props.sdf, a test dataset, into the collection demo_db.molecules.\n", "# The index will default to the molecule's inchikey.\n", "# Return the number of molecules succesfully imported.\n", - "write.writeFromSDF(TestDB, '../../data/test_data/first_200.props.sdf', 'test')" + "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The above call is the most basic version of `writeFromSDF`. For additional flexibility, `writeFromSDF` takes several optional arguments that allow users to specify how inbound molecules should be standardized, a field relating to the data's origin, customize the index, and change how many molecules are inserted into the database at a time. " + "The above call is the most basic version of `writeFromSDF`. For additional flexibility, `writeFromSDF` takes several optional arguments—users can specify a custom scheme object, a registration collection to write scheme objects to, how many molecules are inserted at a time (this can affect performance), and limit the number of molecules written in." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 30, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "populating mongodb collection with compounds from SDF...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "100 molecules successfully imported\n", + "0 duplicates skipped\n" + ] + }, + { + "data": { + "text/plain": [ + "100" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "# Write the contents of first_200_props.sdf, a test dataset, into the TestDatabase created above. \n", + "# Write the first 100 molecules of first_200_props.sdf, a test dataset, into demo_db.molecules\n", "# This write will use canonical SMILES as the identifying index and thus does not conflict with the above write. \n", "# If we had used inchikey again, the write would have imported 0 molecules.\n", - "write.writeFromSDF(TestDB, '../../data/test_data/first_200.props.sdf', 'test', reg_option='standard_setting', index_option='canonical_smiles', chunk_size=100, limit=None)" + "scheme = registration.MolDocScheme()\n", + "scheme.set_index('CanonicalSmiles')\n", + "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf', scheme, reg_collection=demo_db.schema, chunk_size=50, limit=100)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "In order to maintain consistency, the registration options and index options are drawn from a set of predetermined options specified in `Database.utils`." + "In the case that users aren't working with an SDF, `.write` also provides `WriteFromMolList`, which will take a Python list of rdmol objects in place of the SDF argument in `WriteFromSDF`." ] }, { @@ -135,44 +504,121 @@ "source": [ "## `.create` Module Contents\n", "\n", - "mongordkit.Database.create.**createFromHostPort**(database, host=None (*string*), port=None (*string*))\n", + "mongordkit.Database.create.**createFromHostPort**(database_name, host=None (*string*), port=None (*string*)) --> *a MongoDB database instance named database_name*\n", "\n", - "mongordkit.Database.create.**createFromURL**(database, url=None (*string*))" + "mongordkit.Database.create.**createFromURL**(database_name, url=None (*string*)) --> *a MongoDB database instance named database_name*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## `.write` Module Contents" + "## `.registration` Module Contents" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'MoleculeHashString': ,\n", + " 'inchi_standard': ,\n", + " 'inchikey_standard': ,\n", + " 'inchi_KET_15T': (rdmol)>,\n", + " 'inchikey_KET_15T': (rdmol)>,\n", + " 'noiso_smiles': (rdmol)>,\n", + " 'cx_smiles': }" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "registration.HASH_FUNCTIONS" + ] + }, + { + "cell_type": "code", + "execution_count": 32, "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'AnonymousGraph': rdkit.Chem.rdMolHash.HashFunction.AnonymousGraph,\n", + " 'ElementGraph': rdkit.Chem.rdMolHash.HashFunction.ElementGraph,\n", + " 'CanonicalSmiles': rdkit.Chem.rdMolHash.HashFunction.CanonicalSmiles,\n", + " 'MurckoScaffold': rdkit.Chem.rdMolHash.HashFunction.MurckoScaffold,\n", + " 'ExtendedMurcko': rdkit.Chem.rdMolHash.HashFunction.ExtendedMurcko,\n", + " 'MolFormula': rdkit.Chem.rdMolHash.HashFunction.MolFormula,\n", + " 'AtomBondCounts': rdkit.Chem.rdMolHash.HashFunction.AtomBondCounts,\n", + " 'DegreeVector': rdkit.Chem.rdMolHash.HashFunction.DegreeVector,\n", + " 'Mesomer': rdkit.Chem.rdMolHash.HashFunction.Mesomer,\n", + " 'HetAtomTautomer': rdkit.Chem.rdMolHash.HashFunction.HetAtomTautomer,\n", + " 'HetAtomProtomer': rdkit.Chem.rdMolHash.HashFunction.HetAtomProtomer,\n", + " 'RedoxPair': rdkit.Chem.rdMolHash.HashFunction.RedoxPair,\n", + " 'Regioisomer': rdkit.Chem.rdMolHash.HashFunction.Regioisomer,\n", + " 'NetCharge': rdkit.Chem.rdMolHash.HashFunction.NetCharge,\n", + " 'SmallWorldIndexBR': rdkit.Chem.rdMolHash.HashFunction.SmallWorldIndexBR,\n", + " 'SmallWorldIndexBRL': rdkit.Chem.rdMolHash.HashFunction.SmallWorldIndexBRL,\n", + " 'ArthorSubstructureOrder': rdkit.Chem.rdMolHash.HashFunction.ArthorSubstructureOrder}" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "mongordkit.Database.write.**writeFromSDF**(database, source_sdf, source_name *(string)*, reg_option=\"standard_setting\", index_option=\"inchikey\", chunk_size=100, limit=None)" + "registration.RDKIT_HASH_FUNCTIONS" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "As of 7/15/20, `writeFromSDF` supports the following registration options: \n", - "* 'standard_setting'\n", + "**Class** mongordkit.Database.registration.**MolDocScheme()**\n", "\n", - "And the following index options: \n", - "* 'inchikey'\n", - "* 'canonical_smiles'\n", - "* 'het_atom_tautomer'" + "**Instance variables**:\n", + "```\n", + "self.scheme_name = DEFAULT_SCHEME_NAME\n", + "self.author = DEFAULT_AUTHOR\n", + "self.pre_processed = DEFAULT_PREPROCESS\n", + "self.index_option = DEFAULT_INDEX\n", + "self.rdkit_hashes = set(RDKIT_HASH_FUNCTIONS.keys())\n", + "self.hashes = set(HASH_FUNCTIONS.keys())\n", + "self.fingerprints = {}\n", + "self.value_fields = {}\n", + "```\n", + "**Instance methods**:\n", + "- set_index(self, new_index) --> *None*\n", + "- get_index_value(self, rdmol) --> *calculated index value*\n", + "- add_hash_field(self, field_name, field_method) --> *None*\n", + "- add_value_field(self, field_name, field_value) --> *None*\n", + "- remove_field(self, field_name) --> *None*\n", + "- generate_mol_doc(self, rdmol) --> *Dict: document representing molecule according to scheme*" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "## `.write` Module Contents" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "mongordkit.Database.write.**WriteFromSDF**(database, sdf, scheme=MolDocScheme(), reg_collection=None, chunk_size=100, limit=None) --> *int: number of molecules imported*\n", + "\n", + "mongordkit.Database.write.**WriteFromMolList**(database, list, scheme=MolDocScheme(), reg_collection=None, chunk_size=100, limit=None) --> *int: number of molecules imported*" + ] } ], "metadata": { diff --git a/docs/notebooks/Creating and Writing to MongoDB.ipynb b/docs/notebooks/Creating and Writing to MongoDB.ipynb index 91e557e..cdd4ad1 100644 --- a/docs/notebooks/Creating and Writing to MongoDB.ipynb +++ b/docs/notebooks/Creating and Writing to MongoDB.ipynb @@ -6,7 +6,7 @@ "source": [ "# Creating and Writing to MongoDB\n", "\n", - "Last updated: 7/12/20\n", + "Last updated: 8/10/20\n", "\n", "Methods that directly modify MongoDB database instances are included in the `mongordkit.Database` module.\n", "\n", @@ -16,11 +16,12 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ - "from mongordkit.Database import create, write, utils\n", + "from mongordkit.Database import create, write, utils, registration\n", + "from rdkit import Chem\n", "import pymongo" ] }, @@ -29,26 +30,25 @@ "metadata": {}, "source": [ "## Reset Cells\n", - "Run the contents of this cell to reset the local MongoDB database used in this notebook." + "Run the contents of this cell to reset the local MongoDB database, `demo_db`, used in this notebook." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "client = pymongo.MongoClient()\n", - "print(client.list_database_names())\n", - "client.drop_database('TestDatabase')\n", - "print(client.list_database_names())" + "client.drop_database('demo_db')\n", + "demo_db = client.demo_db" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Creating Databases\n", + "## Creating Databases (DEPRECATED for now)\n", "Users can opt to bring their own database instances, but `Database.create` provides methods that will create ready-made MongoDB instances, defaulting to your local MongoDB:" ] }, @@ -58,11 +58,11 @@ "metadata": {}, "outputs": [], "source": [ - "# Return a database using a host port, such as the local port:\n", - "TestDB = create.createFromHostPort('TestDatabase', host='localhost', port=27017)\n", + "# # Return a database using a host port, such as the local port:\n", + "# db = create.createFromHostPort('demo_db', host='localhost', port=27017)\n", "\n", - "# Return a database using a MongoDB URI, such as that provided by Atlas:\n", - "TestDB = create.createFromURL('TestDatabase', url=None)" + "# # Return a database using a MongoDB URI, such as that provided by Atlas:\n", + "# TestDB = create.createFromURL('demo_db', url=None)" ] }, { @@ -78,7 +78,134 @@ "metadata": {}, "outputs": [], "source": [ - "print(utils.STANDARD_SETTING)" + "# print(utils.STANDARD_SETTING)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Data Registration\n", + "`Database.registration` constructs document representations of molecules according to configurable schemes and handles data registration settings.\n", + "\n", + "It does this in two parts. First, it defines the global variables `RDKIT_HASH_FUNCTIONS` and `HASH_FUNCTIONS` as dictionaries that hold map hash function names to methods. It also defines the global variables `DEFAULT_SCHEME_NAME`, `DEFAULT_AUTHOR`, `DEFAULT_PREPROCESS`, and `DEFAULT_INDEX`, which are used in scheme creation and are thus defined for easy configuration. \n", + "\n", + "Second, the file defines the `MolDocScheme` object, which stores scheme information in its instance variables and is passed into `.write` methods in order to specify molecule document format. By default, `MolDocScheme` includes scheme name, author, whether or not the molecule has been pre-processed, an index option, hashes, fingerprints, and value fields. All of the information contained in a `MolDocScheme` object can be used directly to generate documents for molecules:" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'rdmol': Binary(b'\\xef\\xbe\\xad\\xde\\x00\\x00\\x00\\x00\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x80\\x01\\x06\\x00`\\x00\\x00\\x00\\x01\\x03\\x06@(\\x00\\x00\\x00\\x03\\x04\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x0b\\x00\\x01\\x00\\x01\\x02h\\x0c\\x02\\x03h\\x0c\\x03\\x04h\\x0c\\x04\\x05h\\x0c\\x05\\x06h\\x0c\\x06\\x01h\\x0c\\x14\\x01\\x06\\x01\\x06\\x05\\x04\\x03\\x02\\x17\\x00\\x00\\x00\\x00\\x16', 0),\n", + " 'index': 'YXFVVABEGXRONW-UHFFFAOYSA-N',\n", + " 'smiles': 'Cc1ccccc1',\n", + " 'scheme': 'default',\n", + " 'hashes': {'inchi_standard': 'InChI=1S/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", + " 'inchikey_KET_15T': 'YXFVVABEGXRONW-UHFFFAOYNA-N',\n", + " 'noiso_smiles': 'Cc1ccccc1',\n", + " 'MoleculeHashString': '100-7-7-SaZjmQ-zcSDYw-aXeP/g-122pug-haQS5A-qxXe4Q',\n", + " 'inchi_KET_15T': 'InChI=1/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", + " 'inchikey_standard': 'YXFVVABEGXRONW-UHFFFAOYSA-N',\n", + " 'cx_smiles': 'Cc1ccccc1'},\n", + " 'rdkit_hashes': {'Mesomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", + " 'HetAtomProtomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", + " 'Regioisomer': '*C.c1ccccc1',\n", + " 'MurckoScaffold': 'c1ccccc1',\n", + " 'ArthorSubstructureOrder': '00070007010007000000002a000000',\n", + " 'ExtendedMurcko': '*c1ccccc1',\n", + " 'DegreeVector': '0,1,5,1',\n", + " 'RedoxPair': 'C[C]1[CH][CH][CH][CH][CH]1',\n", + " 'SmallWorldIndexBR': 'B7R1',\n", + " 'MolFormula': 'C7H8',\n", + " 'AtomBondCounts': '7,7',\n", + " 'ElementGraph': 'CC1CCCCC1',\n", + " 'CanonicalSmiles': 'Cc1ccccc1',\n", + " 'SmallWorldIndexBRL': 'B7R1L5',\n", + " 'HetAtomTautomer': 'C[C]1[CH][CH][CH][CH][CH]1_0_0',\n", + " 'NetCharge': '0',\n", + " 'AnonymousGraph': '**1*****1'},\n", + " 'fingerprints': {},\n", + " 'value_data': {}}" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "rdmol = Chem.MolFromSmiles('Cc1ccccc1')\n", + "scheme = registration.MolDocScheme()\n", + "scheme.generate_mol_doc(rdmol)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `MolDocScheme` class also defines a series of instance methods, such as `MolDocScheme.set_index` and `MolDocScheme.remove_field`, that can be used to modify document schemes:" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'rdmol': Binary(b'\\xef\\xbe\\xad\\xde\\x00\\x00\\x00\\x00\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x80\\x01\\x06\\x00`\\x00\\x00\\x00\\x01\\x03\\x06@(\\x00\\x00\\x00\\x03\\x04\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x0b\\x00\\x01\\x00\\x01\\x02h\\x0c\\x02\\x03h\\x0c\\x03\\x04h\\x0c\\x04\\x05h\\x0c\\x05\\x06h\\x0c\\x06\\x01h\\x0c\\x14\\x01\\x06\\x01\\x06\\x05\\x04\\x03\\x02\\x17\\x00\\x00\\x00\\x00\\x16', 0),\n", + " 'index': 'C7H8',\n", + " 'smiles': 'Cc1ccccc1',\n", + " 'scheme': 'default',\n", + " 'hashes': {'inchi_standard': 'InChI=1S/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", + " 'inchikey_KET_15T': 'YXFVVABEGXRONW-UHFFFAOYNA-N',\n", + " 'noiso_smiles': 'Cc1ccccc1',\n", + " 'MoleculeHashString': '100-7-7-SaZjmQ-zcSDYw-aXeP/g-122pug-haQS5A-qxXe4Q',\n", + " 'inchi_KET_15T': 'InChI=1/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", + " 'inchikey_standard': 'YXFVVABEGXRONW-UHFFFAOYSA-N',\n", + " 'cx_smiles': 'Cc1ccccc1'},\n", + " 'rdkit_hashes': {'Mesomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", + " 'HetAtomProtomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", + " 'Regioisomer': '*C.c1ccccc1',\n", + " 'MurckoScaffold': 'c1ccccc1',\n", + " 'ArthorSubstructureOrder': '00070007010007000000002a000000',\n", + " 'ExtendedMurcko': '*c1ccccc1',\n", + " 'DegreeVector': '0,1,5,1',\n", + " 'RedoxPair': 'C[C]1[CH][CH][CH][CH][CH]1',\n", + " 'SmallWorldIndexBR': 'B7R1',\n", + " 'MolFormula': 'C7H8',\n", + " 'AtomBondCounts': '7,7',\n", + " 'ElementGraph': 'CC1CCCCC1',\n", + " 'CanonicalSmiles': 'Cc1ccccc1',\n", + " 'SmallWorldIndexBRL': 'B7R1L5',\n", + " 'HetAtomTautomer': 'C[C]1[CH][CH][CH][CH][CH]1_0_0',\n", + " 'NetCharge': '0'},\n", + " 'fingerprints': {},\n", + " 'value_data': {}}" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "scheme.remove_field('AnonymousGraph')\n", + "scheme.set_index('MolFormula')\n", + "scheme.generate_mol_doc(rdmol)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Because `MolDocScheme` objects contain no functions—only references to functions—they can be pickled. In fact, the methods in `write` can save `MolDocSchemes` so that custom schemes are retrievable for later use." ] }, { @@ -86,47 +213,289 @@ "metadata": {}, "source": [ "## Writing to a Database\n", - "`Database.write` provides write functionality. Its core method is `writeFromSDF`, which relies on rdkit's `ForwardSDMolSupplier` to write data from an SDF file into a specified database.\n", + "`Database.write` provides write functionality. Its core method is `WriteFromSDF`, which relies on rdkit's `ForwardSDMolSupplier` to write data from an SDF file into a specified database.\n", "\n", - "For each molecule in the SDF, `writeFromSDF` inserts a document containing at the minimum a unique identifying index, that molecule's SMILES, a pickle of the molecule's rdmol, and a field that specifies the registration option used to store the molecule." + "For each molecule in the SDF, `WriteFromSDF` inserts a document whose fields are specified by the `MolDocScheme` object passed into the function (one with default settings is created if the `scheme` argument is left blank)." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 28, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "populating mongodb collection with compounds from SDF...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:51] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:03:51] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:23] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [22:05:23] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "200 molecules successfully imported\n", + "0 duplicates skipped\n" + ] + }, + { + "data": { + "text/plain": [ + "200" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "# Write the contents of first_200_props.sdf, a test dataset, into the TestDatabase created above. \n", + "# Write the contents of first_200_props.sdf, a test dataset, into the collection demo_db.molecules.\n", "# The index will default to the molecule's inchikey.\n", "# Return the number of molecules succesfully imported.\n", - "write.writeFromSDF(TestDB, '../../data/test_data/first_200.props.sdf', 'test')" + "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The above call is the most basic version of `writeFromSDF`. For additional flexibility, `writeFromSDF` takes several optional arguments that allow users to specify how inbound molecules should be standardized, a field relating to the data's origin, customize the index, and change how many molecules are inserted into the database at a time. " + "The above call is the most basic version of `writeFromSDF`. For additional flexibility, `writeFromSDF` takes several optional arguments—users can specify a custom scheme object, a registration collection to write scheme objects to, how many molecules are inserted at a time (this can affect performance), and limit the number of molecules written in." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 30, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "populating mongodb collection with compounds from SDF...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "100 molecules successfully imported\n", + "0 duplicates skipped\n" + ] + }, + { + "data": { + "text/plain": [ + "100" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "# Write the contents of first_200_props.sdf, a test dataset, into the TestDatabase created above. \n", + "# Write the first 100 molecules of first_200_props.sdf, a test dataset, into demo_db.molecules\n", "# This write will use canonical SMILES as the identifying index and thus does not conflict with the above write. \n", "# If we had used inchikey again, the write would have imported 0 molecules.\n", - "write.writeFromSDF(TestDB, '../../data/test_data/first_200.props.sdf', 'test', reg_option='standard_setting', index_option='canonical_smiles', chunk_size=100, limit=None)" + "scheme = registration.MolDocScheme()\n", + "scheme.set_index('CanonicalSmiles')\n", + "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf', scheme, reg_collection=demo_db.schema, chunk_size=50, limit=100)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "In order to maintain consistency, the registration options and index options are drawn from a set of predetermined options specified in `Database.utils`." + "In the case that users aren't working with an SDF, `.write` also provides `WriteFromMolList`, which will take a Python list of rdmol objects in place of the SDF argument in `WriteFromSDF`." ] }, { @@ -144,27 +513,111 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## `.write` Module Contents" + "## `.registration` Module Contents" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'MoleculeHashString': ,\n", + " 'inchi_standard': ,\n", + " 'inchikey_standard': ,\n", + " 'inchi_KET_15T': (rdmol)>,\n", + " 'inchikey_KET_15T': (rdmol)>,\n", + " 'noiso_smiles': (rdmol)>,\n", + " 'cx_smiles': }" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "registration.HASH_FUNCTIONS" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'AnonymousGraph': rdkit.Chem.rdMolHash.HashFunction.AnonymousGraph,\n", + " 'ElementGraph': rdkit.Chem.rdMolHash.HashFunction.ElementGraph,\n", + " 'CanonicalSmiles': rdkit.Chem.rdMolHash.HashFunction.CanonicalSmiles,\n", + " 'MurckoScaffold': rdkit.Chem.rdMolHash.HashFunction.MurckoScaffold,\n", + " 'ExtendedMurcko': rdkit.Chem.rdMolHash.HashFunction.ExtendedMurcko,\n", + " 'MolFormula': rdkit.Chem.rdMolHash.HashFunction.MolFormula,\n", + " 'AtomBondCounts': rdkit.Chem.rdMolHash.HashFunction.AtomBondCounts,\n", + " 'DegreeVector': rdkit.Chem.rdMolHash.HashFunction.DegreeVector,\n", + " 'Mesomer': rdkit.Chem.rdMolHash.HashFunction.Mesomer,\n", + " 'HetAtomTautomer': rdkit.Chem.rdMolHash.HashFunction.HetAtomTautomer,\n", + " 'HetAtomProtomer': rdkit.Chem.rdMolHash.HashFunction.HetAtomProtomer,\n", + " 'RedoxPair': rdkit.Chem.rdMolHash.HashFunction.RedoxPair,\n", + " 'Regioisomer': rdkit.Chem.rdMolHash.HashFunction.Regioisomer,\n", + " 'NetCharge': rdkit.Chem.rdMolHash.HashFunction.NetCharge,\n", + " 'SmallWorldIndexBR': rdkit.Chem.rdMolHash.HashFunction.SmallWorldIndexBR,\n", + " 'SmallWorldIndexBRL': rdkit.Chem.rdMolHash.HashFunction.SmallWorldIndexBRL,\n", + " 'ArthorSubstructureOrder': rdkit.Chem.rdMolHash.HashFunction.ArthorSubstructureOrder}" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "registration.RDKIT_HASH_FUNCTIONS" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Class** mongordkit.Database.registration.**MolDocScheme()**\n", + "\n", + "**Instance variables**:\n", + "```\n", + "self.scheme_name = DEFAULT_SCHEME_NAME\n", + "self.author = DEFAULT_AUTHOR\n", + "self.pre_processed = DEFAULT_PREPROCESS\n", + "self.index_option = DEFAULT_INDEX\n", + "self.rdkit_hashes = set(RDKIT_HASH_FUNCTIONS.keys())\n", + "self.hashes = set(HASH_FUNCTIONS.keys())\n", + "self.fingerprints = {}\n", + "self.value_fields = {}\n", + "```\n", + "**Instance methods**:\n", + "- set_index(self, new_index) --> *None*\n", + "- get_index_value(self, rdmol) --> *calculated index value*\n", + "- add_hash_field(self, field_name, field_method) --> *None*\n", + "- add_value_field(self, field_name, field_value) --> *None*\n", + "- remove_field(self, field_name) --> *None*\n", + "- generate_mol_doc(self, rdmol) --> *Dict: document representing molecule according to scheme*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "mongordkit.Database.write.**writeFromSDF**(database, source_sdf, source_name *(string)*, reg_option=\"standard_setting\", index_option=\"inchikey\", chunk_size=100, limit=None) --> *int: number of molecules imported*" + "## `.write` Module Contents" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "As of 7/15/20, `writeFromSDF` supports the following registration options: \n", - "* 'standard_setting'\n", + "mongordkit.Database.write.**WriteFromSDF**(database, sdf, scheme=MolDocScheme(), reg_collection=None, chunk_size=100, limit=None) --> *int: number of molecules imported*\n", "\n", - "And the following index options: \n", - "* 'inchikey'\n", - "* 'canonical_smiles'\n", - "* 'het_atom_tautomer'" + "mongordkit.Database.write.**WriteFromMolList**(database, list, scheme=MolDocScheme(), reg_collection=None, chunk_size=100, limit=None) --> *int: number of molecules imported*" ] } ], diff --git a/mongordkit/Database/registration.py b/mongordkit/Database/registration.py new file mode 100644 index 0000000..876321d --- /dev/null +++ b/mongordkit/Database/registration.py @@ -0,0 +1,93 @@ +""" +Constructs document representations of molecules and +handles data registration settings. +""" +import rdkit +from bson import Binary +from rdkit import Chem +from rdkit.Chem import rdMolHash +import pickle + + +DEFAULT_SCHEME_NAME = 'default' +DEFAULT_AUTHOR = 'package-native' +DEFAULT_PREPROCESS = False +DEFAULT_INDEX = 'inchikey_standard' + + +RDKIT_HASH_FUNCTIONS = rdkit.Chem.rdMolHash.HashFunction.names +HASH_FUNCTIONS = {} +HASH_FUNCTIONS['MoleculeHashString'] = rdMolHash.GenerateMoleculeHashString +HASH_FUNCTIONS['inchi_standard'] = Chem.MolToInchi +HASH_FUNCTIONS['inchikey_standard'] = Chem.MolToInchiKey +HASH_FUNCTIONS['inchi_KET_15T'] = lambda rdmol: Chem.MolToInchi(rdmol, options='-KET -15T') +HASH_FUNCTIONS['inchikey_KET_15T'] = lambda rdmol: Chem.MolToInchiKey(rdmol, options='-KET -15T') +HASH_FUNCTIONS['noiso_smiles'] = lambda rdmol: Chem.MolToSmiles(rdmol, isomericSmiles=False) +HASH_FUNCTIONS['cx_smiles'] = Chem.MolToCXSmiles + + +class MolDocScheme(): + + def __init__(self): + self.scheme_name = DEFAULT_SCHEME_NAME + self.author = DEFAULT_AUTHOR + self.pre_processed = DEFAULT_PREPROCESS + self.index_option = DEFAULT_INDEX + self.rdkit_hashes = set(RDKIT_HASH_FUNCTIONS.keys()) + self.hashes = set(HASH_FUNCTIONS.keys()) + self.fingerprints = {} + self.value_fields = {} + + def __repr__(self): + return 'Molecule document representation schema. ' \ + '{Name: ' + str(self.scheme_name) + \ + ', author: ' + str(self.author) + \ + ', index' + str(self.index_option) + \ + '}' + + def set_index(self, new_index): + if new_index not in HASH_FUNCTIONS.keys() and new_index not in RDKIT_HASH_FUNCTIONS.keys(): + raise Exception("Please add this hash first.") + else: + self.index_option = new_index + + def get_index_value(self, rdmol): + if self.index_option in HASH_FUNCTIONS.keys(): + return HASH_FUNCTIONS[self.index_option](rdmol) + elif self.index_option in RDKIT_HASH_FUNCTIONS.keys(): + return rdMolHash.MolHash(rdmol, RDKIT_HASH_FUNCTIONS[self.index_option]) + else: + raise Exception("Specified index option does not exist.") + + def add_hash_field(self, field_name, field_method): + self.hashes.add(field_name) + HASH_FUNCTIONS[field_name] = field_method + + def add_value_field(self, field_name, field_value): + self.value_fields[field_name] = field_value + + def remove_field(self, field_name): + if field_name in self.hashes: + self.hashes.remove(field_name) + print(f'removed {field_name} from scheme') + if field_name in self.value_fields.keys(): + self.value_fields.pop(field_name) + print(f'removed {field_name} from scheme') + if field_name in self.rdkit_hashes: + self.rdkit_hashes.remove(field_name) + print(f'removed {field_name} from scheme') + + def generate_mol_doc(self, rdmol): + molDoc = { + 'rdmol': Binary(rdmol.ToBinary()), + 'index': self.get_index_value(rdmol), + 'smiles': Chem.MolToSmiles(rdmol), + 'scheme': self.scheme_name, + 'hashes': {hash_name: HASH_FUNCTIONS[hash_name](rdmol) for hash_name in self.hashes}, + 'rdkit_hashes': {hash_name: rdMolHash.MolHash(rdmol, RDKIT_HASH_FUNCTIONS[hash_name]) + for hash_name in self.rdkit_hashes}, + 'fingerprints': {fp: fp_method(rdmol) for fp, fp_method in self.fingerprints.items()}, + 'value_data': {field_name: value for field_name, value in self.value_fields.items()} + } + return molDoc + diff --git a/mongordkit/Database/tests/test_write.py b/mongordkit/Database/tests/test_write.py index 2ef0818..1acbe63 100644 --- a/mongordkit/Database/tests/test_write.py +++ b/mongordkit/Database/tests/test_write.py @@ -8,41 +8,49 @@ sys.path.append(Path('.').resolve().parent.parent) from mongordkit.Database import write +from mongordkit.Database import registration def setupDB(): client = mongomock.MongoClient() return client.db -def test_writeCount(): - db = setupDB() - assert 200 == write.writeFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', 'test') +class TestWrite: -def test_invalidIndex(): - with pytest.raises(ValueError): + def test_writeCount(self): + data_scheme = registration.MolDocScheme() db = setupDB() - write.writeFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', 'test', reg_option='standard_setting', index_option='canonica_smiles') - -def test_hashes(): - db = setupDB() - assert 200 == write.writeFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', 'test', 'standard_setting', 'canonical_smiles') - db = setupDB() - assert 200 == write.writeFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', 'test', 'standard_setting', 'het_atom_tautomer') - -def test_uniqueInsertion(): - db = setupDB() - write.writeFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', 'test') - assert 0 == write.writeFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', 'test') - assert 200 == write.writeFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', 'test', reg_option='standard_setting', index_option='canonical_smiles') - -def test_writeLimit(): - db = setupDB() - assert 100 == write.writeFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', 'test', limit=100) - -def test_WriteMolListCount(): - db = setupDB() - f = open('data/zinc.frags.500.q.smi') - frags = [Chem.MolFromSmiles(line.split()[0]) for line in f] - f.close() - frag_smiles = [Chem.MolToSmiles(rdmol) for rdmol in frags] - write.WriteMolList(db.molecules, frags, 'test', chunk_size=100) - assert 499 == db.molecules.count_documents({}) + assert 200 == write.WriteFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', data_scheme) + + def test_invalidIndex(self): + db = setupDB() + data_scheme = registration.MolDocScheme() + with pytest.raises(Exception): + data_scheme.set_index('moo') + + def test_hashes(self): + db = setupDB() + data_scheme = registration.MolDocScheme() + data_scheme.set_index("CanonicalSmiles") + assert 200 == write.WriteFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', data_scheme) + data_scheme.set_index("MoleculeHashString") + assert 200 == write.WriteFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', data_scheme) + + def test_uniqueInsertion(self): + db = setupDB() + data_scheme = registration.MolDocScheme() + assert 200 == write.WriteFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', data_scheme) + assert 0 == write.WriteFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', data_scheme) + + def test_writeLimit(self): + db = setupDB() + data_scheme = registration.MolDocScheme() + assert 10 == write.WriteFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', data_scheme, limit=10) + + def test_WriteMolListCount(self): + db = setupDB() + data_scheme = registration.MolDocScheme() + f = open('data/zinc.frags.500.q.smi') + frags = [Chem.MolFromSmiles(line.split()[0]) for line in f] + f.close() + write.WriteFromMolList(db.molecules, frags, data_scheme) + assert 499 == db.molecules.count_documents({}) \ No newline at end of file diff --git a/mongordkit/Database/utils.py b/mongordkit/Database/utils.py index 38126b9..66ec0d4 100644 --- a/mongordkit/Database/utils.py +++ b/mongordkit/Database/utils.py @@ -20,7 +20,7 @@ def canonicalHash(m): 'fragments': 'removed', } -VALID_IDS = {'inchikey', 'canonical_smiles', 'het_atom_tautomer'} +VALID_HASHES = {'inchikey', 'canonical_smiles', 'het_atom_tautomer'} HASH_FUNCTIONS = {'inchikey': rdinchi.MolToInchiKey, 'canonical_smiles': canonicalHash, diff --git a/mongordkit/Database/write.py b/mongordkit/Database/write.py index d0e813b..02dad52 100644 --- a/mongordkit/Database/write.py +++ b/mongordkit/Database/write.py @@ -1,57 +1,50 @@ -import pymongo +import pymongo, pickle from bson import Binary from rdkit import Chem from rdkit.Chem import rdMolHash from rdkit.Chem import rdinchi -from .utils import * +from .registration import MolDocScheme, HASH_FUNCTIONS, RDKIT_HASH_FUNCTIONS -def writeFromSDF(mol_collection, sdf, src, - reg_collection=None, reg_option="standard_setting", index_option="inchikey", - chunk_size=100, limit=None): +def WriteFromSDF(mol_collection, sdf, scheme=MolDocScheme(), + reg_collection=None, chunk_size=100, limit=None): """ - Writes to MOL_COLLECTION the - contents of an SDF file SDF from SRC in a collection called molecules. - To limit the number of calls to the database, - chunks the molecules into groups of CHUNK_SIZE, - which defaults to 100. Returns the number of molecules - inserted into the collection during its call. + Writes the contents of SDF to MOL_COLLECTION and creates + an index on the index specificed in SCHEME. Optional parameters: + - customize document structure by specifying a SCHEME MolDocScheme object. + - write the scheme object into a separate collection by specifying REG_COLLECTION. + - customize how many molecules are inserted at a time by setting CHUNK_SIZE. + - limit the number of molecules written in by setting LIMIT. :param mol_collection: A MongoDB collection. :param sdf: A Python File object of the desired SDF file. - :param src: For the user's utility, a string that indicates where the file originates. - :param reg_option: Allows control over the inserted document structure. Defaults to a standard - setting that includes an index, SMILES, an rdkit Molecule, and a registration setting. - :param index_option: Allows control over indexing settings. Defaults to generating an Inchikey for - each molecule. - :param chunk_size: How many documents are inserted into the database instance at a time. - :return: The total number of molecules inserted into the collection. + :param scheme: A registration.MolDocScheme() object. + :param reg_collection: A MongoDB collection. + :param chunk_size: Integer indicating how many molecules inserted at a time. + :param limit: Integer indicating how many molecules to insert. """ molecules = mol_collection - print('populating mongodb collection with compounds from chembl...') + print('populating mongodb collection with compounds from SDF...') # This is placeholder code for when more registration options exist. - if index_option not in VALID_IDS: - options = ', '.join(VALID_IDS) - raise ValueError("id_option must be one of {}".format(options)) - else: - hash = HASH_FUNCTIONS[index_option] + # if index_option not in VALID_HASHES: + # options = ', '.join(VALID_HASHES) + # raise ValueError("index_option must be one of {}".format(options)) + # else: + # hash = HASH_FUNCTIONS[index_option] chunk = [] inserted = 0 + duplicates = 0 + if reg_collection: + reg_collection.insert_one({scheme.scheme_name: pickle.dumps(scheme)}) for rdmol in Chem.ForwardSDMolSupplier(sdf): if limit is not None and inserted >= limit: break if rdmol is None: continue - index = hash(rdmol) + index = scheme.get_index_value(rdmol) if mol_collection.count_documents({"index": index}) != 0: + duplicates += 1 continue - # Placeholder for where molecule standardization might take place. - document = { - 'index': hash(rdmol), - 'smiles': Chem.MolToSmiles(rdmol), - 'rdmol': Binary(rdmol.ToBinary()), - 'registration_setting': reg_option - } - # Placeholder for adding setting specific fields to the document. + document = scheme.generate_mol_doc(rdmol) chunk.append(document) inserted += 1 if len(chunk) == chunk_size: @@ -65,50 +58,50 @@ def writeFromSDF(mol_collection, sdf, src, molecules.insert_one(i) inserted += 1 print("{} molecules successfully imported".format(inserted)) + print("{} duplicates skipped".format(duplicates)) + mol_collection.create_index('index') return inserted -def WriteMolList(mol_collection, list, src, - reg_collection=None, reg_option="standard_setting", index_option="inchikey", - chunk_size=100, limit=None): +def WriteFromMolList(mol_collection, list, scheme=MolDocScheme(), + reg_collection=None, chunk_size=100, limit=None): """ - Writes to database instance DB a list of rdmols in the standard format into a molecules collection. + Writes the contents of LIST to MOL_COLLECTION and creates + an index on the index specificed in SCHEME. Optional parameters: + - customize document structure by specifying a SCHEME MolDocScheme object. + - write the scheme object into a separate collection by specifying REG_COLLECTION. + - customize how many molecules are inserted at a time by setting CHUNK_SIZE. + - limit the number of molecules written in by setting LIMIT. :param mol_collection: A MongoDB collection. - :param sdf: A Python list of rdmol objects. - :param src: For the user's utility, a string that indicates where the file originates. - :param reg_option: Allows control over the inserted document structure. Defaults to a standard - setting that includes an index, SMILES, an rdkit Molecule, and a registration setting. - :param index_option: Allows control over indexing settings. Defaults to generating an Inchikey for - each molecule. - :param chunk_size: How many documents are inserted into the database instance at a time. - :return: The total number of molecules inserted into the collection. + :param list: A Python list of rdmol objects. + :param scheme: A registration.MolDocScheme() object. + :param reg_collection: A MongoDB collection. + :param chunk_size: Integer indicating how many molecules inserted at a time. + :param limit: Integer indicating how many molecules to insert. """ molecules = mol_collection - print('populating mongodb collection with compounds from chembl...') + print('populating mongodb collection with compounds from list...') # This is placeholder code for when more registration options exist. - if index_option not in VALID_IDS: - options = ', '.join(VALID_IDS) - raise ValueError("id_option must be one of {}".format(options)) - else: - hash = HASH_FUNCTIONS[index_option] + # if index_option not in VALID_HASHES: + # options = ', '.join(VALID_HASHES) + # raise ValueError("index_option must be one of {}".format(options)) + # else: + # hash = HASH_FUNCTIONS[index_option] chunk = [] inserted = 0 + duplicates = 0 + if reg_collection: + reg_collection.insert_one({scheme.scheme_name: pickle.dumps(scheme)}) for rdmol in list: if limit is not None and inserted >= limit: break if rdmol is None: continue - index = hash(rdmol) - if molecules.count_documents({"index": index}) != 0: + index = scheme.get_index_value(rdmol) + if mol_collection.count_documents({"index": index}) != 0: + duplicates += 1 continue - # Placeholder for where molecule standardization might take place. - document = { - 'index': hash(rdmol), - 'smiles': Chem.MolToSmiles(rdmol), - 'rdmol': Binary(rdmol.ToBinary()), - 'registration_setting': reg_option - } - # Placeholder for adding setting specific fields to the document. + document = scheme.generate_mol_doc(rdmol) chunk.append(document) inserted += 1 if len(chunk) == chunk_size: @@ -122,6 +115,8 @@ def WriteMolList(mol_collection, list, src, molecules.insert_one(i) inserted += 1 print("{} molecules successfully imported".format(inserted)) + print("{} duplicates skipped".format(duplicates)) + mol_collection.create_index('index') return inserted diff --git a/mongordkit/Search/tests/test_similarity.py b/mongordkit/Search/tests/test_similarity.py index 5ff1df2..07f5f64 100644 --- a/mongordkit/Search/tests/test_similarity.py +++ b/mongordkit/Search/tests/test_similarity.py @@ -22,7 +22,7 @@ def test_zeroThreshold(): """ db_python = utils.setupPythonDB('data/test_data/first_200.props.sdf') db_mongo = utils.setupMockDB() - write.writeFromSDF(db_mongo.molecules, 'data/test_data/first_200.props.sdf', 'test') + write.WriteFromSDF(db_mongo.molecules, 'data/test_data/first_200.props.sdf') similarity.AddMorganFingerprints(db_mongo.molecules, db_mongo.mfp_counts) mol = Chem.Mol(db_python[0]['rdmol']) @@ -38,7 +38,7 @@ def test_similarityAccuracy(): """ db_python = utils.setupPythonDB('data/test_data/first_200.props.sdf') db_mongo = utils.setupMockDB() - write.writeFromSDF(db_mongo.molecules, 'data/test_data/first_200.props.sdf', 'test') + write.WriteFromSDF(db_mongo.molecules, 'data/test_data/first_200.props.sdf') similarity.AddMorganFingerprints(db_mongo.molecules, db_mongo.mfp_counts) thresholds = [0.2, 0.4, 0.6, 0.8, 1] for t in thresholds: @@ -61,7 +61,7 @@ def test_similarityAccuracyAggregate(mongoURI): db_mongo = utils.setupMongoDB() else: db_mongo = utils.setupMongoDB(mongoURI) - write.writeFromSDF(db_mongo.molecules, 'data/test_data/first_200.props.sdf', 'test') + write.WriteFromSDF(db_mongo.molecules, 'data/test_data/first_200.props.sdf') similarity.AddMorganFingerprints(db_mongo.molecules, db_mongo.mfp_counts) thresholds = [0.2, 0.4, 0.6, 0.8, 1] counter = 0 @@ -82,7 +82,7 @@ def test_similarityProgression(): """ db_python = utils.setupPythonDB('data/test_data/first_200.props.sdf') db_mongo = utils.setupMockDB() - write.writeFromSDF(db_mongo.molecules, 'data/test_data/first_200.props.sdf', 'test') + write.WriteFromSDF(db_mongo.molecules, 'data/test_data/first_200.props.sdf') similarity.AddMorganFingerprints(db_mongo.molecules, db_mongo.mfp_counts) thresholds = [1, 0.8, 0.6, 0.4, 0.2] for i in range(200): @@ -106,7 +106,7 @@ def test_similarityAggregateProgression(mongoURI): db_mongo = utils.setupMongoDB() else: db_mongo = utils.setupMongoDB(mongoURI) - write.writeFromSDF(db_mongo.molecules, 'data/test_data/first_200.props.sdf', 'test') + write.WriteFromSDF(db_mongo.molecules, 'data/test_data/first_200.props.sdf') similarity.AddMorganFingerprints(db_mongo.molecules, db_mongo.mfp_counts) thresholds = [1, 0.8, 0.6, 0.4, 0.2] for i in range(200): @@ -126,7 +126,7 @@ def test_similarity_accuracy_LSH(mongoURI): db_mongo = utils.setupMongoDB() else: db_mongo = utils.setupMongoDB(mongoURI) - write.writeFromSDF(db_mongo.molecules, 'data/test_data/first_200.props.sdf', 'test') + write.WriteFromSDF(db_mongo.molecules, 'data/test_data/first_200.props.sdf') similarity.AddMorganFingerprints(db_mongo.molecules, db_mongo.mfp_counts) similarity.AddRandPermutations(db_mongo.permutations) similarity.AddLocalityHashes(db_mongo.molecules, db_mongo.permutations, 25) diff --git a/mongordkit/Search/tests/test_substructure.py b/mongordkit/Search/tests/test_substructure.py index 38c2f77..2b29a7d 100644 --- a/mongordkit/Search/tests/test_substructure.py +++ b/mongordkit/Search/tests/test_substructure.py @@ -6,7 +6,7 @@ def test_addPatternFingerprints(): db = utils.setupMockDB() - write.writeFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', 'test') + write.WriteFromSDF(db.molecules, 'data/test_data/first_200.props.sdf') substructure.AddPatternFingerprints(db.molecules) counter = 0 assert db.molecules.count_documents({"pattern_fp": {"$exists": True}}) == 200 @@ -14,7 +14,7 @@ def test_addPatternFingerprints(): def test_SubSearchAccuracy(): db_mock = utils.setupMockDB() - write.writeFromSDF(db_mock.molecules, 'data/test_data/first_200.props.sdf', 'test') + write.WriteFromSDF(db_mock.molecules, 'data/test_data/first_200.props.sdf') substructure.AddPatternFingerprints(db_mock.molecules) db_python = utils.setupPythonDB('data/test_data/first_200.props.sdf') for i in range(200): From 7d1b19585a5ea973fa037eb608856d5eadf6997e Mon Sep 17 00:00:00 2001 From: Christopher Zou Date: Wed, 12 Aug 2020 23:09:54 -0400 Subject: [PATCH 2/7] Update documentation and added hashes --- ...ng and Writing to MongoDB-checkpoint.ipynb | 3 +- ...y and Substructure Search-checkpoint.ipynb | 395 ++++++++---- .../Creating and Writing to MongoDB.ipynb | 3 +- .../Similarity and Substructure Search.ipynb | 562 +++++++++++++++--- .../__pycache__/create.cpython-37.pyc | Bin 1389 -> 1389 bytes .../Database/__pycache__/utils.cpython-37.pyc | Bin 933 -> 936 bytes .../Database/__pycache__/write.cpython-37.pyc | Bin 4963 -> 4377 bytes .../test_create.cpython-37-pytest-5.4.3.pyc | Bin 1499 -> 1288 bytes .../test_write.cpython-37-pytest-5.4.3.pyc | Bin 4115 -> 6323 bytes mongordkit/Search/__init__.py | 12 + .../__pycache__/__init__.cpython-37.pyc | Bin 155 -> 684 bytes .../__pycache__/similarity.cpython-37.pyc | Bin 5159 -> 12138 bytes mongordkit/Search/similarity.py | 128 ++-- mongordkit/Search/substructure.py | 16 +- mongordkit/Search/tests/test_similarity.py | 1 + mongordkit/Search/tests/test_substructure.py | 2 +- mongordkit/Search/tests/utils.py | 4 +- 17 files changed, 855 insertions(+), 271 deletions(-) diff --git a/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb b/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb index cdd4ad1..aec730f 100644 --- a/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb +++ b/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb @@ -488,7 +488,8 @@ "# If we had used inchikey again, the write would have imported 0 molecules.\n", "scheme = registration.MolDocScheme()\n", "scheme.set_index('CanonicalSmiles')\n", - "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf', scheme, reg_collection=demo_db.schema, chunk_size=50, limit=100)" + "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf', \n", + " scheme, reg_collection=demo_db.schema, chunk_size=50, limit=100)" ] }, { diff --git a/docs/notebooks/.ipynb_checkpoints/Similarity and Substructure Search-checkpoint.ipynb b/docs/notebooks/.ipynb_checkpoints/Similarity and Substructure Search-checkpoint.ipynb index 9e5d205..34d092f 100644 --- a/docs/notebooks/.ipynb_checkpoints/Similarity and Substructure Search-checkpoint.ipynb +++ b/docs/notebooks/.ipynb_checkpoints/Similarity and Substructure Search-checkpoint.ipynb @@ -6,18 +6,19 @@ "source": [ "# Similarity and Substructure Search\n", "\n", - "Last updated: 7/11/20\n", + "Last updated: 7/27/20\n", "\n", "Methods for similarity and substructure search are included in the `mongordkit.Search` module." ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from mongordkit.Search import similarity, substructure, utils\n", + "from mongordkit import Search\n", "from mongordkit.Database import create, write\n", "from rdkit import Chem\n", "import pymongo" @@ -29,28 +30,164 @@ "source": [ "## Reset Cells\n", "\n", - "Run these cells to reset the local MongoDB instance used in this notebook." + "Run these cells to reset the MongoDB database used in this notebook." ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, + "outputs": [], + "source": [ + "client = pymongo.MongoClient()\n", + "client.drop_database('demo_db')\n", + "demo_db = client.demo_db" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Preparing for Search\n", + "Adequately preparing the database for searching requires adding a variety of fingerprints and hashes. You can easily perform all of the setup work required for similarity and substructure search by calling the method `Search.PrepareForSearch`. Generally, workflow will follow straight from the following two lines into search calls:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "scrolled": true + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "['TestDatabase', 'admin', 'config', 'db', 'local']\n", - "['admin', 'config', 'db', 'local']\n" + "populating mongodb collection with compounds from SDF...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [22:56:20] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "200 molecules successfully imported\n", + "0 duplicates skipped\n", + "Preparing database and collections for search...\n", + "Added pattern fps, morgan fps, and support for LSH.\n" ] } ], "source": [ - "client = pymongo.MongoClient()\n", - "print(client.list_database_names())\n", - "client.drop_database('TestDatabase')\n", - "print(client.list_database_names())" + "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf')\n", + "Search.PrepareForSearch(demo_db, demo_db.molecules, demo_db.mfp_counts, demo_db.permutations)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "However, the rest of this notebook will explicitly note the addition of fingerprints and hashes in an effort to better communicate how the code actually works. Let's reset the database again so that we can insert the hashes step by step without any issues." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "client.drop_database('demo_db')\n", + "demo_db = client.demo_db" ] }, { @@ -59,177 +196,158 @@ "source": [ "## Similarity Search\n", "\n", - "`mongordkit.Search.similarity` supports similarity search best on a database prepared by `mongordkit.Database.write`. Users can also use any database that has a `molecules` collection where each document in that collection has the following fields:\n", + "`mongordkit.Search.similarity` supports similarity search best on a MongoDB collection prepared by `mongordkit.Database.write`. For the general level of similarity search, users can also use any collection that has documents with the following fields:\n", "- `'rdmol': binary pickle object`\n", - "- `'smiles': some SMILES string`" + "- `'index': a unique identifier for each molecule`\n", + "- `'fingerprints': {a nested document that can be blank at the start}'`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Let's run through an example of similarity search. First, we'll have to set up our database:" + "Let's run through an example of similarity search. First, we'll write into the database 200 molecules from a data file included in the `mongordkit` package. We will use default write settings." ] }, { "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "populating mongodb collection with compounds from chembl...\n", - "200 molecules successfully imported\n" - ] - }, - { - "data": { - "text/plain": [ - "200" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], "source": [ - "TestDB = create.createFromHostPort('TestDatabase', host='localhost', port=27017)\n", - "write.writeFromSDF(TestDB, '../../data/test_data/first_200.props.sdf', 'test')" + "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "`similarity.SimSearchNaive` will directly loop through the database and display results. However, this implementation is extremely slow for any decently-sized database. Instead, `similarity` supports precalculating the following kinds of fingerprints for screening: \n", - "- Morgan (length 1048)\n", + "`similarity.SimSearchNaive` will directly loop through the database and display results. This is good for purposes of verifying accuracy. However, this implementation is extremely slow for any decently-sized database. Instead, `similarity` supports precalculating the following kinds of fingerprints for screening: \n", + "- Morgan (default radius 2, length 2048)\n", "\n", - "through `similarity.addMorganFingerprints`. For each document in a passed in database's `molecules` collection, this method creates a nested field that contains `{morgan_fp: {bits: }, {count: }}`. Note that `addMorganFingerprints` also creates indices on `morgan_fp[bits]` and `morgan_fp[count]` to speed search. " + "through `similarity.AddMorganFingerprints`. For each document in a passed in collection, this method adds the nested field `{morgan_fp: {bits: }, {count: }}` to the document's `fingerprint` field. `AddMorganFingerprints` also creates indices on `morgan_fp[bits]` and `morgan_fp[count]` to speed search. " ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "similarity.addMorganFingerprints(TestDB, radius=2, length=1024)" + "similarity.AddMorganFingerprints(demo_db.molecules, demo_db.mfp_counts)" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'bits': [33,\n", - " 56,\n", - " 84,\n", - " 130,\n", - " 313,\n", - " 314,\n", - " 356,\n", - " 547,\n", - " 650,\n", - " 698,\n", - " 744,\n", - " 747,\n", - " 849,\n", - " 853,\n", - " 967],\n", - " 'count': 15}" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "TestDB.molecules.find_one()['morgan_fp']" + "demo_db.molecules.find_one()['fingerprints']['morgan_fp']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "From here, we can directly perform similarity search. `similarity` provides two methods that take advantage of fingerprint screening: `similaritySearch` and `similaritySearchAggregate`. The latter shifts much of the computation into the MongoDB server by using an aggregation pipeline and may improve performance when working with performant or sharded MongoDB servers. " + "From here, we can directly perform similarity search. `similarity` provides two methods that take advantage of fingerprint screening: `similaritySearch` and `similaritySearchAggregate`. The latter shifts much of the computation into the MongoDB server by using an aggregation pipeline and can dramatically improve performance when working with sharded MongoDB servers." ] }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "similaritySearch: [[0.35294117647058826, 'c1ccc(P(c2ccccc2)c2ccccc2)cc1'], [0.4117647058823529, 'Cc1ccc(S)cc1'], [0.35, 'CC(O)(c1ccccc1)c1ccccc1']]\n", - "\n", - "\n", - "similaritySearchAggregate: [[0.35294117647058826, 'c1ccc(P(c2ccccc2)c2ccccc2)cc1'], [0.4117647058823529, 'Cc1ccc(S)cc1'], [0.35, 'CC(O)(c1ccccc1)c1ccccc1']]\n" - ] - } - ], + "outputs": [], "source": [ "q_mol = Chem.MolFromSmiles('Cc1ccccc1')\n", "\n", "# Perform a similarity search on TestDB for q_mol with a Tanimoto threshold of 0.4. \n", - "results1 = similarity.similaritySearch(q_mol, TestDB, 0.35)\n", + "results1 = similarity.SimSearch(q_mol, demo_db.molecules, demo_db.mfp_counts, 0.8)\n", "\n", "# Do the same thing, but use the MongoDB Aggregation Pipeline. \n", - "results2 = similarity.similaritySearchAggregate(q_mol, TestDB, 0.35)\n", + "results2 = similarity.SimSearchAggregate(q_mol, demo_db.molecules, demo_db.mfp_counts, 0.8)\n", "\n", "print('similaritySearch: {}'.format(results1))\n", "print('\\n')\n", "print('similaritySearchAggregate: {}'.format(results2))" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that the search returns only the index for the molecule, which in this case is the inchikey; users should find it easy to go from the index to the full molecule document by way of a quick search. This also makes it easier for users to retrieve molecules when indices represent multiple tautomers or isomers in the collection.\n", + "\n", + "`SimSearch` and `SimSearchAggregate` both make use of the conventional fingerprint screening method. `similarity` also supports searching using Locality Sensitive Hashing, as developed by ChemBL in an excellent [blog post](http://chembl.blogspot.com/2015/08/lsh-based-similarity-search-in-mongodb.html). The method here is called `SimSearchLSH` and requires a little bit more setup work:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Generate 100 different permutations of length 2048 and save them in demo_db.permutations as separate documents.\n", + "similarity.AddRandPermutations(demo_db.permutations)\n", + "\n", + "# Add locality-sensitive hash values to each documents in demo_db.molecules by splitting the 100 different permutations\n", + "# in demo_db.permutations into 25 different buckets. \n", + "similarity.AddLocalityHashes(demo_db.molecules, demo_db.permutations, 25)\n", + "\n", + "# Create 25 different collections in db_demo each store a subset of hash values for molecules in demo_db.molecules.\n", + "similarity.AddHashCollections(demo_db, demo_db.molecules)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's try a search using the query molecule from earlier:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "q_mol = Chem.MolFromSmiles('Cc1ccccc1')\n", + "\n", + "results3 = similarity.SimSearchLSH(q_mol, demo_db, demo_db.molecules, demo_db.permutations, threshold=0.8)\n", + "\n", + "print('similaritySearchLSH: {}'.format(results3))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The LSH algorithm relies on random permutations using the `numpy` module, so it yields non-deterministic results. This means that LSH is well-suited for *scanning* datasets (its performance on large datasets is faster than either similarity search method), but is less accurate than regular similarity search, especially below thresholds of 0.7. Specific notes on benchmarks can be found in \"Benchmarking Similarity Search.\"" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Substructure Search\n", "\n", - "Likewise, `mongordkit.Search.substructure` supports substructure search best on databases prepared by `write`. Database requirements are identical to those for similarity search: a `molecules` collection whose documents have `rdmol` and `smiles` fields. \n", + "`mongordkit.Search.substructure` supports substructure search best on collections prepared by `write`. Requirements are identical to those for similarity search: a `molecules` collection whose documents have `rdmol` and `index` fields. \n", "\n", "`substructure.SubSearchNaive` provides a fingerprint-less, slower implementation of substructure search suitable for very small databases:" ] }, { "cell_type": "code", - "execution_count": 27, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['c1ccc(-c2ccccc2OCCOc2ccccc2-c2ccccc2)cc1',\n", - " 'COc1ccc(Cc2ccc(OC)cc2)cc1',\n", - " 'COc1cc([N+](=O)[O-])c(N)c([N+](=O)[O-])c1',\n", - " 'COc1ccc(/C=N/O)cc1',\n", - " 'Cc1nc2ccccc2c(Oc2ccccc2)c1-c1ccccc1',\n", - " 'O/N=C/c1ccc2c(c1)OCO2',\n", - " 'COc1ccc(CC#N)cc1',\n", - " 'COc1ccc(C(C)(C)C#N)cc1']" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "q_mol = Chem.MolFromSmiles('C1=CC=CC=C1OC')\n", "\n", "# Perform a substructure search for q_mol on TestDB. \n", - "substructure.SubSearchNaive(q_mol, TestDB, chirality=False)" + "substructure.SubSearchNaive(q_mol, demo_db.molecules, chirality=False)" ] }, { @@ -241,24 +359,26 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "substructure.AddPatternFingerprints(demo_db.molecules)\n", + "substructure.SubSearch(q_mol, demo_db.molecules, chirality=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## `.Search` contents" + ] + }, + { + "cell_type": "markdown", "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'substructure' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0msubstructure\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mAddPatternFingerprints\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mTestDB\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmolecules\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mTestDB\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmorgan_fp_counts\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlength\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0msubstructure\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mSubSearch\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mq_mol\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mTestDB\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mchirality\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mNameError\u001b[0m: name 'substructure' is not defined" - ] - } - ], "source": [ - "substructure.AddPatternFingerprints(TestDB.molecules, TestDB.mfp_counts, length=None)\n", - "substructure.SubSearch(q_mol, TestDB, chirality=False)" + "mongordkit.Search.**PrepareForSearch**(db (*MongoDB database for hash information*), mol_collection (*MongoDB collection*), count_collection (*MongoDB collection*), perm_collection (*MongoDB collection*)) --> None" ] }, { @@ -267,17 +387,30 @@ "source": [ "## `.similarity` Contents\n", "\n", + "### Constants:\n", + "- DEFAULT_THRESHOLD = 0.8\n", + "- DEFAULT_MORGAN_RADIUS = 2\n", + "- DEFAULT_MORGAN_LENGTH = 2048\n", + "- DEFAULT_BIT_N = 2048\n", + "- DEFAULT_BUCKET_N = 25\n", + "- DEFAULT_PERM_LEN = 2048\n", + "- DEFAULT_PERM_N = 100\n", + "\n", "mongordkit.Search.similarity.**AddMorganFingerprints**(mol_collection (*MongoDB collection*), count_collection (*MongoDB collection*), radius=2 (*int: radius of Morgan fingerprint*), length=2048 (*int: length of Morgan fingerprint bit vector*)) --> None\n", "\n", - "mongordkit.Search.similarity.**SimSearchNaive**(mol (*rdmol object*), mol_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, smiles]*\n", + "mongordkit.Search.similarity.**SimSearchNaive**(mol (*rdmol object*), mol_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, index]*\n", + "\n", + "mongordkit.Search.similarity.**SimSearch**(mol (*rdmol object*), mol_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, index]*\n", + "\n", + "mongordkit.Search.similarity.**SimSearchAggregate**(mol (*rdmol object*), mol_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, index]*\n", "\n", - "mongordkit.Search.similarity.**SimSearch**(mol (*rdmol object*), mol_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, smiles]*\n", + "mongordkit.Search.similarity.**AddRandPermutations**(perm_collection (*MongoDB collection*), len=2048 (*int: length corresponding to length of fingerprint bit vectors*), num=100 (*int: number of permutations*)) --> None\n", "\n", - "mongordkit.Search.similarity.**SimSearchAggregate**(mol (*rdmol object*), mol_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, smiles]*\n", + "mongordkit.Search.similarity.**AddLocalityHashes**(mol_collection (*MongoDB collection*), perm_collection (*MongoDB collection*), nBuckets=25 (*int: number of hash buckets. The number of permutations (mod NBuckets) must be 0*)) --> None\n", "\n", - "mongordkit.Search.**AddRandPermutations**(perm_collection (*MongoDB collection), len=2048, num=100) --> None\n", + "mongordkit.Search.similarity.**AddHashCollections**(db (*MongoDB database*), mol_collection (*MongoDB collection*)) --> None\n", "\n", - "mongordkit.Search.similarity.**SimSearchLSH**(mol (*rdmol object*), db (*MongoDB database containing hash collections*), mol_collection (*MongoDB collection*), perm_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, smiles]*" + "mongordkit.Search.similarity.**SimSearchLSH**(mol (*rdmol object*), db (*MongoDB database containing hash collections*), mol_collection (*MongoDB collection*), perm_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, index]*" ] }, { @@ -286,7 +419,7 @@ "source": [ "## `.substructure` Contents\n", "\n", - "mongordkit.Search.substructure.**AddPatternFingerprints**(db, length=2048 (*int: length of Pattern fingerprint bit vector*)) --> None\n", + "mongordkit.Search.substructure.**AddPatternFingerprints**(mol_collection (MongoDB collection), length=2048 (*int: length of Pattern fingerprint bit vector*)) --> None\n", "\n", "mongordkit.Search.similarity.**SubSearchNaive**(pattern (*rdmol object*), db, chirality=False (*boolean: include chirality in search or not*)) --> *list: results with format [smiles]*\n", "\n", diff --git a/docs/notebooks/Creating and Writing to MongoDB.ipynb b/docs/notebooks/Creating and Writing to MongoDB.ipynb index cdd4ad1..aec730f 100644 --- a/docs/notebooks/Creating and Writing to MongoDB.ipynb +++ b/docs/notebooks/Creating and Writing to MongoDB.ipynb @@ -488,7 +488,8 @@ "# If we had used inchikey again, the write would have imported 0 molecules.\n", "scheme = registration.MolDocScheme()\n", "scheme.set_index('CanonicalSmiles')\n", - "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf', scheme, reg_collection=demo_db.schema, chunk_size=50, limit=100)" + "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf', \n", + " scheme, reg_collection=demo_db.schema, chunk_size=50, limit=100)" ] }, { diff --git a/docs/notebooks/Similarity and Substructure Search.ipynb b/docs/notebooks/Similarity and Substructure Search.ipynb index c4263b5..837c466 100644 --- a/docs/notebooks/Similarity and Substructure Search.ipynb +++ b/docs/notebooks/Similarity and Substructure Search.ipynb @@ -6,18 +6,19 @@ "source": [ "# Similarity and Substructure Search\n", "\n", - "Last updated: 7/27/20\n", + "Last updated: 8/11/20\n", "\n", "Methods for similarity and substructure search are included in the `mongordkit.Search` module." ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "from mongordkit.Search import similarity, substructure, utils\n", + "from mongordkit import Search\n", "from mongordkit.Database import create, write\n", "from rdkit import Chem\n", "import pymongo" @@ -29,28 +30,255 @@ "source": [ "## Reset Cells\n", "\n", - "Run these cells to reset the local MongoDB instance used in this notebook." + "Run these cells to reset the MongoDB database used in this notebook." ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 5, "metadata": {}, + "outputs": [], + "source": [ + "client = pymongo.MongoClient()\n", + "client.drop_database('demo_db')\n", + "demo_db = client.demo_db" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Preparing for Search\n", + "Adequately preparing the database for searching requires adding a variety of fingerprints and hashes. You can easily perform all of the setup work required for similarity and substructure search by calling the method `Search.PrepareForSearch`. Generally, workflow will follow straight from the following two lines into search calls:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "scrolled": true + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "['TestDatabase', 'admin', 'config', 'db', 'local']\n", - "['admin', 'config', 'db', 'local']\n" + "populating mongodb collection with compounds from SDF...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:23] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [23:01:23] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "200 molecules successfully imported\n", + "0 duplicates skipped\n", + "Preparing database and collections for search...\n", + "Added pattern fps, morgan fps, and support for LSH.\n" ] } ], "source": [ - "client = pymongo.MongoClient()\n", - "print(client.list_database_names())\n", - "client.drop_database('TestDatabase')\n", - "print(client.list_database_names())" + "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf')\n", + "Search.PrepareForSearch(demo_db, demo_db.molecules, demo_db.mfp_counts, demo_db.permutations)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "However, the rest of this notebook will explicitly note the addition of fingerprints and hashes in an effort to better communicate how the code actually works. Let's reset the database again so that we can insert the hashes step by step without any issues." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "client.drop_database('demo_db')\n", + "demo_db = client.demo_db" ] }, { @@ -59,29 +287,130 @@ "source": [ "## Similarity Search\n", "\n", - "`mongordkit.Search.similarity` supports similarity search best on a database prepared by `mongordkit.Database.write`. Users can also use any database that has a `molecules` collection where each document in that collection has the following fields:\n", + "`mongordkit.Search.similarity` supports similarity search best on a MongoDB collection prepared by `mongordkit.Database.write`. For the general level of similarity search, users can also use any collection that has documents with the following fields:\n", "- `'rdmol': binary pickle object`\n", - "- `'smiles': some SMILES string`" + "- `'index': a unique identifier for each molecule`\n", + "- `'fingerprints': {a nested document that can be blank at the start}'`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Let's run through an example of similarity search. First, we'll have to set up our database:" + "Let's run through an example of similarity search. First, we'll write into the database 200 molecules from a data file included in the `mongordkit` package. We will use default write settings." ] }, { "cell_type": "code", - "execution_count": 4, - "metadata": {}, + "execution_count": 8, + "metadata": { + "scrolled": true + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "populating mongodb collection with compounds from chembl...\n", - "200 molecules successfully imported\n" + "populating mongodb collection with compounds from SDF...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:25] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:44] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:44] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:44] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:44] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:44] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:44] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:44] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:44] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:44] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [23:01:44] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:45] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [23:01:45] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [23:01:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [23:01:46] WARNING: Omitted undefined stereo\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "200 molecules successfully imported\n", + "0 duplicates skipped\n" ] }, { @@ -90,90 +419,90 @@ "200" ] }, - "execution_count": 4, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "TestDB = create.createFromHostPort('TestDatabase', host='localhost', port=27017)\n", - "write.writeFromSDF(TestDB, '../../data/test_data/first_200.props.sdf', 'test')" + "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "`similarity.SimSearchNaive` will directly loop through the database and display results. However, this implementation is extremely slow for any decently-sized database. Instead, `similarity` supports precalculating the following kinds of fingerprints for screening: \n", - "- Morgan (length 1048)\n", + "`similarity.SimSearchNaive` will directly loop through the database and display results. This is good for purposes of verifying accuracy. However, this implementation is extremely slow for any decently-sized database. Instead, `similarity` supports precalculating the following kinds of fingerprints for screening: \n", + "- Morgan (default radius 2, length 2048)\n", "\n", - "through `similarity.addMorganFingerprints`. For each document in a passed in database's `molecules` collection, this method creates a nested field that contains `{morgan_fp: {bits: }, {count: }}`. Note that `addMorganFingerprints` also creates indices on `morgan_fp[bits]` and `morgan_fp[count]` to speed search. " + "through `similarity.AddMorganFingerprints`. For each document in a passed in collection, this method adds the nested field `{morgan_fp: {bits: }, {count: }}` to the document's `fingerprint` field. `AddMorganFingerprints` also creates indices on `morgan_fp[bits]` and `morgan_fp[count]` to speed search. " ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ - "similarity.addMorganFingerprints(TestDB, radius=2, length=1024)" + "similarity.AddMorganFingerprints(demo_db.molecules, demo_db.mfp_counts)" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "{'bits': [33,\n", - " 56,\n", - " 84,\n", - " 130,\n", - " 313,\n", + "{'bits': [84,\n", " 314,\n", " 356,\n", " 547,\n", " 650,\n", - " 698,\n", - " 744,\n", " 747,\n", - " 849,\n", - " 853,\n", - " 967],\n", - " 'count': 15}" + " 967,\n", + " 1057,\n", + " 1080,\n", + " 1154,\n", + " 1337,\n", + " 1380,\n", + " 1722,\n", + " 1768,\n", + " 1873,\n", + " 1877],\n", + " 'count': 16}" ] }, - "execution_count": 6, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "TestDB.molecules.find_one()['morgan_fp']" + "demo_db.molecules.find_one()['fingerprints']['morgan_fp']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "From here, we can directly perform similarity search. `similarity` provides two methods that take advantage of fingerprint screening: `similaritySearch` and `similaritySearchAggregate`. The latter shifts much of the computation into the MongoDB server by using an aggregation pipeline and may improve performance when working with performant or sharded MongoDB servers. " + "From here, we can directly perform similarity search. `similarity` provides two methods that take advantage of fingerprint screening: `similaritySearch` and `similaritySearchAggregate`. The latter shifts much of the computation into the MongoDB server by using an aggregation pipeline and can dramatically improve performance when working with sharded MongoDB servers." ] }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "similaritySearch: [[0.35294117647058826, 'c1ccc(P(c2ccccc2)c2ccccc2)cc1'], [0.4117647058823529, 'Cc1ccc(S)cc1'], [0.35, 'CC(O)(c1ccccc1)c1ccccc1']]\n", + "similaritySearch: []\n", "\n", "\n", - "similaritySearchAggregate: [[0.35294117647058826, 'c1ccc(P(c2ccccc2)c2ccccc2)cc1'], [0.4117647058823529, 'Cc1ccc(S)cc1'], [0.35, 'CC(O)(c1ccccc1)c1ccccc1']]\n" + "similaritySearchAggregate: []\n" ] } ], @@ -181,46 +510,107 @@ "q_mol = Chem.MolFromSmiles('Cc1ccccc1')\n", "\n", "# Perform a similarity search on TestDB for q_mol with a Tanimoto threshold of 0.4. \n", - "results1 = similarity.similaritySearch(q_mol, TestDB, 0.35)\n", + "results1 = similarity.SimSearch(q_mol, demo_db.molecules, demo_db.mfp_counts, 0.8)\n", "\n", "# Do the same thing, but use the MongoDB Aggregation Pipeline. \n", - "results2 = similarity.similaritySearchAggregate(q_mol, TestDB, 0.35)\n", + "results2 = similarity.SimSearchAggregate(q_mol, demo_db.molecules, demo_db.mfp_counts, 0.8)\n", "\n", "print('similaritySearch: {}'.format(results1))\n", "print('\\n')\n", "print('similaritySearchAggregate: {}'.format(results2))" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that the search returns only the index for the molecule, which in this case is the inchikey; users should find it easy to go from the index to the full molecule document by way of a quick search. This also makes it easier for users to retrieve molecules when indices represent multiple tautomers or isomers in the collection.\n", + "\n", + "`SimSearch` and `SimSearchAggregate` both make use of the conventional fingerprint screening method. `similarity` also supports searching using Locality Sensitive Hashing, as developed by ChemBL in an excellent [blog post](http://chembl.blogspot.com/2015/08/lsh-based-similarity-search-in-mongodb.html). The method here is called `SimSearchLSH` and requires a little bit more setup work:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "# Generate 100 different permutations of length 2048 and save them in demo_db.permutations as separate documents.\n", + "similarity.AddRandPermutations(demo_db.permutations)\n", + "\n", + "# Add locality-sensitive hash values to each documents in demo_db.molecules by splitting the 100 different permutations\n", + "# in demo_db.permutations into 25 different buckets. \n", + "similarity.AddLocalityHashes(demo_db.molecules, demo_db.permutations, 25)\n", + "\n", + "# Create 25 different collections in db_demo each store a subset of hash values for molecules in demo_db.molecules.\n", + "similarity.AddHashCollections(demo_db, demo_db.molecules)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's try a search using the query molecule from earlier:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "similaritySearchLSH: []\n" + ] + } + ], + "source": [ + "q_mol = Chem.MolFromSmiles('Cc1ccccc1')\n", + "\n", + "results3 = similarity.SimSearchLSH(q_mol, demo_db, demo_db.molecules, demo_db.permutations, threshold=0.8)\n", + "\n", + "print('similaritySearchLSH: {}'.format(results3))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The LSH algorithm relies on random permutations using the `numpy` module, so it yields non-deterministic results. This means that LSH is well-suited for *scanning* datasets (its performance on large datasets is faster than either similarity search method), but is less accurate than regular similarity search, especially below thresholds of 0.7. Specific notes on benchmarks can be found in \"Benchmarking Similarity Search.\"" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Substructure Search\n", "\n", - "Likewise, `mongordkit.Search.substructure` supports substructure search best on databases prepared by `write`. Database requirements are identical to those for similarity search: a `molecules` collection whose documents have `rdmol` and `smiles` fields. \n", + "`mongordkit.Search.substructure` supports substructure search best on collections prepared by `write`. Requirements are identical to those for similarity search: a `molecules` collection whose documents have `rdmol` and `index` fields. \n", "\n", "`substructure.SubSearchNaive` provides a fingerprint-less, slower implementation of substructure search suitable for very small databases:" ] }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "['c1ccc(-c2ccccc2OCCOc2ccccc2-c2ccccc2)cc1',\n", - " 'COc1ccc(Cc2ccc(OC)cc2)cc1',\n", - " 'COc1cc([N+](=O)[O-])c(N)c([N+](=O)[O-])c1',\n", - " 'COc1ccc(/C=N/O)cc1',\n", - " 'Cc1nc2ccccc2c(Oc2ccccc2)c1-c1ccccc1',\n", - " 'O/N=C/c1ccc2c(c1)OCO2',\n", - " 'COc1ccc(CC#N)cc1',\n", - " 'COc1ccc(C(C)(C)C#N)cc1']" + "['RUTYZGCHBCCSKD-UHFFFAOYSA-N',\n", + " 'WECJUPODCKXNQK-UHFFFAOYSA-N',\n", + " 'GZZJZWYIOOPHOV-UHFFFAOYSA-N',\n", + " 'FXOSHPAYNZBSFO-RMKNXTFCSA-N',\n", + " 'KWLUBKHLCNCFQI-UHFFFAOYSA-N',\n", + " 'VDAJDWUTRXNYMU-RUDMXATFSA-N',\n", + " 'PACGLQCRGWFBJH-UHFFFAOYSA-N',\n", + " 'CDCRUVGWQJYTFO-UHFFFAOYSA-N']" ] }, - "execution_count": 27, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -229,7 +619,7 @@ "q_mol = Chem.MolFromSmiles('C1=CC=CC=C1OC')\n", "\n", "# Perform a substructure search for q_mol on TestDB. \n", - "substructure.SubSearchNaive(q_mol, TestDB, chirality=False)" + "substructure.SubSearchNaive(q_mol, demo_db.molecules, chirality=False)" ] }, { @@ -241,31 +631,44 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 15, "metadata": {}, "outputs": [ { - "ename": "NameError", - "evalue": "name 'substructure' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0msubstructure\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mAddPatternFingerprints\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mTestDB\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmolecules\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mTestDB\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmorgan_fp_counts\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlength\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0msubstructure\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mSubSearch\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mq_mol\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mTestDB\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mchirality\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mNameError\u001b[0m: name 'substructure' is not defined" - ] + "data": { + "text/plain": [ + "['RUTYZGCHBCCSKD-UHFFFAOYSA-N',\n", + " 'WECJUPODCKXNQK-UHFFFAOYSA-N',\n", + " 'GZZJZWYIOOPHOV-UHFFFAOYSA-N',\n", + " 'FXOSHPAYNZBSFO-RMKNXTFCSA-N',\n", + " 'KWLUBKHLCNCFQI-UHFFFAOYSA-N',\n", + " 'VDAJDWUTRXNYMU-RUDMXATFSA-N',\n", + " 'PACGLQCRGWFBJH-UHFFFAOYSA-N',\n", + " 'CDCRUVGWQJYTFO-UHFFFAOYSA-N']" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "substructure.AddPatternFingerprints(TestDB.molecules, TestDB.mfp_counts, length=None)\n", - "substructure.SubSearch(q_mol, TestDB, chirality=False)" + "substructure.AddPatternFingerprints(demo_db.molecules)\n", + "substructure.SubSearch(q_mol, demo_db.molecules, chirality=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Substructure Searching using Locality Sensitive Hashing" + "## `.Search` contents" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "mongordkit.Search.**PrepareForSearch**(db (*MongoDB database for hash information*), mol_collection (*MongoDB collection*), count_collection (*MongoDB collection*), perm_collection (*MongoDB collection*)) --> None" ] }, { @@ -274,13 +677,22 @@ "source": [ "## `.similarity` Contents\n", "\n", + "### Constants:\n", + "- DEFAULT_THRESHOLD = 0.8\n", + "- DEFAULT_MORGAN_RADIUS = 2\n", + "- DEFAULT_MORGAN_LENGTH = 2048\n", + "- DEFAULT_BIT_N = 2048\n", + "- DEFAULT_BUCKET_N = 25\n", + "- DEFAULT_PERM_LEN = 2048\n", + "- DEFAULT_PERM_N = 100\n", + "\n", "mongordkit.Search.similarity.**AddMorganFingerprints**(mol_collection (*MongoDB collection*), count_collection (*MongoDB collection*), radius=2 (*int: radius of Morgan fingerprint*), length=2048 (*int: length of Morgan fingerprint bit vector*)) --> None\n", "\n", - "mongordkit.Search.similarity.**SimSearchNaive**(mol (*rdmol object*), mol_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, smiles]*\n", + "mongordkit.Search.similarity.**SimSearchNaive**(mol (*rdmol object*), mol_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, index]*\n", "\n", - "mongordkit.Search.similarity.**SimSearch**(mol (*rdmol object*), mol_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, smiles]*\n", + "mongordkit.Search.similarity.**SimSearch**(mol (*rdmol object*), mol_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, index]*\n", "\n", - "mongordkit.Search.similarity.**SimSearchAggregate**(mol (*rdmol object*), mol_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, smiles]*\n", + "mongordkit.Search.similarity.**SimSearchAggregate**(mol (*rdmol object*), mol_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, index]*\n", "\n", "mongordkit.Search.similarity.**AddRandPermutations**(perm_collection (*MongoDB collection*), len=2048 (*int: length corresponding to length of fingerprint bit vectors*), num=100 (*int: number of permutations*)) --> None\n", "\n", @@ -288,7 +700,7 @@ "\n", "mongordkit.Search.similarity.**AddHashCollections**(db (*MongoDB database*), mol_collection (*MongoDB collection*)) --> None\n", "\n", - "mongordkit.Search.similarity.**SimSearchLSH**(mol (*rdmol object*), db (*MongoDB database containing hash collections*), mol_collection (*MongoDB collection*), perm_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, smiles]*" + "mongordkit.Search.similarity.**SimSearchLSH**(mol (*rdmol object*), db (*MongoDB database containing hash collections*), mol_collection (*MongoDB collection*), perm_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, index]*" ] }, { @@ -297,7 +709,7 @@ "source": [ "## `.substructure` Contents\n", "\n", - "mongordkit.Search.substructure.**AddPatternFingerprints**(db, length=2048 (*int: length of Pattern fingerprint bit vector*)) --> None\n", + "mongordkit.Search.substructure.**AddPatternFingerprints**(mol_collection (MongoDB collection), length=2048 (*int: length of Pattern fingerprint bit vector*)) --> None\n", "\n", "mongordkit.Search.similarity.**SubSearchNaive**(pattern (*rdmol object*), db, chirality=False (*boolean: include chirality in search or not*)) --> *list: results with format [smiles]*\n", "\n", diff --git a/mongordkit/Database/__pycache__/create.cpython-37.pyc b/mongordkit/Database/__pycache__/create.cpython-37.pyc index 495d11c6db7158328a7c29037a5f64c008dd1bbf..3366231c901096cf8174c21a55643a775d2f57be 100644 GIT binary patch delta 20 acmaFM^_Gj($ZN*T!xQG{RZbjFac?YyogX)7EEm8BX-mNaQm1zaqYP3pgceU;k zU7~e(*Qwso8jm~xtF(4Q7lk#)xA+7~x%DCQ;9cT$H*mMCa0rzmr;cwAod-JfZ)8OU zKD7e7V?$piYFpPjTfNPj?e)Fw>+Oy>_kQcW?Y-V&>jMfy?E+2+R}CI4ufr2w0-$&d1U?}nC`&|>h953VGc<6>go(~ruDc5KjGQbrv#Gs^P2Nr~p)(vC{9 zS4sA&B*kMhso*S$A-@_?IVs-JliVo7uOx+I=z(9+(t|4>XzHuf_v`I9lOkC3>QObd z=zeO^{TtfB_b^sZs`Hu;zK8MP+v93t+>`5vS`lg`RRfD_G^a*@&kXDJtfrX+t`E2q zv5-VVM(n_km>-2C7?4hDlSBd8y}r|1zrM4xA-zH@pAwrh3r5JnmQNg?vfCu^r3O_A z$INyHj?E~1C7t!HjopnVxjv4Zz_(m7wz%c7i1Bb$D!EMTIE(_%Ib?(ecI<%-B#d}$ zM=@ulKOsut#PRoumFgq&!9#-nC(MqTsk&RZBxz45V=Mg(#=wd!5;C*^df0*M!Z5Jv z)Fkh3ygRq*soE1Ohruo4S^k800Vs%Fz|R6p9Y16|f>m1)OcObtGM+^dTE4z@v;AJL zv)$d8Ds&ysiKLx=?DZK(+)p&(D!?5GAwrO9+1cLR-ct%zC6G9xce0XIat)yI_k-5j z-1-&NmPCHcA&`Zstm_3n6J-_WJs~l?=+YIa;zmu>76VjdA^t=`SuARcQ6bC|r;EJw zmngw_waG+Yeig>l&%!)GNaQ(%p1h3fHKt1ty7RThFGAZd>&rJ`dxp#QkVDu8<00eA zEf$WTxGWudnbVOIsj@1ztjOwHAzPLwN^?9B6?t54f_K5WB~Tk)1)3yO>V90W z!=2F$cuf7#^lies0(B+pdM;x^y#}|b^9JZRo7OJ;JzBe)ED~BfrH}TE&^|m^0Yb~q z2(7R{XrIpr4SOltLqao75n5?RXe&TU<{Y7|03pe*lF)ws1EKwxTJ$3j+IMFV+IK0T zl@|!DJV$7i1wtbb=zm6NJKLST{~1m3xH{72dH0ON^k2kiE^O#IO2aC0sXP!;Dhd~v zK%GASJraBS;Ykd^oUxcZUH>tMRe1%@J6=VBIXquNQAhD8ipNl#Ljiw68h;$c6DXcU z@f3(gjXw=9kwfeFGuZqrisw)~kAk3h0mTIrFQRw}1@Z%b8O19okQ$V@1SL_Qo$tGW zy93JCp!Li%-h9|I{x#5KXF%YEZ_EqU;R*5oPX0<|4u6wJ*bUdR*)VV^WIT3283Ae~ z78%68%2uNxWSEkZAn}}~hPDOiER_m68+&`(?RW9KQ;Gd7(Y-jIwOz#IQf7Q9(UI2L z!akw>RhVF!Pts{G;NQsd?Nf=N%206txY5Q5l2j;APZ7yqbbWx{F&z%q&$y3D)S)lBDNbSFddSa s498HH?vS(1*(i6L+-Sx-UO?f`=?Xe2#4TQjbV%LjvN^rJf{$VT4i~5T3IG5A literal 4963 zcmeHL&2JmW72oCO@=Ky*xoMEJowi9_r3&R5{Q%T7s4PmAP@6GAIR*q2#BygTuDRT$ zXJ;czSsq#kJ_J4lMGr;M19j{*r(XMS?6oH&NKQHR(*E8omm+N^F>+{o$P)W@xbx=C zn>X*{H+#KSD{Htu{$!=&d|T80Nq^EShsLjQ2YnE(aoyF9=$Uc#Vdf~KQ#AU-8(8r&m;EreYoyR)(@n3&Et_RZexG8ui zu%&do-#Yq8cv^4DpwHkD_u^d!Ub(NW)2um!l<` zpBsa$_fA<%ulnLR%W>F2uIohlRo37G`nVCGsmOdvTWA8&Sc+KY?kjy+miwFd(8A$ySc}D zj%z0k;SX8+ogEBhCbN9kwJquR9%nzDlscP z=yj^gMlyLn^akid$4nL`gU-jo4@XL=o&DRb-*(yuN4v?GlfGm18Mk|8=t6Dq{^aV_ z27AYrq3{w}7jw^~s_C$PTSzFbrl48p*2F^r_hk-blE%rBwnnBfhm3c(*fv!3j(wOe zUBk?t3%mjE5%aB6*@va}$d-QhE(}MuP$sYgM?i_x)Qh8qwZ-;)p*TaRdnI6@bX-TC zZeR}rsg#s`Q(|`RSSIc9N#7Q>8lkq%7tS%_7(EN3g?-%dN3?&?&vpG1EEJnBe3$v} zVXH{DnT5D-g+urS%@|rRt=(YFIh&IzN#HBXPJu+-oXrL3<_WOZ8VAw1v~*!J@{;wr7)kFhGj~%40}U ztmg~00^5XFrS7sYvqetY37j)~i|zX-Y-oC?EVU073DeKaHgl|}e1yR;CX>$4o(dPr zVYk>J%r1Rtx^p3u>JdCc@`cMLg3f+9@<*YYtW3Em@6P-6i6i^?KOFg?#{<@*n6{AI zyKbY=5C+n5T%EW6S^gEz9NK65q*ySrEvM(eThkrpJ~r0#CA05i!y4?4P<%1JBEs|{Swi7M$-2!;rqAkGU8Ys72w zDyFsO><90UFXmxEXjyg;^g@@k!GbB)*Vp3G%$#w4g!qy1Wf!`4E-cxh6$he16B|9~ z(SdSt{Yi$n^zQbJgJ$QT*^YB}eaDN-@0xCC?+W3IxByognlfJ6-)`@B_HMU!4iDaL zwMCYst|6vRP$t{Wo4(r)M|&Hhm2J1ziFa@xBuGNybY#c)9MSD*B>D(Z8q&-faa!h%r{i*C+(!! zoR+4|6RK8?(P>;&tvz@t@*{a?&;-#|3%Ze6)9bj6jG>p&GV~mNb=}Z2xYzVd7Ch)N zvgpOTDz))j#j~m}>EbHnJR6Vn{vYtjAEQMi@~3+b7m!G00f~H^_R8u6*ab)gcx1Bt z1QMw)Ad%0eNaQmhk(C(|c?fg?T=EnWd3a~aMaTyzWMAPK<0CzI3kXGxpCOd}c^OIH z7b27l0z#$SuRtg!&;&9CQiMtYlnYgjN(&FAZp0g20|S_IdEg>!7xMVmFX9V&Osn}~ zZAH|5Q?|b;+bJIYuas?7uKrimT9trltrj&T)}$~jqxD=>`I4$TVuePo5~12FE)iKH za+%1th`c}q2W3sXNaQ6VR8qyuM5soJ?-2Pek?#>qK5B@?#l0}Q7i=Kp$c5nyujX)jSGiU!+Y4nzBT6W)eIWWBCbDQ!a@?kIZlEa$9 zX+lsNHp!;7=b6gDfxTWUAfGs#vLr(>Snr?Sa;JDKkHWI$!r zqWCG=7Fm@pdOpj-|9E~2lcT}F@0pHkcHQJ~J#W6$@~Vzu)#;)9YZ);;JZ#TuoA8XS_M|IX*eOMY|PH S<}d*6lAn<&|Em0^QTh*p?7RK| diff --git a/mongordkit/Database/tests/__pycache__/test_create.cpython-37-pytest-5.4.3.pyc b/mongordkit/Database/tests/__pycache__/test_create.cpython-37-pytest-5.4.3.pyc index 4f112e0f7fb42e88f22be710a73f34798c594f07..c238be580ad04120a5942de9566b559feb85afb8 100644 GIT binary patch delta 87 zcmcc3-NB{o#LLU&dR{Aj3nK%=V+JI^0%SV?adFv1rURxO^*J5=#=3 z5{pwcnQpOU4C_mQ&s3riYB8oS; z$Q>pa8swwN6vdp8k`%?9n37Z^1Jnc|WPz+(+$E{SCGik5gn$CYAb&A13NRLdoT@1@ jS(jxoqtfIvENT)WKmiU0AqE~s4lv|ll3?Os;$Q~=S5`ii diff --git a/mongordkit/Database/tests/__pycache__/test_write.cpython-37-pytest-5.4.3.pyc b/mongordkit/Database/tests/__pycache__/test_write.cpython-37-pytest-5.4.3.pyc index 59da7eb7b6893695a763777d2f789f9293ac1050..f537de466671d49eaa17a005b84e7072ed302dac 100644 GIT binary patch literal 6323 zcmeHMO^h5z74E<3znT5>U+e_J5(s#LGrQ}bwT)~m#2bf5$qFziXe87cPxtQjx@US^ z)objfM?$eBP6%@e67pe|6GWVH;Kr6GLbS-i>rw22U6Iyrl!R(HQ}XT^&w`ct=9Fz`c^C3pz`uY z)G71^*vbz@oJC-2B3h4SCR$mXcH7j0emWil&t*Jv8YI&O`i|Dua&6PV*!pVSEWA$I zT~9k{`+8A*kJ!se9Cfq82(MvayUlOE(L@#fAFVEYPewv6v^NAkm-aRyv9J=!>tGjn zoYzHoJLKewPG7Wgzjo$6Tkx{nQTX}PeW=NZ&>8>v5ty~0E(jwl# zBQJnNyj4vj)I$SGGea}9P+DOnv{6=u%Cwa#n@(5_Yp8d_DJ*%q@V<+Ayia;-lYZz& zOQVPN^df49deSrFj@HMA`etTsT74@wHY@!~X!Pye$}72@>vzn)lbgA7-RQfyD?iQb zffJg!yQYU0)vp;l7V6yG+|k2I<_-KE?Yb=!)KxRoiJR0)T-QK5Nm`J!OUVyOGB+SO z;8t*uw3)B$=v><9;gmfda1R|l{=lu^(8FQgfuwuiJ)-qJQcv#1I(R>;p>-zjC7JQkh`9=q>^8lA`0hYz5t?N>tVtJ+QG)?y*E;N;?BqbJgyY{+n}u0Jv^ zUaafeKY8_d@Agt%&R@JZ&+MtX^nbL=&8x~YyLDiORS;|NPF)dc=jzH8zki%Mo!gZJ zGn8D0WG79c_Er)}zkfn~X0a}Z96nz6`=WxG3lF5I(xd~~hABmLw=gk3BBzL)A+k*5 zTw$SMk?9iCQ`<8w2@}ZF7cf_@K2x6-HjP_*FHKg`_EjF34>EtWsEw|JY;HK$!hfT8 zn=B(}iDE8jw~{0fQBSnfPOl}R!V6?;EuxyD2Fc*sR-9yUR~B}XLRc0@1G$lIB_a0; z)|2#FD+#)-PE<^PgC`0=cuR;>6bFN~RCHQd5Z&q}tu8}Fy;@i@O4h{Oo@VGXYK@CU zb?@c$=*!vBm-A|Bs?XBN(WaBCNquSzXJG zfgQqLbnSg$|F^a8Xx~SPQ*W#`%}$!u9kr#j)#4?P!dAOi*rFB7NEY5(x7tyUP`L1b zZ9&`(qg!=Te1&?@ER?1RZAMl;$8(RnH(N;@zC&G(LO{A88dmP=HGTV~iIt8@munqE zvMYei@wH-ordl5`%*-sHnU(9CHZaXBG0hmqw0pYrGiTre&j{5jC8{|Ck5SFe{6Upb z?H1%}8SqPd0L~+hv5F)K)tplDS0tGeM*Wr~iDQf+o=}ZSLN&MS@kj1KIQR*-Djal~ zCsgx>sOE>&64j>AI{hqEW1ZA!&;Jdb81glYy$_v0d-ov8TDhl-U($R(TQ89QJxP;3 zApL-(pRF78`Um%dPSER9?)BXC!{>i$wV1iw>ZaWopmVho17*bw4(I-^0Wk~F|H*rR zt+DQk1DK#7yb*_p942yv$O}Zs7{xJ=$G~3@JT(sh^!e)fW=n2d%|zT?ug^>%g*Zin z@CEca;yzF0Wg=f7GEd}-L|!5CB_dxY@+wHZI*A`&rKaOV>O@{6@--qSh`dguL1Y4F zs*E!mm}MmC+wwGsLKuGxU+p2j9@Qu7f2VNw@B|vEF`tY>i;v;Zh)1PQcvKVU^B?o5 z2z!)ArLgDO9u;Aa@~D(;Jr9qnT6&hx(8E1L9)gdy58o1KunkG}E`bJj$?yAY{}R%_ zCg~yKd`!|q#CeKF(CZWKr4Z+@-0S&ig>Ky1>i+=--X#N!pg;v4CdEbUX0q?`-v*OI z3?^IM_{LWBPM3UQcs=Cj$VCu^Do^s+j!q!W5K&&9K$MArOK2fiksfyE7CBfOb?2T0 zEvR#b0h^J-gnnuvSVNG8pv}uY9OhXZU65kBR@1NWhlzQ z*$warTG*(>M3@JZEhL15wxg4?@!!AnUl*r92_oPc62-n*+O!3d=B5L!|<&- z5x#k&;Tw3TkK_fL)XN;SnrOhIEvbB$&5F_T+#4` z#K*wefpAtCAVsoCwrA{^aImd@h29Zr*qd(OiIHN+o!mtqxc#{Yd-QW({)KD;frbxj zw5gu0(Svosau7t+22&hvd3|eP%gaKs&gpwXUB|gY<@VH2ss07ING0u2w$K7^gO|;f!;|$UsHyW}NmwJQC z13hc#fQ=wmYaL0q9~?p0i4aD6cnu%Q*bCb=fR$KQIWj_ zCTJ8!1G$JK?nV>)|H!|PARk9bgG*=Vi|X^+rzbF#lMopDT?liC-MFCA2$#U@4iNtx z+q`G*Hz(~Kxs+k@hEqD62!X+&U04R!3w(siG zNFdCXm#)j{lQo3^^UpdUt97q%15PLfLE#5MCk>Hf178b*8(Xb}QcXc17VtSi(S%qg za+b)~iM&l@Z{p0+^(`nLO<5;NZ?551T-$Z=RJf)7LgDV_x;QQ>js+^!(oon4U!x%+ zP8JnjSyed0I^MX#=^vM^F9$UhPImw;AOI7h9F&LZK$ZuM|hLK;Y> z$;}8E9^~P=S@R(0w^_ciGR$c!7mTw(?3>Y=p0wD)y`c1Vi99(;@uaIA&}!Hi^;a{F L8a2IUxYoY_RC*P@ literal 4115 zcmc(iO^hQ)700XE?f$Smo|)avX2VAqLO!;m#PhK`n~lVxkX<6>zzB#)kPoqXrh0Zf z)9yA^?XbJFFBuLTkk|u?A{3!9;=+w{jyWNY9Q%aC0fj>@+;ZaoUbh{4NQOZoiLH9| zy6RPR)vKysy?%LVsqv4${OipRY$5(G=6-kpwP;HtTx_x^J>{co6CJJCQkpy3YMPuhmgMEA>*n6K3IVXrlEjGMQo7<6(A& z_Y2oV*=Ts@(h>{x zWNE?Domu{hEOP&WC@-tRFm~;KsBBi+Uv9;BQqbNnmU;5*lH2Jh$(B)Q zu0ROsVBf!D1IbzH^=}sF%=tv0}0?QK42noNp||-R|;Un50R6FYK8?KaNb` z6i&IMg`>m1iA>RWJ&Z>Yufiw$KtGE90?GbA?UYq^NIzz>uS-wk_43*z=Z3z{^L_Pl$sBpPcLB<7S8t?f4i%)k&?lWW> z6=WKxAmhzL26`RI8M|kCW9ck!JhTj9@*MtnD9zijWRE&<`hBt{ z9kBfZ{lc5Sy`yRCocjdm0M^CIbkoPvT`x6V!(elX;W;*gt`(c1{h!!e;(8OFAGP=B0bM?KEs-5 zr5_{l6%t=1@ih`(C-FFmZ$O|S-6VRA#5YMiLE>8^o`hHcYDLWouiN^mnL&ls7Z$Mk z;%S03nIH$DIf$61<|aCrM=D`;g|YfBV|8r~x6?XDoRrAjM%x)}h=ViQv}d%*enncaR4p@Un`%X^=1nGTt0Had6loX2xr(&@7~cfAPA{DQI@NT2;|{FQ@nwW{ z=fK1w8$cT724j@qR%HzP!X4tnH16+e`UWj(=DsPc)aYmNr0Y~< zlR@Ex!(o&tYHZT@tq6f3V)`WOUgR%I{)+5OzaqX^d(J)VD2|=I iZx2#6ilgt)F*0=dc;bR+;X{-E))lK|c{cua&-pi%TJb&r diff --git a/mongordkit/Search/__init__.py b/mongordkit/Search/__init__.py index e69de29..73fd660 100644 --- a/mongordkit/Search/__init__.py +++ b/mongordkit/Search/__init__.py @@ -0,0 +1,12 @@ +from .substructure import * +from .similarity import * + + +def PrepareForSearch(db, mol_collection, count_collection, perm_collection): + print("Preparing database and collections for search...") + AddPatternFingerprints(mol_collection) + AddMorganFingerprints(mol_collection, count_collection) + similarity.AddRandPermutations(perm_collection) + similarity.AddLocalityHashes(mol_collection, perm_collection, DEFAULT_BUCKET_N) + similarity.AddHashCollections(db, mol_collection) + print("Added pattern fps, morgan fps, and support for LSH.") \ No newline at end of file diff --git a/mongordkit/Search/__pycache__/__init__.cpython-37.pyc b/mongordkit/Search/__pycache__/__init__.cpython-37.pyc index cb98211bbf5b72a3988c7e30aafcf4d72e542376..49f5b05457114b55f7679e56ecd89c46ca4c68d4 100644 GIT binary patch literal 684 zcmYjPO>fgM7`EeftE#P(Avkf!kswHr*b&gScGU!>s%U%3C30i0jh4ibU+1tXxA8;P z8~mkQIq?@b@j3ymw%)Jj{q)Dh@o}Hv`uO8CdgT!E%NqX|+T;ugULq4j(3C7&Nl`k2 zeJ7zKIt$`;e^U(cXiZ7+ST`sc7ZgJBYA{PQ`ZC#~!+f zGIOwFjdfU&itcO-cC^`oU_UmydpFmz;5x}SuHc5RIY^i1!i`m$%Ge|-2lrZO7bMs5 z*7yCp_vb=L;TGH&sdM+bfH!WY^oIY_Z8nrep|oi-r;97!>($)?o0#wgX3yKy2{x6w zfgya3_}8Y&K3w-9$&wW3Gq>S04EcuD=Tc{-;mvH}Qv|0f<|#&8ao9=-hvUo1`D(h1 zE>@#2m&<4to?wu5jvf!?b!tbf!$GFf=<%%KFji%5_K_zAw%Y@K5`BQL@Mj#XKxzo$ ztxmwGVk>npmT-e=kg0s5-fD4^m{xDqMRSKi6eW3LqR209>tTESa-wwWwNDKLWQ6u` y_i+#C5!F3JW*)1Lpj?B|Wo$|@g1FCPR--&!|0; zT0Y%!W<={!75f&Uid0>eP^n^u1y$6giVYMS7A&aZFJRLU6O*F&OsSp{D(-4xN|bPSKE9e3Gq_r? zXY5%#n-z1oTC}H8`;?eRen~8dMbv(YTU-(^;ofO+TAabXGxoGyLanpn9PXZt+jv=+ zxH>0Z5$93nWue|z%CA1BnW>c3FneeFkzMm|3FM9Ib-RiG%vz%nXS3^;Z*5ziz59oM zK%eK|d#<6TqhuB3`4V!^1(F)gFMV*Af7kKv{T`BCrKkIfuRhWO#n*j9sGsYHsUzj7 z+B5ba1?pk?NLg1t`nZ>hO8J??Y>*P#l5(Vulu!G)zzEV$wO%I31lnFoUI_HVywLrL zAoEmRPzlXkRLmV$noYN1*E$V6{KWC==BCwhny&A1JsHG| zZToS@YS6>YoA++qzjHjsqs~Ftz}Aqoayr9j~3Xfxeau|cia}rnz!B7 zuDgECJibdW^UbDh`<^NBLPy$7yXAXB4f%Cxdv&)VR+Ay1UVM)SdOVmFbKTytIt{dk zp1-y7Zq#LI`yI)BXgHp4x;y6m+qX7u+>hSB(`oED4UDzl=o_ZhKwqP2^Xs;QS&1jl z^lC0%9d!^QmTFydd@oG#G<5U*Vyk91U&DNbr`B)0zxH5bbL;kjaibFE(9)f# z6UGkSBuRur{kGc(Cu>%tw$<-an6}z&yCp&$ohWBR9qSerkqoR-m`mm$%wU)_k)i&0 zryZtIaNVt;7A~^=Hvd$S=kU5O-@o+0v!!>bR+ku}+pgR4(z@;KA$zGwtNx}GdyXIF zqiiI&mj;%ueGnG!JI&}p#d4n53uxP$N225mHLn)&ox?A$X4R7Vk}6F+sgWAfhd?uj zAFJ#?BeVa*Ksi)cE${X;U-h*|P~5{*pb3@LGVN!C1~tyI8tYI?ozxk%po}P`FDVXG zQKSMrFhu$b%~2io2*~?5{}9O0OYL7x-tcx$+kXRfGE0ic;+I<@I9TkZgVfS6In>E-aQ zDKSZRIaj2dm;xM>tbgdk!I}_&0v0S2($JSIbKCLFCy*>xdZyJ9P{9t=EE4cYxac-3 z3xw)}&6`w%b;yEZ2)EW@y)>QH2+*vUw^~?wl%-efkP_Ri+5rjzftnVnKDP?-cFpT| z9#l35P-;lchb8d@ynt{)Q+AJ`ZKw$z)qpsEO(Vy>1t8FPhZ>WXa5~#$giuEOLCgpDNsU~CnqT(bdoca6e*daq=Y2YF-2j%(-ts7TW-q^^hEU>RzZm2~~@+ zEJ|LcrcObdUI1zDO+4~w&Xjynol!LaQWmf@qZ-J~t7nj#!<{_7@-j-*Xz=u*@snS{ z0QCrS4WGgYG=eC24Gd54Eet=!z6JaVfKfWog|?^3C;RJwfeb^%yFJCv0<6;T5CBoa zz>hoy?Www}!ly6}^FhYX;%S=vhs1lh3@9<~EATARXgTW_{K>;2pe;KG?*eyn2PMA{ zWCQ&)y%`YKI%6pQ)LvfxwW`q9FA4Z3z5K5$E$u@EC3A}ay9K2;5oq#DkrVl63dWNm z|1d~1SgME9@Dj5}+Tlzvaip$O%Y_!6iefPFV|Yis!v4oJvLF}a#ncxXY8C*xC4xTy z=zAFJn31yQr0=DEqRR8pcz4woNBk4@@%d=X;xmx|9ebu?gq^6c#kP^@*=-! zYsax00#LYS_T4AA5P)GA2=d>ce@+c*3yVYL$n%OS63|&fIEfX&69UoAzB8408^hS? zwi*X!&1$(VwA(N}xT<}ZYxQU5$}z4o4$5U{sr(KljExh>g*q&nyntMdP?A0nD1~(U zK7QUDl3f_)j|x3CKqR)L{J!=W+6KI4I3+g;h^(!=#Q-z{HDBhh(9G7{X8Y<6HAiiy zmG0TZA6mK6a4{F&Rb=`lx#h0D?6kPeN?C(N*!69s4d2GqS0eORf_r&ZzJV@`qW3Un zM*x3{%FR+jb09Awp~>5GQai0@Tj{-m?t%C0rNP0fJQ&_0?@C-K%Wm%fZL2e z;TPal>Om$3`YeDRp=J#9xftk+0Q$d(fqsgCJ{JQ${LvWb^8osPO@KblK%a_%z7zxf zbdZmMegZ(B0?_9f=qJP!nGAwI2H?y#kEMOi(yddy^mv$RJIU(SahKxBd!C@N+T&n{~%S zoa@(JVRk%3?5Tf2z7ciB@m+fLhVI4yg~cZ6dM=>5MQX@505%U^`5&! zAXDJ+#FAd9IW0sJ1lN*akaLlR8nU4&JYySr1{t=YbA1~MONvl^SBq`wU}KR%nMhkQdzCReHBze33sO1?|URZ6}`$$Ln`TwjCja`9yQm6$HMMm4Wd zLWV)EQ*winA0P>{pk3N7g*(F{7|y&XavmypB(q9B;zz#5R%vWT*=$0 zn~ZKfc0;H_dj{gu*8(-rD99i@W$uBfNW-f3Q56&rIfQTnJ1yq?Ohj;7 zZCf@wKEoS(hP!slmgFo}9^5u1NC&rR4whknj^l9(x}(V11S`SBg=am%TWqUVC+Bj2 z@U#e1J)8ViG~Q<{hJf^#cN|X)3>C(ESIrF$+o>CaDnkx#GK|5#6B#+wNUPIC%-?Bl zgI7f(V}?s@(U{_Deebq{2$*Lg(G*&oL{msKSX1Uf8>u~B8j2%@@5 z!ZPi<a!uPORcL$bp9O6~VdN>hB>rJb55aw)5 z0ouZcyP&Tpuh&m%Z3TMak;E$seo+ zFksJQw;we9o1WeB5J^3;&AR2)%_ml)L;B`M%Fq{h(u(1&02U+K`4Fbt8d5bXd-uk@ z+k=dpIq0dxl)RUylgEv{SdF?-hZI8vFAj*?#V8_V#qD>H*e`BnxR--1FqaKpfOmh&vsQ9wnUSeU!9U$fg36-O}>={A#MVS!Wx!ORw|aX3ZkmhW!G?aS9t5X}+M zB_ANEW?R>ySBL2cD8s_Q{Da@Zv@>^)f3{6wHfeo=Ti=y#r~N`iG!5C?pnwyScN3kk zy+6n6JPOB@e2J;95+WW0u@6NHAlG zl~{LBJ#Pcbj2^{08f=Y08(&Mxp$;Y<5eBpHF(Xf^bEHFMOt9#nsYC{LDBJxTma6Ma z2|{9>ogG_ZFKJ-6iHTS2KQU>+CWPo@5?XjR@RA6kA!5;B$fBZ|ApWs)3xvs9!* zO>9S!u|-cTYAg*Lh3yFq>h>t0&R~t{Ro9bEI`8jL$s^=cG8FhyU@Pmms*&ZP4+#MI zawM_dW!MIwXuRY3!oFx)V8IZ8rJ3~u9ts0Y=8yK@|4ez59>Zk<6^XH=EtHtcMCc1H zlQ5JwRR*}ss|ayZ3746RxlAL-#UXB~l|{2zwg(^&@bbAGcR;S41=_{nl%odu zU_vY)7%v8s6mWlmAew@14!N=O9;B0C93i%N1)=+S@v1QUfjIq(We&pg;ye65FD{6S zfsq8`^I(IQf_YfP1@Rj9WPy4DbuC-3_O0A?wnuH@2uZh#pC0M9J|Y%1~$d&c5To6q>eD1{55H|Tp#7^0SJjq zS$vcrGI`s!4YMlA^8_#;76Sk`4n|R7mGLCrI~UtSmq}0KyD>6wjd;H&aRbR68%sKp zd-GI{0wvaT)TH1AZXiVnq1qbJe|GWyk@T3_1ledN0S2MkIKB}}ri>#;kE3r%G2GX8 z_GE^XJ9}aX{x8Sf9VI`%^-IaRM-$bbq4u~L`uF2kCa)m$Bj1u(Pwy=x?2Eq^`Qo3! z3y&6q4HzQWfHVbINSnuTBx}eTs__`4pxgx{SSrSI@)2VHT;4@KRO?twn~HHvNSjl< zdjEk;yn5V9(!p;fB~&<(lKpXW@Sn%;NnSy7FeV=aeVcza#0VcgT-VHdBLkUmO>JJ2eTP>?;d(}M7m_*FIcTBU$DmD5W zl#u6xQ!KX6j7fPhB3)QN63=*G=YW`(YL@m3nEU4`U88ocQF5JjZ;LIMk}y;2NNiSkp$eBe%2)G|KZwnEk2@nbs48h`Ut>vG!@?l6{ypw^_mK2i z8*;TuWA_+npMmxmW_W+Wi1!(aYFb-V&uFEX%`wz7eLlxStBDUz5Jf*4qDMY>%;gLo zW79up?;8$=24_Uyzs%~pg3$OiKSf?Rl=%#RErqRUEr5F_FXONpPPLG;aaVbaP36b0 z!5L#NsFI+=w*sI6GbJ5#bDT8J9!q1Fd8K|BGtN-OMzfqbS!_v$SVU2X_ndg)NmQcM z|5fC$jV1OOfk%5pvN%IMqLT~?7O%+LK{HrL-uI{H2@^q~5c$-En4XUW$OtbeQ0K9~ z<-r7B5h&sOp$|Wr{YPCG&)_9v zs|bs>ppXZ86dfSC7B5b!(p^2Kv--0a1+?2B%y@5ZyJ4H#2WAvCP&gC^o+}ZxPOC~E z`llc1xktom01x>p9FPT!qO4XT1<+&zk3#hTtWy?EM(USXurPb2VKujfb@c*f^50NY z>AphhG!XC(E^bt|oQ)Ww6rY%5Xo*gD#NlrW92-tO&C#24OhmeF!wb{!%{n!^oaWW7 zPH=ak$eA}5s+oAC)hOnM4;KgBp}O7I=O<`XvhgJtI(NMO1rCJ`$N_B!zOFJ%C2H8$ z1zvxWHDBR1BVsj+@E0rkRKvXK-3K4gK}ZmzTSUt|*j%HdocG7lhFF_ul{{LeXz)am z4%eh0cO_9ubeM%OSvFsJ1p4bU1P;7xpyRX_j`~G3CDR{RI&}+432zvpawCo4$@m1# zzJa#oJ~G|&qa@#$HPmp7&}z%yLV4J@Pw`hR(TWUG7yU`6r_rQuBKJB?I!&meNxDuZ znI@Oq5yrZ=k)eH7Qlvwi{G%!6BQBbcbA3TMddULZuk4wabmL50D~Mc z*~vkLfykuh+B-W=%^_}K+x9;p_uu~nEH1Cz8b=6~YbyxTFQOaLMG_Xk5+xfjynjG* zU9qZKWxJ|ZtVqNL=9HG`5{;F7eMLhUPIt;?m}wvIfl4}YiW8N*HGy+p9;hUmmgw|n zo}aDI(dX#6X`bsuHE5P_Y_-#DAIRUPDglz}bpL2+a@zO!fL3*~|M1$a&8}K zQL|T?uE5#mt0dGOE%+joFZyQHtZwLr%0B?Jp%><}XN%?HrQ&2^F|KOu)szqcSIN@+65Ob(qXICxkrcHi#4 zec$)q^2YSE!*KoR@3UK_G4pEOpB?pTTm~j=CF)%K@?V4%Q)nm?Y;bfr6$&3dw=DOIWDdZ&)=7>-{}Uj zBg4c?{3vvz9XIwne&8uTdE~~@Q_c1(?k9fIj(Umi=7o>k9Y1VI)m46&xN%cS8KT1d zr0pefB=@DN>y}r$p7J_w*Gm$q!mI9T=qk~P0yo-zD4U6!puMYPSIHRT$FAoJ8T(2K zH|}l6iRv|zo|5DKCv=MKtM2`_bj8T%ZiG=W0l(RHlV~*Wy1U+s6SwVQnVyS*WwRH^ z*lk7uinQDlI+Hdg(vAWF)n4d#A}Bhlb9W*&VVSzSCU?AEfLWu}mHHd`f|bOKX{B!9 zV`La}bN$ZUTbub(cY48&9|XrrUva%4BE!MFsFl8Qlkv!LGs1N82|hF6IX<%(gU=Ph z8-5aJ1#QaAjxgG`Cbkhr(TjTj;w%6^-P}EA9i9VSjwzKk)b+RJnO4i8Cy`65uMvJwmiIzLv ztTa~f7p7LA{mZv6zaL8#Uv9P)W*l|fQe9q?@h*y&J1|G|suH_?l9%)1ruM_j$DUd5 zKFVe`{Z9TtdvY1N<2eXcw)iriIw3DFFmSWzOIBRSwE80u(zZS8bxMrP4^vVxw_Gl7=s1ro3@dq$#WsEbtLLiA^jde*61fA;uYE7+*b zs%dIHLxQ5B2DKu0)$mlaRH{H^W+20c)9b?Kaw`gDX0|Z5f}hAvoH;<>R&L;i;Gu~-9nBLYt2qRK@=9!%<%baGr7w&Gw*rd!v zqm1und|!h*7tfK#GoBE+#V1H8zJO2h^AM~!$6bxj1#aOt#~1ho+-G?OKXn-`P9T*w zKqK`YEc#6WG&O{^Yp9P7UYiJ{)d9la&`yfLC8Mw?>=pKy!Y?p43Xxax5IIJ5Qcj%V zRBEJ!B_JO-w;#qA$N;q46O@OM96Seg`Gt zqwJR3qIVoF5l{8NSCBMNoCO0R1wiV6oZ)EfT)(FKQN&b~ducE#a=aXy zMEsfQhdb&L)t!TA5>)A;7>Gc@HgU&G5G@es$CUx-U$7PSM`O0G0*3?}MczfI~$x6S(1V;kq|tzQcw1l;&K3gZrXfWBGvL#=wFW`KNJiG&Oi ziMP|#ahh9d3#a*mSYv`+=INDUrg{;A?2%+v#{>SYru2hsz9Ch#=I{G4lBHWpMJg-o z1d*3yXK0pSmvJVw6?z>RtCvWP6-Npz6oAGP@XG?}UnD`cRLJg`It!7Nkt^f`mDwnD z{4jrd2icsGd-z2BJ!&yKQA50`mPrp;e}Z%7PMh_0e2?o8%%-HE1e&RWY)T*+1LYa~ zh;AzUl2IWFG8d3EEOYf1dK}RY8I9QYChmCu|CWBlye1yd&4_pwDZRm&>I}|M=Wu3P zNv)Pncu@PCI4>?B1-dAn7w4&Ve2W)!ud;CUb6)&FTuMj1S|$jKPCpB&bI1o%;zdoB zQ$&V9T($r2{}qzbIYUR{R3zM9tkaP(33{!TlCAtS)%CkF@I#rC(l;`j`+c#Rx&k-- zeppTYm{hqWP6AE6hPsEi$9(qcY2dAntRTM)vGwgLNT=EU&IH#lRl6#p!z6JcQXix! z#2Nhp2(~Z#bCj#y332?4^8;UhwtAdy>GZ2u72r1^p{hFSY*mrE^vhM8LKEdd_uND$ zodZ$Mx9_PqGyD+Aou(p+D7uuB^oeLvz_(2@7o|Tsnk( z#?^n@f|PXTA*HtXow#281YH%;qxva{pON@Ei8n|PkE>shxC)V#$4)J4m9OP<^-F4h zjl{1=Tqp4+iCYj^38_FgqBQiRFJ&uV>pLHyUrclS7VK>}U~z*lan~%F3t)5g4*DH& zxQQ2v@0!CYxC?AZjc@45)XdY1IyJ?`(^I^=dHYi+(Y9w?QD|?{KF~!&(T3}x2q^Ry zP6`Se8h9d;)Y&A?mZ|ZWCrB-{L_JP=#xgsfPpoE*VltgJDhSL+KCHK?W;Tos5BGM% z-0-$f*;L2$#~3=Mr7}7MQ(rH+cGmfi9Uq+9atk``79JQhb{%62pJogk@ zVZ+fCb^6;&A50pKZkRWt;qvn~CGa|o>V41_$}^2))9R8wE0nHvB7y&AuG1F9lpK^0 Sqf2>gHl0Oh*}3G@9P2*_lOGiT diff --git a/mongordkit/Search/similarity.py b/mongordkit/Search/similarity.py index 83e1e22..b31ac43 100644 --- a/mongordkit/Search/similarity.py +++ b/mongordkit/Search/similarity.py @@ -1,7 +1,4 @@ -import pymongo -import rdkit -import math - +import pymongo, rdkit, math from bson import ObjectId from rdkit import Chem from rdkit.Chem import AllChem @@ -9,8 +6,21 @@ import numpy as np import functools +# Default configurations for a variety of constants. +DEFAULT_THRESHOLD = 0.8 + +# Morgan fingerprints +DEFAULT_MORGAN_RADIUS = 2 +DEFAULT_MORGAN_LEN = 2048 + +# LSH constants +DEFAULT_BIT_N = 2048 +DEFAULT_BUCKET_N = 25 +DEFAULT_PERM_LEN = 2048 +DEFAULT_PERM_N = 100 + -def SimSearchNaive(mol, mol_collection, threshold=0.8): +def SimSearchNaive(mol, mol_collection, threshold=DEFAULT_THRESHOLD): """ Searches MOL_COLLECTION for molecules with Tanimoto similarity to MOL greater than or equal to THRESHOLD. @@ -20,16 +30,19 @@ def SimSearchNaive(mol, mol_collection, threshold=0.8): :return: A list of SMILES that fulfill threshold, along with their tanimoto scores. """ results = [] - qfp = list(AllChem.GetMorganFingerprintAsBitVect(mol, 2, nBits=2048).GetOnBits()) + qfp = list(AllChem.GetMorganFingerprintAsBitVect(mol, DEFAULT_MORGAN_RADIUS, + nBits=DEFAULT_MORGAN_LEN).GetOnBits()) for molDoc in mol_collection.find(): - mfp = list((AllChem.GetMorganFingerprintAsBitVect(Chem.Mol(molDoc['rdmol']), 2, nBits=2048).GetOnBits())) + mfp = list((AllChem.GetMorganFingerprintAsBitVect(Chem.Mol(molDoc['rdmol']), DEFAULT_MORGAN_RADIUS, + nBits=DEFAULT_MORGAN_LEN).GetOnBits())) tanimoto = calc_tanimoto(qfp, mfp) if tanimoto >= threshold: - results.append([tanimoto, molDoc['smiles']]) + results.append(["tanimoto: " + str(tanimoto)] + + ["index" + ": " + str(mol["index"])]) return results -def AddMorganFingerprints(mol_collection, count_collection, radius=2, length=2048): +def AddMorganFingerprints(mol_collection, count_collection): """ Adds Morgan fingerprint bit vectors and counts with RADIUS and LENGTH bits to all documents in MOL_COLLECTION. Inserts bit frequency information @@ -40,38 +53,43 @@ def AddMorganFingerprints(mol_collection, count_collection, radius=2, length=204 :param length: NBits in desired Morgan fingerprints. Defaults to 2048. """ for m in mol_collection.find(): - bit_vector = list((AllChem.GetMorganFingerprintAsBitVect(Chem.Mol(m['rdmol']), radius, length).GetOnBits())) + bit_vector = list((AllChem.GetMorganFingerprintAsBitVect(Chem.Mol(m['rdmol']), + DEFAULT_MORGAN_RADIUS, + nBits=DEFAULT_MORGAN_LEN).GetOnBits())) count = len(bit_vector) - mol_collection.update_one({'_id': m['_id']}, {'$set': {'morgan_fp': {'bits': bit_vector, + mol_collection.update_one({'_id': m['_id']}, {'$set': {'fingerprints.morgan_fp': {'bits': bit_vector, 'count': count}}}) counts = {} - chunk_size = 100 for m in mol_collection.find(): - for bit in m['morgan_fp']['bits']: + for bit in m['fingerprints']['morgan_fp']['bits']: counts[bit] = counts.get(bit, 0) + 1 for k, v in counts.items(): count_collection.insert_one({'_id': k, 'count': v}) a = count_collection.find_one() - mol_collection.create_index('morgan_fp.bits') - mol_collection.create_index('morgan_fp.count') + mol_collection.create_index('fingerprints.morgan_fp.bits') + mol_collection.create_index('fingerprints.morgan_fp.count') return None -def SimSearch(mol, mol_collection, count_collection=None, threshold=0.8): +def SimSearch(mol, mol_collection, count_collection=None, threshold=DEFAULT_THRESHOLD): """ Searches MOL_COLLECTION for molecules with Tanimoto similarity to MOL greater than or equal to THRESHOLD. :param mol: An rdmol object. :param mol_collection: A MongoDB collection that meets requirements. :param threshold: Tanimoto threshold for similarity. Defaults to 0.8 + :param return_fields: A list of strings that indicate fields to return in addition + to the Tanimoto threshold. Defaults to only canonical smiles. :return: A list of SMILES that fulfill threshold, along with their tanimoto scores. """ results = [] a = count_collection.find_one() - qfp = list(AllChem.GetMorganFingerprintAsBitVect(mol, 2, nBits=2048).GetOnBits()) + qfp = list(AllChem.GetMorganFingerprintAsBitVect(mol, DEFAULT_MORGAN_RADIUS, + nBits=DEFAULT_MORGAN_LEN).GetOnBits()) if threshold == 0: for mol in mol_collection.find(): - results.append([calc_tanimoto(qfp, mol['morgan_fp']['bits']), mol['smiles']]) + tanimoto = [str(calc_tanimoto(qfp, mol['fingerprints']['morgan_fp']['bits']))] + results.append(tanimoto + [str(mol['index'])]) return results qfp_count = len(qfp) fp_min = int(math.ceil((threshold * qfp_count))) @@ -85,17 +103,16 @@ def SimSearch(mol, mol_collection, count_collection=None, threshold=0.8): {'_id': {'$in': qfp}}).sort('count', 1).limit(req_common_count)] else: req_common_bits = qfp[:req_common_count] - for mol in mol_collection.find({'morgan_fp.count': {'$gte': fp_min, '$lte': fp_max}, - 'morgan_fp.bits': {'$in': req_common_bits}}): - - - tanimoto = calc_tanimoto(qfp, mol['morgan_fp']['bits']) + for mol in mol_collection.find({'fingerprints.morgan_fp.count': {'$gte': fp_min, '$lte': fp_max}, + 'fingerprints.morgan_fp.bits': {'$in': req_common_bits}}): + tanimoto = calc_tanimoto(qfp, mol['fingerprints']['morgan_fp']['bits']) if tanimoto >= threshold: - results.append([tanimoto, mol['smiles']]) + results.append([tanimoto] + + [str(mol["index"])]) return results -def SimSearchAggregate(mol, mol_collection, count_collection=None, threshold=0.8): +def SimSearchAggregate(mol, mol_collection, count_collection=None, threshold=DEFAULT_THRESHOLD): """ Searches MOL_COLLECTION for molecules with Tanimoto similarity to MOL greater than or equal to THRESHOLD. @@ -106,10 +123,12 @@ def SimSearchAggregate(mol, mol_collection, count_collection=None, threshold=0.8 :return: A list of SMILES that fulfill threshold, along with their tanimoto scores. """ results = [] - qfp = list(AllChem.GetMorganFingerprintAsBitVect(mol, 2, nBits=2048).GetOnBits()) + qfp = list(AllChem.GetMorganFingerprintAsBitVect(mol, DEFAULT_MORGAN_RADIUS, + nBits=DEFAULT_MORGAN_LEN).GetOnBits()) if threshold == 0: for mol in mol_collection.find(): - results.append([calc_tanimoto(qfp, mol['morgan_fp']['bits']), mol['smiles']]) + tanimoto = [str(calc_tanimoto(qfp, mol['fingerprints']['morgan_fp']['bits']))] + results.append(tanimoto + [str(mol['index'])]) return results qfp_count = len(qfp) fp_min = int(math.ceil((threshold * qfp_count))) @@ -124,23 +143,23 @@ def SimSearchAggregate(mol, mol_collection, count_collection=None, threshold=0.8 else: req_common_bits = qfp[:req_common_count] aggregate = [ - {'$match': {'morgan_fp.count': {'$gte': fp_min, '$lte': fp_max}, - 'morgan_fp.bits': {'$in': req_common_bits}}}, + {'$match': {'fingerprints.morgan_fp.count': {'$gte': fp_min, '$lte': fp_max}, + 'fingerprints.morgan_fp.bits': {'$in': req_common_bits}}}, {'$project': - {'tanimoto': {'$let': {'vars': {'common': {'$size': {'$setIntersection': ['$morgan_fp.bits', qfp]}}}, - 'in': {'$divide': ['$$common', {'$add': [qfp_count, {'$subtract': ['$morgan_fp.count', '$$common']}]}]} + {'tanimoto': {'$let': {'vars': {'common': {'$size': {'$setIntersection': ['$fingerprints.morgan_fp.bits', qfp]}}}, + 'in': {'$divide': ['$$common', {'$add': [qfp_count, {'$subtract': ['$fingerprints.morgan_fp.count', '$$common']}]}]} } }, - 'smiles': 1 + 'index': 1 } }, {'$match': {'tanimoto': {'$gte': threshold}}} ] response = mol_collection.aggregate(aggregate) - return [[r['tanimoto'], r['smiles']] for r in response] + return [[r['tanimoto'], r['index']] for r in response] -def AddRandPermutations(perm_collection, len=2048, num=100): +def AddRandPermutations(perm_collection, len=DEFAULT_PERM_LEN, num=DEFAULT_PERM_N): """ Uses the function get_permutations to generate NUM random permutations of bits of length LEN and saves each in COLLECTION as a separate document. @@ -153,7 +172,7 @@ def AddRandPermutations(perm_collection, len=2048, num=100): for i, perm in enumerate(get_permutations(len, num))]) -def AddLocalityHashes(mol_collection, perm_collection, nBuckets=25): +def AddLocalityHashes(mol_collection, perm_collection, nBuckets=DEFAULT_BUCKET_N): """ Adds locality-sensitive hash values to each document in MOL_COLLECTION based on permutations in PERM_COLLECTION. This method requires documents @@ -191,7 +210,7 @@ def AddHashCollections(db, mol_collection): {'$push': {'molecules': moldoc['_id']}}, True) -def SimSearchLSH(mol, db, mol_collection, perm_collection, threshold=0.8): +def SimSearchLSH(mol, db, mol_collection, perm_collection, threshold=DEFAULT_THRESHOLD): """ Conducts a similarity search for query molecule MOL in MOL_COLLECTION with Tanimoto threshold THRESHOLD. @@ -202,11 +221,13 @@ def SimSearchLSH(mol, db, mol_collection, perm_collection, threshold=0.8): :return: """ results = [] - qfp = list(AllChem.GetMorganFingerprintAsBitVect(mol, 2, nBits=2048).GetOnBits()) + qfp = list(AllChem.GetMorganFingerprintAsBitVect(mol, DEFAULT_MORGAN_RADIUS, + nBits=DEFAULT_MORGAN_LEN).GetOnBits()) qfp_bits = [int(n) for n in qfp] if threshold == 0: for mol in db.molecules.find(): - results.append([calc_tanimoto(qfp, mol['morgan_fp']['bits']), mol['smiles']]) + tanimoto = [str(calc_tanimoto(qfp, mol['fingerprints']['morgan_fp']['bits']))] + results.append(tanimoto + [str(mol['index'])]) return results qfp_count = len(qfp) fp_min = int(math.ceil((threshold * qfp_count))) @@ -223,29 +244,36 @@ def SimSearchLSH(mol, db, mol_collection, perm_collection, threshold=0.8): permutations = [p['permutation'] for p in perm_collection.find()] min_hash = get_min_hash(mol, permutations) hash_groups = hash_to_buckets(min_hash) - nested_res = [list(i)[0]['molecules'] for i in - [db['LSHash_' + str(i)].find({'_id': h}, {'molecules': 1}) for i, h in enumerate(hash_groups)]] + nested_res = [] + cursors = [db['LSHash_' + str(i)].find({'_id': h}, {'molecules': 1}) for i, h in enumerate(hash_groups)] + for c in cursors: + cursor = list(c) + if len(cursor) == 0: + continue + else: + nested_res.append(cursor[0]['molecules']) hashed_ids = [ObjectId(x) for x in (set([str(item) for sublist in nested_res for item in sublist]))] aggregate = [ - {'$match': {'_id':{'$in': hashed_ids}, 'morgan_fp.count': {'$gte': fp_min, '$lte': fp_max}, - 'morgan_fp.bits': {'$in': req_common_bits}}}, + {'$match': {'_id':{'$in': hashed_ids}, 'fingerprints.morgan_fp.count': {'$gte': fp_min, '$lte': fp_max}, + 'fingerprints.morgan_fp.bits': {'$in': req_common_bits}}}, {'$project': - {'tanimoto': {'$let': {'vars': {'common': {'$size': {'$setIntersection': ['$morgan_fp.bits', qfp]}}}, + {'tanimoto': {'$let': {'vars': {'common': {'$size': {'$setIntersection': ['$fingerprints.morgan_fp.bits', qfp]}}}, 'in': {'$divide': ['$$common', { - '$add': [qfp_count, {'$subtract': ['$morgan_fp.count', '$$common']}]}]} + '$add': [qfp_count, {'$subtract': ['$fingerprints.morgan_fp.count', '$$common']}]}]} } }, - 'smiles': 1 + 'index': 1 } }, {'$match': {'tanimoto': {'$gte': threshold}}} ] - results = mol_collection.aggregate(aggregate) - return [[r['tanimoto'], r['smiles']] for r in results] + response = mol_collection.aggregate(aggregate) + return [[r['tanimoto'], r['index']] for r in response] def get_min_hash(mol, permutations): - qfp = [int(n) for n in AllChem.GetMorganFingerprintAsBitVect(mol, 2, nBits=2048)] + qfp = [int(n) for n in list(AllChem.GetMorganFingerprintAsBitVect(mol, DEFAULT_MORGAN_RADIUS, + nBits=DEFAULT_MORGAN_LEN))] min_hash = [] for perm in permutations: for idx, i in enumerate(perm): @@ -255,7 +283,7 @@ def get_min_hash(mol, permutations): return min_hash -def hash_to_buckets(min_hash, num_buckets=25, nBits=2048): +def hash_to_buckets(min_hash, num_buckets=DEFAULT_BUCKET_N, nBits=DEFAULT_BIT_N): if len(min_hash) % num_buckets: print('Length of min_hash must be divisible by number of buckets.') return @@ -267,7 +295,7 @@ def hash_to_buckets(min_hash, num_buckets=25, nBits=2048): return buckets -def get_permutations(len_permutations=2048, num_permutations=100): +def get_permutations(len_permutations=DEFAULT_PERM_LEN, num_permutations=DEFAULT_PERM_N): """Gets NUM_PERMUTATIONS random permutations of numbers of length LEN_PERMUTATIONS each.""" return map(lambda _: np.random.permutation(len_permutations), range(num_permutations)) diff --git a/mongordkit/Search/substructure.py b/mongordkit/Search/substructure.py index 3d1c593..b198442 100644 --- a/mongordkit/Search/substructure.py +++ b/mongordkit/Search/substructure.py @@ -20,7 +20,7 @@ def SubSearchNaive(pattern, mol_collection, chirality=False): for molDoc in mol_collection.find(): rdmol = Chem.Mol(molDoc['rdmol']) if rdmol.HasSubstructMatch(pattern, useChirality=chirality): - results.append(molDoc['smiles']) + results.append(molDoc['index']) return results @@ -33,7 +33,7 @@ def AddPatternFingerprints(mol_collection): mol = Chem.Mol(moldoc['rdmol']) bit_vector = list(PatternFingerprint(mol).GetOnBits()) count = len(bit_vector) - mol_collection.update_one({'_id': moldoc['_id']}, {'$set': {'pattern_fp': {'bits': bit_vector, 'count': count}}}) + mol_collection.update_one({'_id': moldoc['_id']}, {'$set': {'fingerprints.pattern_fp': {'bits': bit_vector, 'count': count}}}) return @@ -49,14 +49,10 @@ def SubSearch(pattern, mol_collection, chirality=False): results = [] query_fp = list(PatternFingerprint(pattern).GetOnBits()) qfp_len = len(query_fp) - for molDoc in mol_collection.find({'pattern_fp.count': {'$gte': qfp_len}, - 'pattern_fp.bits': {'$all': query_fp} + for molDoc in mol_collection.find({'fingerprints.pattern_fp.count': {'$gte': qfp_len}, + 'fingerprints.pattern_fp.bits': {'$all': query_fp} }): rdmol = Chem.Mol(molDoc['rdmol']) if rdmol.HasSubstructMatch(pattern, useChirality=chirality): - results.append(molDoc['smiles']) - return results - - -def SubSearchAggregate(pattern, db, chirality=False): - return \ No newline at end of file + results.append(molDoc['index']) + return results \ No newline at end of file diff --git a/mongordkit/Search/tests/test_similarity.py b/mongordkit/Search/tests/test_similarity.py index 07f5f64..52bc7dc 100644 --- a/mongordkit/Search/tests/test_similarity.py +++ b/mongordkit/Search/tests/test_similarity.py @@ -136,6 +136,7 @@ def test_similarity_accuracy_LSH(mongoURI): for t in thresholds: for i in range(200): mol = Chem.Mol(db_python[i]['rdmol']) + smiles = Chem.MolToSmiles(mol) search_python = [result[1] for result in utils.similaritySearchPython(mol, db_python, t)] search_mongo_LSH = [result[1] for result in similarity.SimSearchLSH(mol, db_mongo, db_mongo.molecules, db_mongo.permutations, t)] diff --git a/mongordkit/Search/tests/test_substructure.py b/mongordkit/Search/tests/test_substructure.py index 2b29a7d..22a2425 100644 --- a/mongordkit/Search/tests/test_substructure.py +++ b/mongordkit/Search/tests/test_substructure.py @@ -9,7 +9,7 @@ def test_addPatternFingerprints(): write.WriteFromSDF(db.molecules, 'data/test_data/first_200.props.sdf') substructure.AddPatternFingerprints(db.molecules) counter = 0 - assert db.molecules.count_documents({"pattern_fp": {"$exists": True}}) == 200 + assert db.molecules.count_documents({"fingerprints.pattern_fp": {"$exists": True}}) == 200 def test_SubSearchAccuracy(): diff --git a/mongordkit/Search/tests/utils.py b/mongordkit/Search/tests/utils.py index 8521df3..c38936c 100644 --- a/mongordkit/Search/tests/utils.py +++ b/mongordkit/Search/tests/utils.py @@ -25,7 +25,7 @@ def similaritySearchPython(query_mol, molecules, threshold): mfp = list(AllChem.GetMorganFingerprintAsBitVect(Chem.Mol(mol['rdmol']), 2, nBits=2048).GetOnBits()) tanimoto = calc_tanimoto(qfp, mfp) if calc_tanimoto(qfp, mfp) >= threshold: - results.append([tanimoto, mol['smiles']]) + results.append([tanimoto, str(mol['index'])]) return results @@ -38,7 +38,7 @@ def SubSearchPython(pattern, molecules): for moldoc in molecules: mol = Chem.Mol(moldoc['rdmol']) if mol.HasSubstructMatch(pattern): - results.append(moldoc['smiles']) + results.append(moldoc['index']) return results From 8ef571426cf44a69e078e02bd38bd2ef899c7d84 Mon Sep 17 00:00:00 2001 From: Christopher Zou Date: Tue, 18 Aug 2020 14:41:20 -0400 Subject: [PATCH 3/7] Update hashes, update README, polish documentation and benchmarks --- README.md | 41 +- ...ng and Writing to MongoDB-checkpoint.ipynb | 519 +++++++++-------- .../Similarity Testing-checkpoint.ipynb | 244 -------- ...y and Substructure Search-checkpoint.ipynb | 430 ++++++++++---- .../Creating and Writing to MongoDB.ipynb | 519 +++++++++-------- docs/notebooks/Explore LSH.ipynb | 284 ---------- .../notebooks/Exploring Multiprocessing.ipynb | 340 ----------- docs/notebooks/Similarity Benchmarking.ipynb | 428 ++++++++++++++ docs/notebooks/Similarity Testing.ipynb | 532 ------------------ .../Similarity and Substructure Search.ipynb | 496 +++++++--------- .../notebooks/Substructure Benchmarking.ipynb | 211 ++++--- docs/testing.md | 11 +- .../Database/__pycache__/write.cpython-37.pyc | Bin 4377 -> 0 bytes mongordkit/Database/registration.py | 16 +- mongordkit/Database/write.py | 19 +- mongordkit/Search/similarity.py | 6 +- mongordkit/Search/tests/test_similarity.py | 2 +- 17 files changed, 1650 insertions(+), 2448 deletions(-) delete mode 100644 docs/notebooks/.ipynb_checkpoints/Similarity Testing-checkpoint.ipynb delete mode 100644 docs/notebooks/Explore LSH.ipynb delete mode 100644 docs/notebooks/Exploring Multiprocessing.ipynb create mode 100644 docs/notebooks/Similarity Benchmarking.ipynb delete mode 100644 docs/notebooks/Similarity Testing.ipynb delete mode 100644 mongordkit/Database/__pycache__/write.cpython-37.pyc diff --git a/README.md b/README.md index 4471e86..fadbe91 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,18 @@ [![Build Status](https://dev.azure.com/cwzou/mongo-rdkit/_apis/build/status/rdkit.mongo-rdkit?branchName=master)](https://dev.azure.com/cwzou/mongo-rdkit/_build/latest?definitionId=1&branchName=master) Mongo-rdkit is an integration between MongoDB, -a NoSQL database platform, and RDKit, a collection of chemoinformatics and machine-learning software. +a NoSQL database platform, and RDKit, a collection of cheminformatics and machine-learning software. This package contains tools to create and manipulate a chemically-intelligent database, as well as methods for high-performance searches on the database that leverage native MongoDB features. Useful links: * [BSD License](https://github.com/rdkit/mongo-rdkit/blob/master/LICENSE) - a business friendly license for open-source. -* [Jupyter Notebooks](https://github.com/rdkit/mongo-rdkit/tree/master/docs) - resources for getting started. +* [Jupyter Notebooks](https://github.com/rdkit/mongo-rdkit/tree/master/docs) - walkthroughs for main functionality. +* [Testing Guide](https://github.com/rdkit/mongo-rdkit/blob/master/docs/testing.md) - walkthrough of running `mongordkit` tests. ## Documentation Jupyter Notebooks and resources for getting started in the [docs](https://github.com/rdkit/mongo-rdkit/tree/master/docs) -folder on GitHub +folder on GitHub. ## Installation As the package is not officially configured with a setup.py file or pushed onto PyPi, these are working install instructions. @@ -43,9 +44,43 @@ echo $PYTHONPATH You can now `import mongordkit` in your Python interpreter or run all tests using the `pytest` command. ### Windows: +Similarly, ensure that `conda` has been added to `PATH`. +Clone the repository into your desired directory and navigate into it. +Create a conda environment called mongo_rdkit that includes dependencies: +``` +conda env create --quiet --force --file env.yml +``` +Activate this conda environment: +``` +call activate mongo_rdkit +``` +Check that you are able to import mongordkit: +``` +python -c "import mongordkit" +``` +If this fails, you may need to add the current directory manually to `PYTHONPATH`: +``` +set PYTHONPATH=%PYTHONPATH%;C:. +``` +You can now use `mongordkit` in your interpreter and run tests using `python -m pytest`. +## Package Contents +### Modules +`mongordkit` contains two main modules, each of which contains a variety of importable methods and classes. +`Database` contains functionality for writing and registering data. `Search` contains functionality for setting up and performing +substructure and similarity search. Detailed walkthroughs can be found in the notebooks, listed below. + +### Notebooks +- **Creating and Writing to MongoDB**: documentation and demos for creating and modifying mongo-rdkit databases. +- **Similarity and Substructure Search**: documentation and demos for similarity and substructure search. +- **Similarity Benchmarking**: documentation for reproducing similarity benchmarking. +- **Substructure Benchmarking**: documentation for reproducing substructure benchmarking. +### Configuration +- **azure_pipelines.yml**: CI/CD pipeline configurations. +- **conftest.py**: `pytest` configurations. +- **env.yml**: required dependencies. ## License Code released under the BSD License. diff --git a/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb b/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb index aec730f..c581d97 100644 --- a/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb +++ b/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -35,7 +35,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -88,14 +88,14 @@ "## Data Registration\n", "`Database.registration` constructs document representations of molecules according to configurable schemes and handles data registration settings.\n", "\n", - "It does this in two parts. First, it defines the global variables `RDKIT_HASH_FUNCTIONS` and `HASH_FUNCTIONS` as dictionaries that hold map hash function names to methods. It also defines the global variables `DEFAULT_SCHEME_NAME`, `DEFAULT_AUTHOR`, `DEFAULT_PREPROCESS`, and `DEFAULT_INDEX`, which are used in scheme creation and are thus defined for easy configuration. \n", + "It does this in two parts. First, it defines the global variable `HASH_FUNCTIONS` as a dictionary that maps hash function names to methods. It also defines the global variables `DEFAULT_SCHEME_NAME`, `DEFAULT_AUTHOR`, `DEFAULT_PREPROCESS`, and `DEFAULT_INDEX`, which are used in scheme creation and are thus defined for easy configuration. \n", "\n", "Second, the file defines the `MolDocScheme` object, which stores scheme information in its instance variables and is passed into `.write` methods in order to specify molecule document format. By default, `MolDocScheme` includes scheme name, author, whether or not the molecule has been pre-processed, an index option, hashes, fingerprints, and value fields. All of the information contained in a `MolDocScheme` object can be used directly to generate documents for molecules:" ] }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -105,35 +105,34 @@ " 'index': 'YXFVVABEGXRONW-UHFFFAOYSA-N',\n", " 'smiles': 'Cc1ccccc1',\n", " 'scheme': 'default',\n", - " 'hashes': {'inchi_standard': 'InChI=1S/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", - " 'inchikey_KET_15T': 'YXFVVABEGXRONW-UHFFFAOYNA-N',\n", - " 'noiso_smiles': 'Cc1ccccc1',\n", - " 'MoleculeHashString': '100-7-7-SaZjmQ-zcSDYw-aXeP/g-122pug-haQS5A-qxXe4Q',\n", - " 'inchi_KET_15T': 'InChI=1/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", + " 'hashes': {'MolFormula': 'C7H8',\n", + " 'SmallWorldIndexBRL': 'B7R1L5',\n", + " 'AtomBondCounts': '7,7',\n", + " 'cx_smiles': 'Cc1ccccc1',\n", + " 'NetCharge': '0',\n", + " 'CanonicalSmiles': 'Cc1ccccc1',\n", " 'inchikey_standard': 'YXFVVABEGXRONW-UHFFFAOYSA-N',\n", - " 'cx_smiles': 'Cc1ccccc1'},\n", - " 'rdkit_hashes': {'Mesomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", - " 'HetAtomProtomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", + " 'inchikey_KET_15T': 'YXFVVABEGXRONW-UHFFFAOYNA-N',\n", + " 'SmallWorldIndexBR': 'B7R1',\n", + " 'DegreeVector': '0,1,5,1',\n", + " 'ElementGraph': 'CC1CCCCC1',\n", + " 'HetAtomTautomer': 'C[C]1[CH][CH][CH][CH][CH]1_0_0',\n", + " 'inchi_standard': 'InChI=1S/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", + " 'RedoxPair': 'C[C]1[CH][CH][CH][CH][CH]1',\n", + " 'AnonymousGraph': '**1*****1',\n", + " 'Mesomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", " 'Regioisomer': '*C.c1ccccc1',\n", + " 'inchi_KET_15T': 'InChI=1/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", " 'MurckoScaffold': 'c1ccccc1',\n", " 'ArthorSubstructureOrder': '00070007010007000000002a000000',\n", + " 'noiso_smiles': 'Cc1ccccc1',\n", " 'ExtendedMurcko': '*c1ccccc1',\n", - " 'DegreeVector': '0,1,5,1',\n", - " 'RedoxPair': 'C[C]1[CH][CH][CH][CH][CH]1',\n", - " 'SmallWorldIndexBR': 'B7R1',\n", - " 'MolFormula': 'C7H8',\n", - " 'AtomBondCounts': '7,7',\n", - " 'ElementGraph': 'CC1CCCCC1',\n", - " 'CanonicalSmiles': 'Cc1ccccc1',\n", - " 'SmallWorldIndexBRL': 'B7R1L5',\n", - " 'HetAtomTautomer': 'C[C]1[CH][CH][CH][CH][CH]1_0_0',\n", - " 'NetCharge': '0',\n", - " 'AnonymousGraph': '**1*****1'},\n", + " 'HetAtomProtomer': 'C[C]1[CH][CH][CH][CH][CH]1_0'},\n", " 'fingerprints': {},\n", " 'value_data': {}}" ] }, - "execution_count": 23, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -153,9 +152,16 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 4, "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "removed AnonymousGraph from scheme\n" + ] + }, { "data": { "text/plain": [ @@ -163,34 +169,33 @@ " 'index': 'C7H8',\n", " 'smiles': 'Cc1ccccc1',\n", " 'scheme': 'default',\n", - " 'hashes': {'inchi_standard': 'InChI=1S/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", - " 'inchikey_KET_15T': 'YXFVVABEGXRONW-UHFFFAOYNA-N',\n", - " 'noiso_smiles': 'Cc1ccccc1',\n", - " 'MoleculeHashString': '100-7-7-SaZjmQ-zcSDYw-aXeP/g-122pug-haQS5A-qxXe4Q',\n", - " 'inchi_KET_15T': 'InChI=1/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", + " 'hashes': {'MolFormula': 'C7H8',\n", + " 'SmallWorldIndexBRL': 'B7R1L5',\n", + " 'AtomBondCounts': '7,7',\n", + " 'cx_smiles': 'Cc1ccccc1',\n", + " 'NetCharge': '0',\n", + " 'CanonicalSmiles': 'Cc1ccccc1',\n", " 'inchikey_standard': 'YXFVVABEGXRONW-UHFFFAOYSA-N',\n", - " 'cx_smiles': 'Cc1ccccc1'},\n", - " 'rdkit_hashes': {'Mesomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", - " 'HetAtomProtomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", + " 'inchikey_KET_15T': 'YXFVVABEGXRONW-UHFFFAOYNA-N',\n", + " 'SmallWorldIndexBR': 'B7R1',\n", + " 'DegreeVector': '0,1,5,1',\n", + " 'ElementGraph': 'CC1CCCCC1',\n", + " 'HetAtomTautomer': 'C[C]1[CH][CH][CH][CH][CH]1_0_0',\n", + " 'inchi_standard': 'InChI=1S/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", + " 'RedoxPair': 'C[C]1[CH][CH][CH][CH][CH]1',\n", + " 'Mesomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", " 'Regioisomer': '*C.c1ccccc1',\n", + " 'inchi_KET_15T': 'InChI=1/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", " 'MurckoScaffold': 'c1ccccc1',\n", " 'ArthorSubstructureOrder': '00070007010007000000002a000000',\n", + " 'noiso_smiles': 'Cc1ccccc1',\n", " 'ExtendedMurcko': '*c1ccccc1',\n", - " 'DegreeVector': '0,1,5,1',\n", - " 'RedoxPair': 'C[C]1[CH][CH][CH][CH][CH]1',\n", - " 'SmallWorldIndexBR': 'B7R1',\n", - " 'MolFormula': 'C7H8',\n", - " 'AtomBondCounts': '7,7',\n", - " 'ElementGraph': 'CC1CCCCC1',\n", - " 'CanonicalSmiles': 'Cc1ccccc1',\n", - " 'SmallWorldIndexBRL': 'B7R1L5',\n", - " 'HetAtomTautomer': 'C[C]1[CH][CH][CH][CH][CH]1_0_0',\n", - " 'NetCharge': '0'},\n", + " 'HetAtomProtomer': 'C[C]1[CH][CH][CH][CH][CH]1_0'},\n", " 'fingerprints': {},\n", " 'value_data': {}}" ] }, - "execution_count": 24, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -220,7 +225,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -234,91 +239,91 @@ "name": "stderr", "output_type": "stream", "text": [ - "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:51] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:03:51] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", - "RDKit WARNING: [22:05:23] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n" + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [15:39:46] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n" ] }, { @@ -335,7 +340,7 @@ "200" ] }, - "execution_count": 28, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -356,7 +361,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -370,97 +375,95 @@ "name": "stderr", "output_type": "stream", "text": [ - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n" + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:48] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:48] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [15:39:50] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n" ] }, { @@ -477,7 +480,7 @@ "100" ] }, - "execution_count": 30, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -519,13 +522,29 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "{'MoleculeHashString': ,\n", + "{'AnonymousGraph': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.AnonymousGraph)>,\n", + " 'ElementGraph': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.ElementGraph)>,\n", + " 'CanonicalSmiles': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.CanonicalSmiles)>,\n", + " 'MurckoScaffold': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.MurckoScaffold)>,\n", + " 'ExtendedMurcko': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.ExtendedMurcko)>,\n", + " 'MolFormula': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.MolFormula)>,\n", + " 'AtomBondCounts': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.AtomBondCounts)>,\n", + " 'DegreeVector': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.DegreeVector)>,\n", + " 'Mesomer': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.Mesomer)>,\n", + " 'HetAtomTautomer': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.HetAtomTautomer)>,\n", + " 'HetAtomProtomer': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.HetAtomProtomer)>,\n", + " 'RedoxPair': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.RedoxPair)>,\n", + " 'Regioisomer': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.Regioisomer)>,\n", + " 'NetCharge': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.NetCharge)>,\n", + " 'SmallWorldIndexBR': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.SmallWorldIndexBR)>,\n", + " 'SmallWorldIndexBRL': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.SmallWorldIndexBRL)>,\n", + " 'ArthorSubstructureOrder': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.ArthorSubstructureOrder)>,\n", " 'inchi_standard': ,\n", " 'inchikey_standard': ,\n", " 'inchi_KET_15T': (rdmol)>,\n", @@ -534,7 +553,7 @@ " 'cx_smiles': }" ] }, - "execution_count": 31, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -543,42 +562,6 @@ "registration.HASH_FUNCTIONS" ] }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'AnonymousGraph': rdkit.Chem.rdMolHash.HashFunction.AnonymousGraph,\n", - " 'ElementGraph': rdkit.Chem.rdMolHash.HashFunction.ElementGraph,\n", - " 'CanonicalSmiles': rdkit.Chem.rdMolHash.HashFunction.CanonicalSmiles,\n", - " 'MurckoScaffold': rdkit.Chem.rdMolHash.HashFunction.MurckoScaffold,\n", - " 'ExtendedMurcko': rdkit.Chem.rdMolHash.HashFunction.ExtendedMurcko,\n", - " 'MolFormula': rdkit.Chem.rdMolHash.HashFunction.MolFormula,\n", - " 'AtomBondCounts': rdkit.Chem.rdMolHash.HashFunction.AtomBondCounts,\n", - " 'DegreeVector': rdkit.Chem.rdMolHash.HashFunction.DegreeVector,\n", - " 'Mesomer': rdkit.Chem.rdMolHash.HashFunction.Mesomer,\n", - " 'HetAtomTautomer': rdkit.Chem.rdMolHash.HashFunction.HetAtomTautomer,\n", - " 'HetAtomProtomer': rdkit.Chem.rdMolHash.HashFunction.HetAtomProtomer,\n", - " 'RedoxPair': rdkit.Chem.rdMolHash.HashFunction.RedoxPair,\n", - " 'Regioisomer': rdkit.Chem.rdMolHash.HashFunction.Regioisomer,\n", - " 'NetCharge': rdkit.Chem.rdMolHash.HashFunction.NetCharge,\n", - " 'SmallWorldIndexBR': rdkit.Chem.rdMolHash.HashFunction.SmallWorldIndexBR,\n", - " 'SmallWorldIndexBRL': rdkit.Chem.rdMolHash.HashFunction.SmallWorldIndexBRL,\n", - " 'ArthorSubstructureOrder': rdkit.Chem.rdMolHash.HashFunction.ArthorSubstructureOrder}" - ] - }, - "execution_count": 32, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "registration.RDKIT_HASH_FUNCTIONS" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -591,7 +574,6 @@ "self.author = DEFAULT_AUTHOR\n", "self.pre_processed = DEFAULT_PREPROCESS\n", "self.index_option = DEFAULT_INDEX\n", - "self.rdkit_hashes = set(RDKIT_HASH_FUNCTIONS.keys())\n", "self.hashes = set(HASH_FUNCTIONS.keys())\n", "self.fingerprints = {}\n", "self.value_fields = {}\n", @@ -616,10 +598,17 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "mongordkit.Database.write.**WriteFromSDF**(database, sdf, scheme=MolDocScheme(), reg_collection=None, chunk_size=100, limit=None) --> *int: number of molecules imported*\n", + "mongordkit.Database.write.**WriteFromSDF**(database, sdf, scheme=MolDocScheme(), reg_collection=None, chunk_size=100, limit=None, warnings=False (*Make this true to turn on rdkit warnings*) --> *int: number of molecules imported*\n", "\n", "mongordkit.Database.write.**WriteFromMolList**(database, list, scheme=MolDocScheme(), reg_collection=None, chunk_size=100, limit=None) --> *int: number of molecules imported*" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/docs/notebooks/.ipynb_checkpoints/Similarity Testing-checkpoint.ipynb b/docs/notebooks/.ipynb_checkpoints/Similarity Testing-checkpoint.ipynb deleted file mode 100644 index c2a351f..0000000 --- a/docs/notebooks/.ipynb_checkpoints/Similarity Testing-checkpoint.ipynb +++ /dev/null @@ -1,244 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Similarity Search Benchmarking" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import mongordkit\n", - "import time\n", - "import pymongo\n", - "import rdkit\n", - "import matplotlib\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "import pandas as pd\n", - "from rdkit import Chem\n", - "from statistics import mean\n", - "import mongomock\n", - "from rdkit.Chem import AllChem\n", - "from mongordkit.Database import write\n", - "from mongordkit.Search import similarity" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "populating mongodb collection with compounds from chembl...\n", - "inserted chunk...\n", - "inserted chunk...\n", - "200 molecules successfully imported\n" - ] - }, - { - "data": { - "text/plain": [ - "200" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "#Create a mongomock database instance and write to it. \n", - "client = mongomock.MongoClient()\n", - "db = client.db\n", - "\n", - "#Write 200 molecules into the database\n", - "write.writeFromSDF(db, '../../data/test_data/first_200.props.sdf', 'test')" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "#Add Morgan fingerprints into the database\n", - "similarity.addMorganFingerprints(db)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[[1.0, 'CC1=CC(=O)C=CC1=O']]" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "#Check that similarity search is working, at least for one molecule. \n", - "doc = db.molecules.find_one()\n", - "m = Chem.Mol(doc['rdmol'])\n", - "results = similarity.similaritySearch(m, db, .8)\n", - "results" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "populating mongodb collection with compounds from chembl...\n", - "The specified setting does not exist. Will only insert default molecules\n", - "inserted chunk...\n", - "inserted chunk...\n", - "1000 molecules successfully imported\n" - ] - }, - { - "data": { - "text/plain": [ - "1000" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "#Create a regular mongoDB database instance and write the first 1000 molecules to it. \n", - "client = pymongo.MongoClient()\n", - "db = client.db\n", - "db.molecules.drop()\n", - "db.mfp_counts.drop()\n", - "write.writeFromSDF(db, '../../../chembl_27.sdf', 'test', reg_option='inchikey', index_option='inchikey', chunk_size=500, limit=500)" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [], - "source": [ - "similarity.addMorganFingerprints(db)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Measuring performance for similarity threshold 0.7.\n" - ] - } - ], - "source": [ - "#Run benchmarks for similarity search with and without aggregation parameters. \n", - "thresholds = [0.7, 0.75, 0.8, 0.85, 0.9, 0.95]\n", - "times = []\n", - "repetitions = 5\n", - "for t in thresholds: \n", - " print(\"Measuring performance for similarity threshold {}.\".format(t))\n", - " temp_times = []\n", - " for r in range(repetitions):\n", - " start = time.time()\n", - " for m in db.molecules.find():\n", - " mol = Chem.Mol(m['rdmol'])\n", - " similarity.similaritySearchAggregate(mol, db, t)\n", - " print('working')\n", - " end = time.time()\n", - " temp_times.append(end - start)\n", - " times.append([t, mean(temp_times)])\n", - "print(times)" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "x_list = [v[0] for v in times]\n", - "y_list = [v[1]*1000 for v in times]\n", - "plt.xlabel('thresholds')\n", - "plt.ylabel('time (ms)')\n", - "plt.plot(x_list, y_list)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "py37_rdkit_beta", - "language": "python", - "name": "py37_rdkit_beta" - }, - "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.7.7" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/docs/notebooks/.ipynb_checkpoints/Similarity and Substructure Search-checkpoint.ipynb b/docs/notebooks/.ipynb_checkpoints/Similarity and Substructure Search-checkpoint.ipynb index 34d092f..82c3f12 100644 --- a/docs/notebooks/.ipynb_checkpoints/Similarity and Substructure Search-checkpoint.ipynb +++ b/docs/notebooks/.ipynb_checkpoints/Similarity and Substructure Search-checkpoint.ipynb @@ -6,7 +6,7 @@ "source": [ "# Similarity and Substructure Search\n", "\n", - "Last updated: 7/27/20\n", + "Last updated: 8/11/20\n", "\n", "Methods for similarity and substructure search are included in the `mongordkit.Search` module." ] @@ -63,104 +63,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "populating mongodb collection with compounds from SDF...\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", - "RDKit WARNING: [22:56:20] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ + "populating mongodb collection with compounds from SDF...\n", "200 molecules successfully imported\n", "0 duplicates skipped\n", "Preparing database and collections for search...\n", @@ -182,7 +85,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -211,11 +114,219 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "populating mongodb collection with compounds from SDF...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [15:43:38] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:40] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:40] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:40] WARNING: Omitted undefined stereo\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "200 molecules successfully imported\n", + "0 duplicates skipped\n" + ] + }, + { + "data": { + "text/plain": [ + "200" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf')" ] @@ -232,7 +343,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -241,9 +352,36 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "{'bits': [84,\n", + " 314,\n", + " 356,\n", + " 547,\n", + " 650,\n", + " 747,\n", + " 967,\n", + " 1057,\n", + " 1080,\n", + " 1154,\n", + " 1337,\n", + " 1380,\n", + " 1722,\n", + " 1768,\n", + " 1873,\n", + " 1877],\n", + " 'count': 16}" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "demo_db.molecules.find_one()['fingerprints']['morgan_fp']" ] @@ -257,17 +395,28 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "similaritySearch: [[0.4117647058823529, 'WLHCBQAPPJAULW-UHFFFAOYSA-N']]\n", + "\n", + "\n", + "similaritySearchAggregate: [[0.4117647058823529, 'WLHCBQAPPJAULW-UHFFFAOYSA-N']]\n" + ] + } + ], "source": [ "q_mol = Chem.MolFromSmiles('Cc1ccccc1')\n", "\n", "# Perform a similarity search on TestDB for q_mol with a Tanimoto threshold of 0.4. \n", - "results1 = similarity.SimSearch(q_mol, demo_db.molecules, demo_db.mfp_counts, 0.8)\n", + "results1 = similarity.SimSearch(q_mol, demo_db.molecules, demo_db.mfp_counts, 0.4)\n", "\n", "# Do the same thing, but use the MongoDB Aggregation Pipeline. \n", - "results2 = similarity.SimSearchAggregate(q_mol, demo_db.molecules, demo_db.mfp_counts, 0.8)\n", + "results2 = similarity.SimSearchAggregate(q_mol, demo_db.molecules, demo_db.mfp_counts, 0.4)\n", "\n", "print('similaritySearch: {}'.format(results1))\n", "print('\\n')\n", @@ -285,7 +434,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -309,13 +458,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "similaritySearchLSH: []\n" + ] + } + ], "source": [ "q_mol = Chem.MolFromSmiles('Cc1ccccc1')\n", "\n", - "results3 = similarity.SimSearchLSH(q_mol, demo_db, demo_db.molecules, demo_db.permutations, threshold=0.8)\n", + "results3 = similarity.SimSearchLSH(q_mol, demo_db, demo_db.molecules, \n", + " demo_db.permutations, demo_db.mfp_counts, threshold=0.8)\n", "\n", "print('similaritySearchLSH: {}'.format(results3))" ] @@ -340,9 +498,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "['RUTYZGCHBCCSKD-UHFFFAOYSA-N',\n", + " 'WECJUPODCKXNQK-UHFFFAOYSA-N',\n", + " 'GZZJZWYIOOPHOV-UHFFFAOYSA-N',\n", + " 'FXOSHPAYNZBSFO-RMKNXTFCSA-N',\n", + " 'KWLUBKHLCNCFQI-UHFFFAOYSA-N',\n", + " 'VDAJDWUTRXNYMU-RUDMXATFSA-N',\n", + " 'PACGLQCRGWFBJH-UHFFFAOYSA-N',\n", + " 'CDCRUVGWQJYTFO-UHFFFAOYSA-N']" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "q_mol = Chem.MolFromSmiles('C1=CC=CC=C1OC')\n", "\n", @@ -359,9 +535,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "['RUTYZGCHBCCSKD-UHFFFAOYSA-N',\n", + " 'WECJUPODCKXNQK-UHFFFAOYSA-N',\n", + " 'GZZJZWYIOOPHOV-UHFFFAOYSA-N',\n", + " 'FXOSHPAYNZBSFO-RMKNXTFCSA-N',\n", + " 'KWLUBKHLCNCFQI-UHFFFAOYSA-N',\n", + " 'VDAJDWUTRXNYMU-RUDMXATFSA-N',\n", + " 'PACGLQCRGWFBJH-UHFFFAOYSA-N',\n", + " 'CDCRUVGWQJYTFO-UHFFFAOYSA-N']" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "substructure.AddPatternFingerprints(demo_db.molecules)\n", "substructure.SubSearch(q_mol, demo_db.molecules, chirality=False)" @@ -410,7 +604,7 @@ "\n", "mongordkit.Search.similarity.**AddHashCollections**(db (*MongoDB database*), mol_collection (*MongoDB collection*)) --> None\n", "\n", - "mongordkit.Search.similarity.**SimSearchLSH**(mol (*rdmol object*), db (*MongoDB database containing hash collections*), mol_collection (*MongoDB collection*), perm_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, index]*" + "mongordkit.Search.similarity.**SimSearchLSH**(mol (*rdmol object*), db (*MongoDB database containing hash collections*), mol_collection (*MongoDB collection*), perm_collection (*MongoDB collection*), count_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, index]*" ] }, { diff --git a/docs/notebooks/Creating and Writing to MongoDB.ipynb b/docs/notebooks/Creating and Writing to MongoDB.ipynb index aec730f..c581d97 100644 --- a/docs/notebooks/Creating and Writing to MongoDB.ipynb +++ b/docs/notebooks/Creating and Writing to MongoDB.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -35,7 +35,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -88,14 +88,14 @@ "## Data Registration\n", "`Database.registration` constructs document representations of molecules according to configurable schemes and handles data registration settings.\n", "\n", - "It does this in two parts. First, it defines the global variables `RDKIT_HASH_FUNCTIONS` and `HASH_FUNCTIONS` as dictionaries that hold map hash function names to methods. It also defines the global variables `DEFAULT_SCHEME_NAME`, `DEFAULT_AUTHOR`, `DEFAULT_PREPROCESS`, and `DEFAULT_INDEX`, which are used in scheme creation and are thus defined for easy configuration. \n", + "It does this in two parts. First, it defines the global variable `HASH_FUNCTIONS` as a dictionary that maps hash function names to methods. It also defines the global variables `DEFAULT_SCHEME_NAME`, `DEFAULT_AUTHOR`, `DEFAULT_PREPROCESS`, and `DEFAULT_INDEX`, which are used in scheme creation and are thus defined for easy configuration. \n", "\n", "Second, the file defines the `MolDocScheme` object, which stores scheme information in its instance variables and is passed into `.write` methods in order to specify molecule document format. By default, `MolDocScheme` includes scheme name, author, whether or not the molecule has been pre-processed, an index option, hashes, fingerprints, and value fields. All of the information contained in a `MolDocScheme` object can be used directly to generate documents for molecules:" ] }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -105,35 +105,34 @@ " 'index': 'YXFVVABEGXRONW-UHFFFAOYSA-N',\n", " 'smiles': 'Cc1ccccc1',\n", " 'scheme': 'default',\n", - " 'hashes': {'inchi_standard': 'InChI=1S/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", - " 'inchikey_KET_15T': 'YXFVVABEGXRONW-UHFFFAOYNA-N',\n", - " 'noiso_smiles': 'Cc1ccccc1',\n", - " 'MoleculeHashString': '100-7-7-SaZjmQ-zcSDYw-aXeP/g-122pug-haQS5A-qxXe4Q',\n", - " 'inchi_KET_15T': 'InChI=1/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", + " 'hashes': {'MolFormula': 'C7H8',\n", + " 'SmallWorldIndexBRL': 'B7R1L5',\n", + " 'AtomBondCounts': '7,7',\n", + " 'cx_smiles': 'Cc1ccccc1',\n", + " 'NetCharge': '0',\n", + " 'CanonicalSmiles': 'Cc1ccccc1',\n", " 'inchikey_standard': 'YXFVVABEGXRONW-UHFFFAOYSA-N',\n", - " 'cx_smiles': 'Cc1ccccc1'},\n", - " 'rdkit_hashes': {'Mesomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", - " 'HetAtomProtomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", + " 'inchikey_KET_15T': 'YXFVVABEGXRONW-UHFFFAOYNA-N',\n", + " 'SmallWorldIndexBR': 'B7R1',\n", + " 'DegreeVector': '0,1,5,1',\n", + " 'ElementGraph': 'CC1CCCCC1',\n", + " 'HetAtomTautomer': 'C[C]1[CH][CH][CH][CH][CH]1_0_0',\n", + " 'inchi_standard': 'InChI=1S/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", + " 'RedoxPair': 'C[C]1[CH][CH][CH][CH][CH]1',\n", + " 'AnonymousGraph': '**1*****1',\n", + " 'Mesomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", " 'Regioisomer': '*C.c1ccccc1',\n", + " 'inchi_KET_15T': 'InChI=1/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", " 'MurckoScaffold': 'c1ccccc1',\n", " 'ArthorSubstructureOrder': '00070007010007000000002a000000',\n", + " 'noiso_smiles': 'Cc1ccccc1',\n", " 'ExtendedMurcko': '*c1ccccc1',\n", - " 'DegreeVector': '0,1,5,1',\n", - " 'RedoxPair': 'C[C]1[CH][CH][CH][CH][CH]1',\n", - " 'SmallWorldIndexBR': 'B7R1',\n", - " 'MolFormula': 'C7H8',\n", - " 'AtomBondCounts': '7,7',\n", - " 'ElementGraph': 'CC1CCCCC1',\n", - " 'CanonicalSmiles': 'Cc1ccccc1',\n", - " 'SmallWorldIndexBRL': 'B7R1L5',\n", - " 'HetAtomTautomer': 'C[C]1[CH][CH][CH][CH][CH]1_0_0',\n", - " 'NetCharge': '0',\n", - " 'AnonymousGraph': '**1*****1'},\n", + " 'HetAtomProtomer': 'C[C]1[CH][CH][CH][CH][CH]1_0'},\n", " 'fingerprints': {},\n", " 'value_data': {}}" ] }, - "execution_count": 23, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -153,9 +152,16 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 4, "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "removed AnonymousGraph from scheme\n" + ] + }, { "data": { "text/plain": [ @@ -163,34 +169,33 @@ " 'index': 'C7H8',\n", " 'smiles': 'Cc1ccccc1',\n", " 'scheme': 'default',\n", - " 'hashes': {'inchi_standard': 'InChI=1S/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", - " 'inchikey_KET_15T': 'YXFVVABEGXRONW-UHFFFAOYNA-N',\n", - " 'noiso_smiles': 'Cc1ccccc1',\n", - " 'MoleculeHashString': '100-7-7-SaZjmQ-zcSDYw-aXeP/g-122pug-haQS5A-qxXe4Q',\n", - " 'inchi_KET_15T': 'InChI=1/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", + " 'hashes': {'MolFormula': 'C7H8',\n", + " 'SmallWorldIndexBRL': 'B7R1L5',\n", + " 'AtomBondCounts': '7,7',\n", + " 'cx_smiles': 'Cc1ccccc1',\n", + " 'NetCharge': '0',\n", + " 'CanonicalSmiles': 'Cc1ccccc1',\n", " 'inchikey_standard': 'YXFVVABEGXRONW-UHFFFAOYSA-N',\n", - " 'cx_smiles': 'Cc1ccccc1'},\n", - " 'rdkit_hashes': {'Mesomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", - " 'HetAtomProtomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", + " 'inchikey_KET_15T': 'YXFVVABEGXRONW-UHFFFAOYNA-N',\n", + " 'SmallWorldIndexBR': 'B7R1',\n", + " 'DegreeVector': '0,1,5,1',\n", + " 'ElementGraph': 'CC1CCCCC1',\n", + " 'HetAtomTautomer': 'C[C]1[CH][CH][CH][CH][CH]1_0_0',\n", + " 'inchi_standard': 'InChI=1S/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", + " 'RedoxPair': 'C[C]1[CH][CH][CH][CH][CH]1',\n", + " 'Mesomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", " 'Regioisomer': '*C.c1ccccc1',\n", + " 'inchi_KET_15T': 'InChI=1/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", " 'MurckoScaffold': 'c1ccccc1',\n", " 'ArthorSubstructureOrder': '00070007010007000000002a000000',\n", + " 'noiso_smiles': 'Cc1ccccc1',\n", " 'ExtendedMurcko': '*c1ccccc1',\n", - " 'DegreeVector': '0,1,5,1',\n", - " 'RedoxPair': 'C[C]1[CH][CH][CH][CH][CH]1',\n", - " 'SmallWorldIndexBR': 'B7R1',\n", - " 'MolFormula': 'C7H8',\n", - " 'AtomBondCounts': '7,7',\n", - " 'ElementGraph': 'CC1CCCCC1',\n", - " 'CanonicalSmiles': 'Cc1ccccc1',\n", - " 'SmallWorldIndexBRL': 'B7R1L5',\n", - " 'HetAtomTautomer': 'C[C]1[CH][CH][CH][CH][CH]1_0_0',\n", - " 'NetCharge': '0'},\n", + " 'HetAtomProtomer': 'C[C]1[CH][CH][CH][CH][CH]1_0'},\n", " 'fingerprints': {},\n", " 'value_data': {}}" ] }, - "execution_count": 24, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -220,7 +225,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -234,91 +239,91 @@ "name": "stderr", "output_type": "stream", "text": [ - "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:51] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:03:51] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:51] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:03:52] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:23] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", - "RDKit WARNING: [22:05:23] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n" + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:46] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [15:39:46] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n" ] }, { @@ -335,7 +340,7 @@ "200" ] }, - "execution_count": 28, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -356,7 +361,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -370,97 +375,95 @@ "name": "stderr", "output_type": "stream", "text": [ - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:05:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:20] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:20] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:12:21] WARNING: Charges were rearranged\n" + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:48] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:48] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:39:50] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [15:39:50] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n" ] }, { @@ -477,7 +480,7 @@ "100" ] }, - "execution_count": 30, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -519,13 +522,29 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "{'MoleculeHashString': ,\n", + "{'AnonymousGraph': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.AnonymousGraph)>,\n", + " 'ElementGraph': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.ElementGraph)>,\n", + " 'CanonicalSmiles': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.CanonicalSmiles)>,\n", + " 'MurckoScaffold': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.MurckoScaffold)>,\n", + " 'ExtendedMurcko': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.ExtendedMurcko)>,\n", + " 'MolFormula': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.MolFormula)>,\n", + " 'AtomBondCounts': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.AtomBondCounts)>,\n", + " 'DegreeVector': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.DegreeVector)>,\n", + " 'Mesomer': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.Mesomer)>,\n", + " 'HetAtomTautomer': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.HetAtomTautomer)>,\n", + " 'HetAtomProtomer': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.HetAtomProtomer)>,\n", + " 'RedoxPair': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.RedoxPair)>,\n", + " 'Regioisomer': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.Regioisomer)>,\n", + " 'NetCharge': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.NetCharge)>,\n", + " 'SmallWorldIndexBR': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.SmallWorldIndexBR)>,\n", + " 'SmallWorldIndexBRL': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.SmallWorldIndexBRL)>,\n", + " 'ArthorSubstructureOrder': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.ArthorSubstructureOrder)>,\n", " 'inchi_standard': ,\n", " 'inchikey_standard': ,\n", " 'inchi_KET_15T': (rdmol)>,\n", @@ -534,7 +553,7 @@ " 'cx_smiles': }" ] }, - "execution_count": 31, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -543,42 +562,6 @@ "registration.HASH_FUNCTIONS" ] }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'AnonymousGraph': rdkit.Chem.rdMolHash.HashFunction.AnonymousGraph,\n", - " 'ElementGraph': rdkit.Chem.rdMolHash.HashFunction.ElementGraph,\n", - " 'CanonicalSmiles': rdkit.Chem.rdMolHash.HashFunction.CanonicalSmiles,\n", - " 'MurckoScaffold': rdkit.Chem.rdMolHash.HashFunction.MurckoScaffold,\n", - " 'ExtendedMurcko': rdkit.Chem.rdMolHash.HashFunction.ExtendedMurcko,\n", - " 'MolFormula': rdkit.Chem.rdMolHash.HashFunction.MolFormula,\n", - " 'AtomBondCounts': rdkit.Chem.rdMolHash.HashFunction.AtomBondCounts,\n", - " 'DegreeVector': rdkit.Chem.rdMolHash.HashFunction.DegreeVector,\n", - " 'Mesomer': rdkit.Chem.rdMolHash.HashFunction.Mesomer,\n", - " 'HetAtomTautomer': rdkit.Chem.rdMolHash.HashFunction.HetAtomTautomer,\n", - " 'HetAtomProtomer': rdkit.Chem.rdMolHash.HashFunction.HetAtomProtomer,\n", - " 'RedoxPair': rdkit.Chem.rdMolHash.HashFunction.RedoxPair,\n", - " 'Regioisomer': rdkit.Chem.rdMolHash.HashFunction.Regioisomer,\n", - " 'NetCharge': rdkit.Chem.rdMolHash.HashFunction.NetCharge,\n", - " 'SmallWorldIndexBR': rdkit.Chem.rdMolHash.HashFunction.SmallWorldIndexBR,\n", - " 'SmallWorldIndexBRL': rdkit.Chem.rdMolHash.HashFunction.SmallWorldIndexBRL,\n", - " 'ArthorSubstructureOrder': rdkit.Chem.rdMolHash.HashFunction.ArthorSubstructureOrder}" - ] - }, - "execution_count": 32, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "registration.RDKIT_HASH_FUNCTIONS" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -591,7 +574,6 @@ "self.author = DEFAULT_AUTHOR\n", "self.pre_processed = DEFAULT_PREPROCESS\n", "self.index_option = DEFAULT_INDEX\n", - "self.rdkit_hashes = set(RDKIT_HASH_FUNCTIONS.keys())\n", "self.hashes = set(HASH_FUNCTIONS.keys())\n", "self.fingerprints = {}\n", "self.value_fields = {}\n", @@ -616,10 +598,17 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "mongordkit.Database.write.**WriteFromSDF**(database, sdf, scheme=MolDocScheme(), reg_collection=None, chunk_size=100, limit=None) --> *int: number of molecules imported*\n", + "mongordkit.Database.write.**WriteFromSDF**(database, sdf, scheme=MolDocScheme(), reg_collection=None, chunk_size=100, limit=None, warnings=False (*Make this true to turn on rdkit warnings*) --> *int: number of molecules imported*\n", "\n", "mongordkit.Database.write.**WriteFromMolList**(database, list, scheme=MolDocScheme(), reg_collection=None, chunk_size=100, limit=None) --> *int: number of molecules imported*" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/docs/notebooks/Explore LSH.ipynb b/docs/notebooks/Explore LSH.ipynb deleted file mode 100644 index ed142b5..0000000 --- a/docs/notebooks/Explore LSH.ipynb +++ /dev/null @@ -1,284 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Exploring Locality Sensitive Hashing" - ] - }, - { - "cell_type": "code", - "execution_count": 56, - "metadata": {}, - "outputs": [], - "source": [ - "# Imports\n", - "\n", - "import numpy as np\n", - "from rdkit import Chem\n", - "from rdkit.Chem import AllChem\n", - "import sys\n", - "import functools\n", - "import mongomock" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "# Permutation function\n", - "\n", - "def get_permutations(len_permutations=2048, num_permutations=100):\n", - " return map(lambda _: np.random.permutation(2048), range(num_permutations))" - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "metadata": {}, - "outputs": [], - "source": [ - "permutations = get_permutations()" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": {}, - "outputs": [], - "source": [ - "def get_min_hash(mol, permutations):\n", - " qfp = list(AllChem.GetMorganFingerprintAsBitVect(mol, 2, nBits=2048))\n", - " min_hash = []\n", - " for perm in permutations:\n", - " for idx, i in enumerate(perm):\n", - " if qfp_bits[i]:\n", - " min_hash.append(idx)\n", - " break \n", - " return min_hash" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [], - "source": [ - "mol = Chem.MolFromSmiles('C1=CC=CC=C1OC')\n", - "min_hash = get_min_hash(mol, permutations)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 54, - "metadata": {}, - "outputs": [], - "source": [ - "def hash_to_buckets(min_hash, num_buckets=25, nBits=2048):\n", - " if len(min_hash) % num_buckets:\n", - " raise Exception('number of buckets must be divisiable by the hash length')\n", - " buckets = []\n", - " hash_per_bucket = int(len(min_hash) / num_buckets)\n", - " num_bits = (nBits-1).bit_length()\n", - "# if num_bits * hash_per_bucket > sys.maxint.bit_length():\n", - "# raise Exception('numbers are too large to produce valid buckets')\n", - " for b in range(num_buckets):\n", - " buckets.append(functools.reduce(lambda x,y: (x << num_bits) + y, min_hash[b:(b + hash_per_bucket)]))\n", - " return buckets" - ] - }, - { - "cell_type": "code", - "execution_count": 55, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[250056202389,\n", - " 1941707205052,\n", - " 782309908621,\n", - " 1281762813978,\n", - " 3814522409145,\n", - " 1211290208280,\n", - " 224114294943,\n", - " 1589238888575,\n", - " 206825584784,\n", - " 1366332571687,\n", - " 1091525753125,\n", - " 1237114759205,\n", - " 336236456125,\n", - " 2517006411838,\n", - " 318620430363,\n", - " 1623757740190,\n", - " 532689514536,\n", - " 232591015954,\n", - " 1357377474657,\n", - " 343673079808,\n", - " 155025670508,\n", - " 833224401069,\n", - " 1527081060,\n", - " 3127462010894,\n", - " 1486478143488]" - ] - }, - "execution_count": 55, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "hash_to_buckets(min_hash)" - ] - }, - { - "cell_type": "code", - "execution_count": 57, - "metadata": {}, - "outputs": [], - "source": [ - "client = mongomock.MongoClient()" - ] - }, - { - "cell_type": "code", - "execution_count": 58, - "metadata": {}, - "outputs": [], - "source": [ - "db = client.db" - ] - }, - { - "cell_type": "code", - "execution_count": 59, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 59, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "db.list_collection_names()" - ] - }, - { - "cell_type": "code", - "execution_count": 60, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 60, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "db.molecules.insert_one({'_id': 1, 'molecule': 'boom'})" - ] - }, - { - "cell_type": "code", - "execution_count": 61, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['molecules']" - ] - }, - "execution_count": 61, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "db.list_collection_names()" - ] - }, - { - "cell_type": "code", - "execution_count": 62, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 62, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "db.molecules.find()" - ] - }, - { - "cell_type": "code", - "execution_count": 63, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'_id': 1, 'molecule': 'boom'}" - ] - }, - "execution_count": 63, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "db.molecules.find_one()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "py37_rdkit_beta", - "language": "python", - "name": "py37_rdkit_beta" - }, - "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.7.7" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/docs/notebooks/Exploring Multiprocessing.ipynb b/docs/notebooks/Exploring Multiprocessing.ipynb deleted file mode 100644 index 300afb8..0000000 --- a/docs/notebooks/Exploring Multiprocessing.ipynb +++ /dev/null @@ -1,340 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "import pymongo\n", - "import rdkit\n", - "import math\n", - "from rdkit import Chem\n", - "from rdkit.Chem import AllChem\n", - "from rdkit.Chem.rdmolops import PatternFingerprint\n", - "from mongordkit.Database import write\n", - "from mongordkit import Search" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "client = pymongo.MongoClient()\n", - "db = client['multip']\n", - "molecules = db.molecules" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "write.writeFromSDF(db.molecules, '../../data/test_data/first_200.props.sdf', 'test')" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[ObjectId('5f22bce9ad3e9621e4119c64'),\n", - " ObjectId('5f22bce9ad3e9621e4119c65'),\n", - " ObjectId('5f22bce9ad3e9621e4119c66'),\n", - " ObjectId('5f22bce9ad3e9621e4119c67'),\n", - " ObjectId('5f22bce9ad3e9621e4119c68'),\n", - " ObjectId('5f22bce9ad3e9621e4119c69'),\n", - " ObjectId('5f22bce9ad3e9621e4119c6a'),\n", - " ObjectId('5f22bce9ad3e9621e4119c6b'),\n", - " ObjectId('5f22bce9ad3e9621e4119c6c'),\n", - " ObjectId('5f22bce9ad3e9621e4119c6d'),\n", - " ObjectId('5f22bce9ad3e9621e4119c6e'),\n", - " ObjectId('5f22bce9ad3e9621e4119c6f'),\n", - " ObjectId('5f22bce9ad3e9621e4119c70'),\n", - " ObjectId('5f22bce9ad3e9621e4119c71'),\n", - " ObjectId('5f22bce9ad3e9621e4119c72'),\n", - " ObjectId('5f22bce9ad3e9621e4119c73'),\n", - " ObjectId('5f22bce9ad3e9621e4119c74'),\n", - " ObjectId('5f22bce9ad3e9621e4119c75'),\n", - " ObjectId('5f22bce9ad3e9621e4119c76'),\n", - " ObjectId('5f22bce9ad3e9621e4119c77'),\n", - " ObjectId('5f22bce9ad3e9621e4119c78'),\n", - " ObjectId('5f22bce9ad3e9621e4119c79'),\n", - " ObjectId('5f22bce9ad3e9621e4119c7a'),\n", - " ObjectId('5f22bce9ad3e9621e4119c7b'),\n", - " ObjectId('5f22bce9ad3e9621e4119c7c'),\n", - " ObjectId('5f22bce9ad3e9621e4119c7d'),\n", - " ObjectId('5f22bce9ad3e9621e4119c7e'),\n", - " ObjectId('5f22bce9ad3e9621e4119c7f'),\n", - " ObjectId('5f22bce9ad3e9621e4119c80'),\n", - " ObjectId('5f22bce9ad3e9621e4119c81'),\n", - " ObjectId('5f22bce9ad3e9621e4119c82'),\n", - " ObjectId('5f22bce9ad3e9621e4119c83'),\n", - " ObjectId('5f22bce9ad3e9621e4119c84'),\n", - " ObjectId('5f22bce9ad3e9621e4119c85'),\n", - " ObjectId('5f22bce9ad3e9621e4119c86'),\n", - " ObjectId('5f22bce9ad3e9621e4119c87'),\n", - " ObjectId('5f22bce9ad3e9621e4119c88'),\n", - " ObjectId('5f22bce9ad3e9621e4119c89'),\n", - " ObjectId('5f22bce9ad3e9621e4119c8a'),\n", - " ObjectId('5f22bce9ad3e9621e4119c8b'),\n", - " ObjectId('5f22bce9ad3e9621e4119c8c'),\n", - " ObjectId('5f22bce9ad3e9621e4119c8d'),\n", - " ObjectId('5f22bce9ad3e9621e4119c8e'),\n", - " ObjectId('5f22bce9ad3e9621e4119c8f'),\n", - " ObjectId('5f22bce9ad3e9621e4119c90'),\n", - " ObjectId('5f22bce9ad3e9621e4119c91'),\n", - " ObjectId('5f22bce9ad3e9621e4119c92'),\n", - " ObjectId('5f22bce9ad3e9621e4119c93'),\n", - " ObjectId('5f22bce9ad3e9621e4119c94'),\n", - " ObjectId('5f22bce9ad3e9621e4119c95'),\n", - " ObjectId('5f22bce9ad3e9621e4119c96'),\n", - " ObjectId('5f22bce9ad3e9621e4119c97'),\n", - " ObjectId('5f22bce9ad3e9621e4119c98'),\n", - " ObjectId('5f22bce9ad3e9621e4119c99'),\n", - " ObjectId('5f22bce9ad3e9621e4119c9a'),\n", - " ObjectId('5f22bce9ad3e9621e4119c9b'),\n", - " ObjectId('5f22bce9ad3e9621e4119c9c'),\n", - " ObjectId('5f22bce9ad3e9621e4119c9d'),\n", - " ObjectId('5f22bce9ad3e9621e4119c9e'),\n", - " ObjectId('5f22bce9ad3e9621e4119c9f'),\n", - " ObjectId('5f22bce9ad3e9621e4119ca0'),\n", - " ObjectId('5f22bce9ad3e9621e4119ca1'),\n", - " ObjectId('5f22bce9ad3e9621e4119ca2'),\n", - " ObjectId('5f22bce9ad3e9621e4119ca3'),\n", - " ObjectId('5f22bce9ad3e9621e4119ca4'),\n", - " ObjectId('5f22bce9ad3e9621e4119ca5'),\n", - " ObjectId('5f22bce9ad3e9621e4119ca6'),\n", - " ObjectId('5f22bce9ad3e9621e4119ca7'),\n", - " ObjectId('5f22bce9ad3e9621e4119ca8'),\n", - " ObjectId('5f22bce9ad3e9621e4119ca9'),\n", - " ObjectId('5f22bce9ad3e9621e4119caa'),\n", - " ObjectId('5f22bce9ad3e9621e4119cab'),\n", - " ObjectId('5f22bce9ad3e9621e4119cac'),\n", - " ObjectId('5f22bce9ad3e9621e4119cad'),\n", - " ObjectId('5f22bce9ad3e9621e4119cae'),\n", - " ObjectId('5f22bce9ad3e9621e4119caf'),\n", - " ObjectId('5f22bce9ad3e9621e4119cb0'),\n", - " ObjectId('5f22bce9ad3e9621e4119cb1'),\n", - " ObjectId('5f22bce9ad3e9621e4119cb2'),\n", - " ObjectId('5f22bce9ad3e9621e4119cb3'),\n", - " ObjectId('5f22bce9ad3e9621e4119cb4'),\n", - " ObjectId('5f22bce9ad3e9621e4119cb5'),\n", - " ObjectId('5f22bce9ad3e9621e4119cb6'),\n", - " ObjectId('5f22bce9ad3e9621e4119cb7'),\n", - " ObjectId('5f22bce9ad3e9621e4119cb8'),\n", - " ObjectId('5f22bce9ad3e9621e4119cb9'),\n", - " ObjectId('5f22bce9ad3e9621e4119cba'),\n", - " ObjectId('5f22bce9ad3e9621e4119cbb'),\n", - " ObjectId('5f22bce9ad3e9621e4119cbc'),\n", - " ObjectId('5f22bce9ad3e9621e4119cbd'),\n", - " ObjectId('5f22bce9ad3e9621e4119cbe'),\n", - " ObjectId('5f22bce9ad3e9621e4119cbf'),\n", - " ObjectId('5f22bce9ad3e9621e4119cc0'),\n", - " ObjectId('5f22bce9ad3e9621e4119cc1'),\n", - " ObjectId('5f22bce9ad3e9621e4119cc2'),\n", - " ObjectId('5f22bce9ad3e9621e4119cc3'),\n", - " ObjectId('5f22bce9ad3e9621e4119cc4'),\n", - " ObjectId('5f22bce9ad3e9621e4119cc5'),\n", - " ObjectId('5f22bce9ad3e9621e4119cc6'),\n", - " ObjectId('5f22bce9ad3e9621e4119cc7'),\n", - " ObjectId('5f22bce9ad3e9621e4119cc8'),\n", - " ObjectId('5f22bce9ad3e9621e4119cc9'),\n", - " ObjectId('5f22bce9ad3e9621e4119cca'),\n", - " ObjectId('5f22bce9ad3e9621e4119ccb'),\n", - " ObjectId('5f22bce9ad3e9621e4119ccc'),\n", - " ObjectId('5f22bce9ad3e9621e4119ccd'),\n", - " ObjectId('5f22bce9ad3e9621e4119cce'),\n", - " ObjectId('5f22bce9ad3e9621e4119ccf'),\n", - " ObjectId('5f22bce9ad3e9621e4119cd0'),\n", - " ObjectId('5f22bce9ad3e9621e4119cd1'),\n", - " ObjectId('5f22bce9ad3e9621e4119cd2'),\n", - " ObjectId('5f22bce9ad3e9621e4119cd3'),\n", - " ObjectId('5f22bce9ad3e9621e4119cd4'),\n", - " ObjectId('5f22bce9ad3e9621e4119cd5'),\n", - " ObjectId('5f22bce9ad3e9621e4119cd6'),\n", - " ObjectId('5f22bce9ad3e9621e4119cd7'),\n", - " ObjectId('5f22bce9ad3e9621e4119cd8'),\n", - " ObjectId('5f22bce9ad3e9621e4119cd9'),\n", - " ObjectId('5f22bce9ad3e9621e4119cda'),\n", - " ObjectId('5f22bce9ad3e9621e4119cdb'),\n", - " ObjectId('5f22bce9ad3e9621e4119cdc'),\n", - " ObjectId('5f22bce9ad3e9621e4119cdd'),\n", - " ObjectId('5f22bce9ad3e9621e4119cde'),\n", - " ObjectId('5f22bce9ad3e9621e4119cdf'),\n", - " ObjectId('5f22bce9ad3e9621e4119ce0'),\n", - " ObjectId('5f22bce9ad3e9621e4119ce1'),\n", - " ObjectId('5f22bce9ad3e9621e4119ce2'),\n", - " ObjectId('5f22bce9ad3e9621e4119ce3'),\n", - " ObjectId('5f22bce9ad3e9621e4119ce4'),\n", - " ObjectId('5f22bce9ad3e9621e4119ce5'),\n", - " ObjectId('5f22bce9ad3e9621e4119ce6'),\n", - " ObjectId('5f22bce9ad3e9621e4119ce7'),\n", - " ObjectId('5f22bce9ad3e9621e4119ce8'),\n", - " ObjectId('5f22bce9ad3e9621e4119ce9'),\n", - " ObjectId('5f22bce9ad3e9621e4119cea'),\n", - " ObjectId('5f22bce9ad3e9621e4119ceb'),\n", - " ObjectId('5f22bce9ad3e9621e4119cec'),\n", - " ObjectId('5f22bce9ad3e9621e4119ced'),\n", - " ObjectId('5f22bce9ad3e9621e4119cee'),\n", - " ObjectId('5f22bce9ad3e9621e4119cef'),\n", - " ObjectId('5f22bce9ad3e9621e4119cf0'),\n", - " ObjectId('5f22bce9ad3e9621e4119cf1'),\n", - " ObjectId('5f22bce9ad3e9621e4119cf2'),\n", - " ObjectId('5f22bce9ad3e9621e4119cf3'),\n", - " ObjectId('5f22bce9ad3e9621e4119cf4'),\n", - " ObjectId('5f22bce9ad3e9621e4119cf5'),\n", - " ObjectId('5f22bce9ad3e9621e4119cf6'),\n", - " ObjectId('5f22bce9ad3e9621e4119cf7'),\n", - " ObjectId('5f22bce9ad3e9621e4119cf8'),\n", - " ObjectId('5f22bce9ad3e9621e4119cf9'),\n", - " ObjectId('5f22bce9ad3e9621e4119cfa'),\n", - " ObjectId('5f22bce9ad3e9621e4119cfb'),\n", - " ObjectId('5f22bce9ad3e9621e4119cfc'),\n", - " ObjectId('5f22bce9ad3e9621e4119cfd'),\n", - " ObjectId('5f22bce9ad3e9621e4119cfe'),\n", - " ObjectId('5f22bce9ad3e9621e4119cff'),\n", - " ObjectId('5f22bce9ad3e9621e4119d00'),\n", - " ObjectId('5f22bce9ad3e9621e4119d01'),\n", - " ObjectId('5f22bce9ad3e9621e4119d02'),\n", - " ObjectId('5f22bce9ad3e9621e4119d03'),\n", - " ObjectId('5f22bce9ad3e9621e4119d04'),\n", - " ObjectId('5f22bce9ad3e9621e4119d05'),\n", - " ObjectId('5f22bce9ad3e9621e4119d06'),\n", - " ObjectId('5f22bce9ad3e9621e4119d07'),\n", - " ObjectId('5f22bce9ad3e9621e4119d08'),\n", - " ObjectId('5f22bce9ad3e9621e4119d09'),\n", - " ObjectId('5f22bce9ad3e9621e4119d0a'),\n", - " ObjectId('5f22bce9ad3e9621e4119d0b'),\n", - " ObjectId('5f22bce9ad3e9621e4119d0c'),\n", - " ObjectId('5f22bce9ad3e9621e4119d0d'),\n", - " ObjectId('5f22bce9ad3e9621e4119d0e'),\n", - " ObjectId('5f22bce9ad3e9621e4119d0f'),\n", - " ObjectId('5f22bce9ad3e9621e4119d10'),\n", - " ObjectId('5f22bce9ad3e9621e4119d11'),\n", - " ObjectId('5f22bce9ad3e9621e4119d12'),\n", - " ObjectId('5f22bce9ad3e9621e4119d13'),\n", - " ObjectId('5f22bce9ad3e9621e4119d14'),\n", - " ObjectId('5f22bce9ad3e9621e4119d15'),\n", - " ObjectId('5f22bce9ad3e9621e4119d16'),\n", - " ObjectId('5f22bce9ad3e9621e4119d17'),\n", - " ObjectId('5f22bce9ad3e9621e4119d18'),\n", - " ObjectId('5f22bce9ad3e9621e4119d19'),\n", - " ObjectId('5f22bce9ad3e9621e4119d1a'),\n", - " ObjectId('5f22bce9ad3e9621e4119d1b'),\n", - " ObjectId('5f22bce9ad3e9621e4119d1c'),\n", - " ObjectId('5f22bce9ad3e9621e4119d1d'),\n", - " ObjectId('5f22bce9ad3e9621e4119d1e'),\n", - " ObjectId('5f22bce9ad3e9621e4119d1f'),\n", - " ObjectId('5f22bce9ad3e9621e4119d20'),\n", - " ObjectId('5f22bce9ad3e9621e4119d21'),\n", - " ObjectId('5f22bce9ad3e9621e4119d22'),\n", - " ObjectId('5f22bce9ad3e9621e4119d23'),\n", - " ObjectId('5f22bce9ad3e9621e4119d24'),\n", - " ObjectId('5f22bce9ad3e9621e4119d25'),\n", - " ObjectId('5f22bce9ad3e9621e4119d26'),\n", - " ObjectId('5f22bce9ad3e9621e4119d27'),\n", - " ObjectId('5f22bce9ad3e9621e4119d28'),\n", - " ObjectId('5f22bce9ad3e9621e4119d29'),\n", - " ObjectId('5f22bce9ad3e9621e4119d2a'),\n", - " ObjectId('5f22bce9ad3e9621e4119d2b')]" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "document_ids = molecules.find().distinct('_id')\n", - "document_ids" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "def chunk(list, length):\n", - " for i in range(0, len(l), length):\n", - " yield l[i:i + n]" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def calculate(chunk, input):\n", - " client = pymongo.MongoClient('localhost', 27017, maxPoolSize=1000)\n", - " db = client['multip']\n", - " collection = db['molecules']\n", - " chunk_list = []\n", - " for id in chunk: \n", - " result = \n", - " chunk_list.append()\n", - " \n", - " \n", - "# # define client inside function\n", - " \n", - " \n", - " \n", - " \n", - "# client = pymongo.MongoClient('localhost', 27017, maxPoolSize=10000)\n", - "\n", - "# db = client['multip']\n", - "# collection = db['molecules']\n", - "# chunk_result_list = []\n", - "# # loop over the id's in the chunk and do the calculation with each\n", - "# # my problem right now is that I want to be able to chunk the CURSOR.\n", - "# for id in chunk:\n", - "# #do the calculation with document collection.find_one(id) \n", - "# chunk_result_list.append(result)\n", - "# return chunk_result_list" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There are two ways that we can split the processing here. \n", - "\n", - "When the cursor query is expensive, we want to split up the cursor. \n", - "\n", - "When the cursor query is not, we simply want to keep the cursor together, and parallelize the subsequent operations. Let's start with the latter. We've got a cursor object that is iterable. \n", - "\n", - "What you could do is iterate through the cursor and get all the object ids. Then you could find all of them again and \n", - "For " - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "py37_rdkit_beta", - "language": "python", - "name": "py37_rdkit_beta" - }, - "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.7.7" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/docs/notebooks/Similarity Benchmarking.ipynb b/docs/notebooks/Similarity Benchmarking.ipynb new file mode 100644 index 0000000..7ebd8fb --- /dev/null +++ b/docs/notebooks/Similarity Benchmarking.ipynb @@ -0,0 +1,428 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Similarity Search Benchmarking\n", + "\n", + "These benchmarks were originally run on an early 2015 MacBook Pro with a 2.7 GHz dual-core i5 processor and 8GB of memory. \n", + "\n", + "They make use of a ChEMBL_27 dataset. \n", + "## Setup Work\n", + "### Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import mongordkit\n", + "import time\n", + "import pymongo\n", + "import rdkit\n", + "import matplotlib\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from os import sys\n", + "import pandas as pd\n", + "from rdkit import Chem\n", + "from statistics import mean, median\n", + "import mongomock\n", + "from rdkit.Chem import AllChem\n", + "from mongordkit.Database import write\n", + "from mongordkit.Search import similarity\n", + "from mongordkit import Search" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Database Setup\n", + "Here we set up a database called `test` that will hold our molecules. We will construct a collection called `molecules_100K` to hold the first 100,000 molecules in the ChEMBL_27 dataset and a collection called `molecules_1M` to hold the first 1,000,000 molecules in the ChEMBL_27 dataset. If you have already run benchmarks from `mongo-rdkit` on your local MongoDB instance, these should have been set up already." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Initialize the client that will connect to the database.\n", + "client = pymongo.MongoClient()\n", + "db = client.test" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# If necessary, write the first 100,000 compounds to molecules_100K.\n", + "if db.molecules_100K.count_documents({}) != 100000:\n", + " write.WriteFromSDF(db.molecules_100K, '../../../chembl_27.sdf', chunk_size=1000, limit=100000)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# If necessary, write the first 1,000,000 compounds to molecules_1M.\n", + "if db.molecules_1M.count_documents({}) != 1000000:\n", + " write.writeFromSDF(db.molecules_1M, '../../../chembl_27.sdf', chunk_size=1000, limit=1000000)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Let's ensure that there are actually 100,000 and 1M documents in these collections, respectively.\n", + "print(f\"In molecules_100K: {db.molecules_100K.count_documents({})} documents\")\n", + "print(f\"In molecules_1M: {db.molecules_1M.count_documents({})} documents\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Next, we have to prepare the database for search by adding in fingerprints and hash collections.\n", + "Search.PrepareForSearch(db, db.molecules_100K, db.molecules_100KCt, db.molecules_100KPm)\n", + "Search.PrepareForSearch(db, db.molecules_1M, db.molecules_1MCt, db.molecules_1MPm)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Query Set Setup\n", + "To benchmark, we'll use the first 200 compounds in ChEMBL. Let's get an rdmol for each of these and write them into a list. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "first_200 = []\n", + "for rdmol in Chem.ForwardMolSupplier('../../data/test_data/first_200.props.sdf'): \n", + " first_200.append(rdmol)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Benchmarks" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will search each compound five times against the target database, taking the mean value as representative of that molecule. We'll then take the median and mean for all 200 compounds, repeating the entire process for thresholds 0.7, 0.75, 0.8, 0.85, and 0.9. \n", + "\n", + "We will benchmark both the `SimSearchAggregate` and `SimSearchLSH` methods, keeping in mind that the LSH method does not return exact results. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "thresholds = [0.7, 0.75, 0.8, 0.85, 0.9, 0.95]\n", + "repetitions = 5" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### `SimSearchAggregate`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Benchmark against the first 100,000 molecules in ChEMBL. \n", + "aggregate_means_100K = []\n", + "aggregate_medians_100K = []\n", + "\n", + "for t in thresholds: \n", + " print(f\"Measuring performance for similarity threshold {t}...\")\n", + " query_times = []\n", + " for rdmol in first_200:\n", + " temp_times = []\n", + " for r in range(repetitions):\n", + " start = time.time()\n", + " _ = similarity.SimSearchAggregate(rdmol, db.molecules_100K, db.molecules_100KCt, threshold=t)\n", + " end = time.time()\n", + " temp_times.append(end - start)\n", + " query_times.append(mean(temp_times))\n", + " aggregate_means_100K.append([t, mean(query_times)])\n", + " aggregate_medians_100K.append([t, median(query_times)])\n", + "\n", + "print(f\"Aggregate means: {aggregate_means_100K}\")\n", + "print(f\"Aggregate medians: {aggregate_medians_100K}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Before we take a look at the 1M molecule dataset, let's graph these times to get a better idea of how similarity search increases in time required with lowered similarity thresholds: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x_list = [v[0] for v in aggregate_medians_100K]\n", + "y_list = [v[1] for v in aggregate_medians_100K]\n", + "plt.xlabel('thresholds')\n", + "plt.ylabel('time (s)')\n", + "plt.title('SimSearchAggregate medians / 100K dataset')\n", + "plt.plot(x_list, y_list)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And here are the equivalent benchmarks against a million-molecule dataset:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Benchmark against the first 1M molecules in ChEMBL. \n", + "aggregate_means_1M = []\n", + "aggregate_medians_1M = []\n", + "\n", + "for t in thresholds: \n", + " print(f\"Measuring performance for similarity threshold {t}...\")\n", + " query_times = []\n", + " for rdmol in first_200:\n", + " temp_times = []\n", + " for r in range(repetitions):\n", + " start = time.time()\n", + " _ = similarity.SimSearchAggregate(rdmol, db.molecules_1M, db.molecules_1MCt, threshold=t)\n", + " end = time.time()\n", + " temp_times.append(end - start)\n", + " query_times.append(mean(temp_times))\n", + " aggregate_means_1M.append([t, mean(query_times)])\n", + " aggregate_medians_1M.append([t, median(query_times)])\n", + "\n", + "print(f\"Aggregate means: {aggregate_means_1M}\")\n", + "print(f\"Aggregate medians: {aggregate_medians_1M}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x_list = [v[0] for v in aggregate_medians_1M]\n", + "y_list = [v[1] for v in aggregate_medians_1M]\n", + "plt.xlabel('thresholds')\n", + "plt.ylabel('time (s)')\n", + "plt.title('SimSearchAggregate medians / 1M dataset')\n", + "plt.plot(x_list, y_list)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### `SimSearchLSH`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will benchmark speed for LSH in the same way as we did for normal similarity search. As noted by the original ChEMBL authors of this approach, however, LSH also introduces an element of inaccuracy. Thus, we will also include a section on comparing results of `SimSearchAggregate` and `SimSearchLSH`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Benchmark against the first 100,000 molecules in ChEMBL. \n", + "LSH_means_100K = []\n", + "LSH_medians_100K = []\n", + "\n", + "for t in thresholds: \n", + " print(f\"Measuring performance for similarity threshold {t}...\")\n", + " query_times = []\n", + " for rdmol in first_200:\n", + " temp_times = []\n", + " for r in range(repetitions):\n", + " start = time.time()\n", + " _ = similarity.SimSearchLSH(rdmol, db, db.molecules_100K, \n", + " db.molecules_100KP, db.molecules_100KCt, threshold=t)\n", + " end = time.time()\n", + " temp_times.append(end - start)\n", + " query_times.append(mean(temp_times))\n", + " LSH_means_100K.append([t, mean(query_times)])\n", + " LSH_medians_100K.append([t, median(query_times)])\n", + "\n", + "print(f\"LSH means: {LSH_means_100K}\")\n", + "print(f\"LSH medians: {LSH_medians_100K}\")\n", + "\n", + "x_list = [v[0] for v in LSH_medians_100K]\n", + "y_list = [v[1] for v in LSH_medians_100K]\n", + "plt.xlabel('thresholds')\n", + "plt.ylabel('time (s)')\n", + "plt.title('SimSearchLSH medians / 100K dataset')\n", + "plt.plot(x_list, y_list)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Benchmark against the first 100,000 molecules in ChEMBL. \n", + "LSH_means_1M = []\n", + "LSH_medians_1M = []\n", + "\n", + "for t in thresholds: \n", + " print(f\"Measuring performance for similarity threshold {t}...\")\n", + " query_times = []\n", + " for rdmol in first_200:\n", + " temp_times = []\n", + " for r in range(repetitions):\n", + " start = time.time()\n", + " _ = similarity.SimSearchLSH(rdmol, db, db.molecules_1M, \n", + " db.molecules_1MP, db.molecules_1MCt, threshold=t)\n", + " end = time.time()\n", + " temp_times.append(end - start)\n", + " query_times.append(mean(temp_times))\n", + " LSH_means_1M.append([t, mean(query_times)])\n", + " LSH_medians_1M.append([t, median(query_times)])\n", + "\n", + "print(f\"LSH means: {LSH_means_1M}\")\n", + "print(f\"LSH medians: {LSH_medians_1M}\")\n", + "\n", + "x_list = [v[0] for v in LSH_medians_1M]\n", + "y_list = [v[1] for v in LSH_medians_1M]\n", + "plt.xlabel('thresholds')\n", + "plt.ylabel('time (s)')\n", + "plt.title('SimSearchLSH medians / 1M dataset')\n", + "plt.plot(x_list, y_list)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order to compare accuracy, we will use the approach written about in the ChEMBL blog post: finding the symmetric set difference between the two sets of results as a percentage of the size of the union of the two result sets. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "results = []\n", + "\n", + "for t in thresholds: \n", + " print(f\"Measuring accuracy for similarity threshold {t}...\")\n", + " nmols_w_discrepancies = 0\n", + " discrepancies_per_mol = []\n", + " discrepancy_percent_per_mol = []\n", + " for rdmol in first_200:\n", + " sim_lsh = similarity.SimSearchLSH(rdmol, db, db.molecules_100K, \n", + " db.molecules_100KP, db.molecules_100KCt, threshold=t)\n", + " sim_agg = similarity.SimSearchAggregate(rdmol, db.molecules_100K, db.molecules_100KCt, threshold=t)\n", + " if sim_lsh: \n", + " set_lsh = set(result[1] for result in sim_lsh)\n", + " else:\n", + " set_lsh = set()\n", + " if sim_agg: \n", + " set_agg = set(result[1] for result in sim_agg)\n", + " else: \n", + " set_agg = set()\n", + " sym_set_diff = (set_lsh ^ set_agg)\n", + " discrepancies = len(sym_set_diff)\n", + " total = len(set_lsh | set_agg)\n", + " if discrepancies:\n", + " nmols_w_discrepancies += 1\n", + " discrepancies_per_mol.append(discrepancies)\n", + " discrepancy_percent_per_mol.append(discrepancies / total * 100)\n", + " results.append([t, f'nmols_w_discrepancies: {nmols_w_discrepancies}', \n", + " np.mean(discrepancies_per_mol), np.mean(discrepancy_percent_per_mol)])\n", + "print(results)\n", + "x_list = [v[0] for v in results]\n", + "y_list = [v[3] for v in results]\n", + "plt.xlabel('thresholds')\n", + "plt.ylabel('discrepancy percent per molecule')\n", + "plt.title('LSH Accuracy / 100K dataset')\n", + "plt.plot(x_list, y_list)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Discussion\n", + "These times are already very reasonable for a similarity search. However, it is worth noting that these benchmarks were run on a local MongoDB instance, effectively making no distinction between the client and the server. A MongoDB instance that has more horizontal scaling could benefit greatly from the aggregation pipeline, thus speeding search even further. \n", + "\n", + "The time complexity also increases greatly with decreasing Tanimoto thresholds." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "py37_rdkit_beta", + "language": "python", + "name": "py37_rdkit_beta" + }, + "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.7.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/docs/notebooks/Similarity Testing.ipynb b/docs/notebooks/Similarity Testing.ipynb deleted file mode 100644 index 986a6c0..0000000 --- a/docs/notebooks/Similarity Testing.ipynb +++ /dev/null @@ -1,532 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Similarity Search Benchmarking\n", - "\n", - "These benchmarks were originally run on an early 2015 MacBook Pro with a 2.7 GHz dual-core i5 processor and 8GB of memory. \n", - "\n", - "They make use of a ChEMBL_27 dataset. " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import mongordkit\n", - "import time\n", - "import pymongo\n", - "import rdkit\n", - "import matplotlib\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "from os import sys\n", - "import pandas as pd\n", - "from rdkit import Chem\n", - "from statistics import mean\n", - "import mongomock\n", - "from rdkit.Chem import AllChem\n", - "from mongordkit.Database import write\n", - "from mongordkit.Search import similarity" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "populating mongodb collection with compounds from chembl...\n", - "199 molecules successfully imported\n" - ] - } - ], - "source": [ - "#Create a mongomock database instance and write to it. \n", - "client = mongomock.MongoClient()\n", - "db = client.db\n", - "\n", - "#Write 200 molecules into the database\n", - "write.writeFromSDF(db.molecules, '../../data/test_data/first_200.props.sdf', 'test', chunk_size=100, limit=199)\n", - "doc = db.molecules.find_one()\n", - "m = Chem.Mol(doc['rdmol'])" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "#Add Morgan fingerprints into the database\n", - "similarity.addMorganFingerprints(db)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "#Check that similarity search is working, at least for one molecule. \n", - "doc = db.molecules.find_one()\n", - "m = Chem.Mol(doc['rdmol'])\n", - "results = similarity.similaritySearch(m, db, .8)\n", - "results" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "populating mongodb collection with compounds from chembl...\n", - "inserted chunk...\n", - "inserted chunk...\n", - "1000 molecules successfully imported\n" - ] - }, - { - "data": { - "text/plain": [ - "1000" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "#Create a regular mongoDB database instance and write the first 1000 molecules to it. \n", - "client = pymongo.MongoClient()\n", - "db = client.db\n", - "db.molecules.drop()\n", - "db.mfp_counts.drop()\n", - "write.writeFromSDF(db, '../../../chembl_27.sdf', 'test', reg_option='standard_setting', index_option='inchikey', chunk_size=500, limit=500)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "def calc_tanimoto(Na, Nb):\n", - " Nab = len(set(Na).intersection((set(Nb))))\n", - " return float(Nab) / (len(Na) + len(Nb) - Nab)\n", - "\n", - "def similarity_search_naive(query_mol, db, threshold): \n", - " results = []\n", - " qfp = list(AllChem.GetMorganFingerprintAsBitVect(query_mol, 2, nBits=1024).GetOnBits())\n", - " for mol in db.molecules.find():\n", - " mfp = list(AllChem.GetMorganFingerprintAsBitVect(Chem.Mol(mol['rdmol']), 2, nBits=1024).GetOnBits())\n", - " tanimoto = calc_tanimoto(qfp, mfp)\n", - " if calc_tanimoto(qfp, mfp) >= threshold:\n", - " results.append([tanimoto, mol['smiles']])\n", - " return results" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Measuring performance for similarity threshold 0.7.\n", - "Measuring performance for similarity threshold 0.75.\n", - "Measuring performance for similarity threshold 0.8.\n", - "Measuring performance for similarity threshold 0.85.\n", - "Measuring performance for similarity threshold 0.9.\n", - "Measuring performance for similarity threshold 0.95.\n", - "[[0.7, 3.236401987075806], [0.75, 2.964214563369751], [0.8, 2.850223159790039], [0.85, 2.716036558151245], [0.9, 2.50888934135437], [0.95, 2.7822859287261963]]\n", - "Measuring performance for similarity threshold 0.7.\n" - ] - }, - { - "ename": "NameError", - "evalue": "name 'query_mol' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 23\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mm\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdb\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmolecules\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfind\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 24\u001b[0m \u001b[0mmol\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mChem\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mMol\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mm\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'rdmol'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 25\u001b[0;31m \u001b[0m_\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msimilarity_search_naive\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmol\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 26\u001b[0m \u001b[0mend\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtime\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[0mtemp_times\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mend\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mstart\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m\u001b[0m in \u001b[0;36msimilarity_search_naive\u001b[0;34m(mol, db, t)\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0msimilarity_search_naive\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmol\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0mresults\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0mqfp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mAllChem\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mGetMorganFingerprintAsBitVect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mquery_mol\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnBits\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1024\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mGetOnBits\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 8\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mmol\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdb\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmolecules\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfind\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0mmfp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mAllChem\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mGetMorganFingerprintAsBitVect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mChem\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mMol\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmol\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'rdmol'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnBits\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1024\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mGetOnBits\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mNameError\u001b[0m: name 'query_mol' is not defined" - ] - } - ], - "source": [ - "#Run benchmarks for similarity search with and without aggregation parameters, then with LSH + aggregation. \n", - "thresholds = [0.7, 0.75, 0.8, 0.85, 0.9, 0.95]\n", - "times = []\n", - "repetitions = 5\n", - "for t in thresholds: \n", - " print(\"Measuring performance for similarity threshold {}.\".format(t))\n", - " temp_times = []\n", - " for r in range(repetitions):\n", - " start = time.time()\n", - " for m in db.molecules.find():\n", - " mol = Chem.Mol(m['rdmol'])\n", - " _ = similarity.similaritySearch(mol, db, t)\n", - " end = time.time()\n", - " temp_times.append(end - start)\n", - " times.append([t, mean(temp_times)])\n", - "print(times)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Measuring performance for similarity threshold 0.7.\n", - "Measuring performance for similarity threshold 0.75.\n" - ] - }, - { - "ename": "KeyboardInterrupt", - "evalue": "", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;32mbreak\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0mmol\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mChem\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mMol\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mm\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'rdmol'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0m_\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msimilarity_search_naive\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmol\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 12\u001b[0m \u001b[0mcounter\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0mend\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtime\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m\u001b[0m in \u001b[0;36msimilarity_search_naive\u001b[0;34m(query_mol, db, threshold)\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0mqfp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mAllChem\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mGetMorganFingerprintAsBitVect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mquery_mol\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnBits\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1024\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mGetOnBits\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mmol\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdb\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmolecules\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfind\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 9\u001b[0;31m \u001b[0mmfp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mAllChem\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mGetMorganFingerprintAsBitVect\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mChem\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mMol\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmol\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'rdmol'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnBits\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1024\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mGetOnBits\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 10\u001b[0m \u001b[0mtanimoto\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcalc_tanimoto\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mqfp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmfp\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcalc_tanimoto\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mqfp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmfp\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m>=\u001b[0m \u001b[0mthreshold\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mKeyboardInterrupt\u001b[0m: " - ] - } - ], - "source": [ - "for t in thresholds: \n", - " print(\"Measuring performance for similarity threshold {}.\".format(t))\n", - " temp_times = []\n", - " for r in range(5):\n", - " start = time.time()\n", - " counter = 0\n", - " for m in db.molecules.find():\n", - " if counter > 100: \n", - " break\n", - " mol = Chem.Mol(m['rdmol'])\n", - " _ = similarity_search_naive(mol, db, t)\n", - " counter += 1\n", - " end = time.time()\n", - " temp_times.append(end - start)\n", - " times.append([t, mean(temp_times)])\n", - "print(times)" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 40, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "x_list = [v[0] for v in times]\n", - "y_list = [v[1]*1000 for v in times]\n", - "plt.xlabel('thresholds')\n", - "plt.ylabel('time (ms)')\n", - "plt.title('Without Aggregation')\n", - "plt.plot(x_list, y_list)" - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Measuring performance for similarity threshold 0.7.\n", - "Measuring performance for similarity threshold 0.75.\n", - "Measuring performance for similarity threshold 0.8.\n", - "Measuring performance for similarity threshold 0.85.\n", - "Measuring performance for similarity threshold 0.9.\n", - "Measuring performance for similarity threshold 0.95.\n", - "[[0.7, 6.002911186218261], [0.75, 5.983159065246582], [0.8, 5.641262626647949], [0.85, 5.888340759277344], [0.9, 6.869273900985718], [0.95, 5.446581506729126]]\n" - ] - }, - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 41, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "thresholds = [0.7, 0.75, 0.8, 0.85, 0.9, 0.95]\n", - "times = []\n", - "repetitions = 5\n", - "for t in thresholds: \n", - " print(\"Measuring performance for similarity threshold {}.\".format(t))\n", - " temp_times = []\n", - " for r in range(repetitions):\n", - " start = time.time()\n", - " for m in db.molecules.find():\n", - " mol = Chem.Mol(m['rdmol'])\n", - " _ = similarity.similaritySearchAggregate(mol, db, t)\n", - " end = time.time()\n", - " temp_times.append(end - start)\n", - " times.append([t, mean(temp_times)])\n", - "print(times)\n", - "x_list = [v[0] for v in times]\n", - "y_list = [v[1]*1000 for v in times]\n", - "plt.xlabel('thresholds')\n", - "plt.ylabel('time (ms)')\n", - "plt.title('With Aggregation')\n", - "plt.plot(x_list, y_list)" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "populating mongodb collection with compounds from chembl...\n", - "The specified setting does not exist. Will only insert default molecules\n", - "inserted chunk...\n", - "inserted chunk...\n", - "1000 molecules successfully imported\n" - ] - } - ], - "source": [ - "db.molecules.drop()\n", - "db.mfp_counts.drop()\n", - "write.writeFromSDF(db, '../../../chembl_27.sdf', 'test', reg_option='inchikey', index_option='inchikey', chunk_size=500, limit=500)\n", - "similarity.addMorganFingerprints(db)" - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Measuring performance for similarity threshold 0.7.\n", - "Measuring performance for similarity threshold 0.75.\n", - "Measuring performance for similarity threshold 0.8.\n", - "Measuring performance for similarity threshold 0.85.\n", - "Measuring performance for similarity threshold 0.9.\n", - "Measuring performance for similarity threshold 0.95.\n", - "[[0.7, 0.0038346290588378907], [0.75, 0.003863954544067383], [0.8, 0.00497593879699707], [0.85, 0.00534672737121582], [0.9, 0.004187107086181641], [0.95, 0.006510639190673828]]\n" - ] - }, - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 47, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "#Compute benchmarks with a fingerprint counts collection.\n", - "thresholds = [0.7, 0.75, 0.8, 0.85, 0.9, 0.95]\n", - "times = []\n", - "repetitions = 5\n", - "for t in thresholds: \n", - " print(\"Measuring performance for similarity threshold {}.\".format(t))\n", - " temp_times = []\n", - " for r in range(repetitions):\n", - " start = time.time()\n", - " for m in db.molecules.find():\n", - " mol = Chem.Mol(m['rdmol'])\n", - " _ = similarity.similaritySearch(mol, db, t)\n", - " end = time.time()\n", - " temp_times.append(end - start)\n", - " times.append([t, mean(temp_times)])\n", - "print(times)\n", - "x_list = [v[0] for v in times]\n", - "y_list = [v[1]*1000 for v in times]\n", - "plt.xlabel('thresholds')\n", - "plt.ylabel('time (ms)')\n", - "plt.title('Without Aggregation')\n", - "plt.plot(x_list, y_list)" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Measuring performance for similarity threshold 0.7.\n", - "Measuring performance for similarity threshold 0.75.\n", - "Measuring performance for similarity threshold 0.8.\n", - "Measuring performance for similarity threshold 0.85.\n", - "Measuring performance for similarity threshold 0.9.\n", - "Measuring performance for similarity threshold 0.95.\n", - "[[0.7, 0.009987068176269532], [0.75, 0.0059474468231201175], [0.8, 0.005334234237670899], [0.85, 0.0038384437561035157], [0.9, 0.0040286540985107425], [0.95, 0.0037296295166015627]]\n" - ] - }, - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 45, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "times = []\n", - "for t in thresholds: \n", - " print(\"Measuring performance for similarity threshold {}.\".format(t))\n", - " temp_times = []\n", - " for r in range(repetitions):\n", - " start = time.time()\n", - " for m in db.molecules.find():\n", - " mol = Chem.Mol(m['rdmol'])\n", - " _ = similarity.similaritySearchAggregate(mol, db, t)\n", - " end = time.time()\n", - " temp_times.append(end - start)\n", - " times.append([t, mean(temp_times)])\n", - "print(times)\n", - "x_list = [v[0] for v in times]\n", - "y_list = [v[1]*1000 for v in times]\n", - "plt.xlabel('thresholds')\n", - "plt.ylabel('time (ms)')\n", - "plt.title('Without Aggregation')\n", - "plt.plot(x_list, y_list)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "py37_rdkit_beta", - "language": "python", - "name": "py37_rdkit_beta" - }, - "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.7.7" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/docs/notebooks/Similarity and Substructure Search.ipynb b/docs/notebooks/Similarity and Substructure Search.ipynb index 837c466..82c3f12 100644 --- a/docs/notebooks/Similarity and Substructure Search.ipynb +++ b/docs/notebooks/Similarity and Substructure Search.ipynb @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -35,7 +35,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -54,7 +54,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 3, "metadata": { "scrolled": true }, @@ -63,195 +63,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "populating mongodb collection with compounds from SDF...\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:21] WARNING: Charges were rearranged\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [22:56:21] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:23] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", - "RDKit WARNING: [23:01:23] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:24] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:24] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ + "populating mongodb collection with compounds from SDF...\n", "200 molecules successfully imported\n", "0 duplicates skipped\n", "Preparing database and collections for search...\n", @@ -273,7 +85,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -302,7 +114,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 5, "metadata": { "scrolled": true }, @@ -318,91 +130,182 @@ "name": "stderr", "output_type": "stream", "text": [ - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:25] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:25] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:44] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:44] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:44] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:44] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:44] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:44] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:44] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:44] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:44] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [23:01:44] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:45] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", - "RDKit WARNING: [23:01:45] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [23:01:45] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [23:01:46] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:46] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [23:01:46] WARNING: Omitted undefined stereo\n" + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:38] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [15:43:38] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged; Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", + "RDKit WARNING: [15:43:40] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:40] WARNING: Omitted undefined stereo\n", + "RDKit WARNING: [15:43:40] WARNING: Omitted undefined stereo\n" ] }, { @@ -419,7 +322,7 @@ "200" ] }, - "execution_count": 8, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -440,7 +343,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -449,7 +352,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -474,7 +377,7 @@ " 'count': 16}" ] }, - "execution_count": 10, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -492,17 +395,17 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "similaritySearch: []\n", + "similaritySearch: [[0.4117647058823529, 'WLHCBQAPPJAULW-UHFFFAOYSA-N']]\n", "\n", "\n", - "similaritySearchAggregate: []\n" + "similaritySearchAggregate: [[0.4117647058823529, 'WLHCBQAPPJAULW-UHFFFAOYSA-N']]\n" ] } ], @@ -510,10 +413,10 @@ "q_mol = Chem.MolFromSmiles('Cc1ccccc1')\n", "\n", "# Perform a similarity search on TestDB for q_mol with a Tanimoto threshold of 0.4. \n", - "results1 = similarity.SimSearch(q_mol, demo_db.molecules, demo_db.mfp_counts, 0.8)\n", + "results1 = similarity.SimSearch(q_mol, demo_db.molecules, demo_db.mfp_counts, 0.4)\n", "\n", "# Do the same thing, but use the MongoDB Aggregation Pipeline. \n", - "results2 = similarity.SimSearchAggregate(q_mol, demo_db.molecules, demo_db.mfp_counts, 0.8)\n", + "results2 = similarity.SimSearchAggregate(q_mol, demo_db.molecules, demo_db.mfp_counts, 0.4)\n", "\n", "print('similaritySearch: {}'.format(results1))\n", "print('\\n')\n", @@ -531,7 +434,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -555,7 +458,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -569,7 +472,8 @@ "source": [ "q_mol = Chem.MolFromSmiles('Cc1ccccc1')\n", "\n", - "results3 = similarity.SimSearchLSH(q_mol, demo_db, demo_db.molecules, demo_db.permutations, threshold=0.8)\n", + "results3 = similarity.SimSearchLSH(q_mol, demo_db, demo_db.molecules, \n", + " demo_db.permutations, demo_db.mfp_counts, threshold=0.8)\n", "\n", "print('similaritySearchLSH: {}'.format(results3))" ] @@ -594,7 +498,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -610,7 +514,7 @@ " 'CDCRUVGWQJYTFO-UHFFFAOYSA-N']" ] }, - "execution_count": 14, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -631,7 +535,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -647,7 +551,7 @@ " 'CDCRUVGWQJYTFO-UHFFFAOYSA-N']" ] }, - "execution_count": 15, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -700,7 +604,7 @@ "\n", "mongordkit.Search.similarity.**AddHashCollections**(db (*MongoDB database*), mol_collection (*MongoDB collection*)) --> None\n", "\n", - "mongordkit.Search.similarity.**SimSearchLSH**(mol (*rdmol object*), db (*MongoDB database containing hash collections*), mol_collection (*MongoDB collection*), perm_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, index]*" + "mongordkit.Search.similarity.**SimSearchLSH**(mol (*rdmol object*), db (*MongoDB database containing hash collections*), mol_collection (*MongoDB collection*), perm_collection (*MongoDB collection*), count_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, index]*" ] }, { diff --git a/docs/notebooks/Substructure Benchmarking.ipynb b/docs/notebooks/Substructure Benchmarking.ipynb index 26f2eb8..ef27503 100644 --- a/docs/notebooks/Substructure Benchmarking.ipynb +++ b/docs/notebooks/Substructure Benchmarking.ipynb @@ -15,7 +15,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Imports" + "## Setup Work\n", + "### Imports" ] }, { @@ -38,27 +39,25 @@ "import numpy as np\n", "from os import sys\n", "import pandas as pd\n", - "from statistics import mean, median\n", "from IPython.display import display, HTML\n", "\n", "from mongordkit.Database import write\n", "from mongordkit.Search import similarity\n", - "from mongordkit.Search import substructure" + "from mongordkit.Search import substructure\n", + "from mongordkit import Search" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Database Setup\n", - "Here we set up a database called `test` that will hold our molecules. We will construct 1 collection called `molecules_100K` to hold the first 100,000 molecules in the ChEMBL_27 dataset and a collection called `molecules_1M` to hold the first 1,000,000 molecules in the ChEMBL_27 dataset." + "### Database Setup\n", + "Here we set up a database called `test` that will hold our molecules. We will construct a collection called `molecules_100K` to hold the first 100,000 molecules in the ChEMBL_27 dataset and a collection called `molecules_1M` to hold the first 1,000,000 molecules in the ChEMBL_27 dataset. If you have already run benchmarks from `mongo-rdkit` on your local MongoDB instance, these should have been set up already." ] }, { - "cell_type": "code", - "execution_count": 8, + "cell_type": "raw", "metadata": {}, - "outputs": [], "source": [ "# Initialize the client that will connect to the database.\n", "client = pymongo.MongoClient()\n", @@ -67,76 +66,65 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "populating mongodb collection with compounds from chembl...\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "RDKit WARNING: [15:22:20] Warning: conflicting stereochemistry at atom 11 ignored.\n", - "RDKit WARNING: [15:45:12] Warning: conflicting stereochemistry at atom 14 ignored.\n", - "RDKit WARNING: [16:15:11] Warning: conflicting stereochemistry at atom 10 ignored.\n", - "RDKit WARNING: [16:15:11] Warning: conflicting stereochemistry at atom 10 ignored.\n", - "RDKit WARNING: [16:15:40] Warning: conflicting stereochemistry at atom 10 ignored.\n", - "RDKit WARNING: [16:15:40] Warning: conflicting stereochemistry at atom 10 ignored.\n", - "RDKit WARNING: [16:26:44] Warning: conflicting stereochemistry at atom 6 ignored.\n", - "RDKit WARNING: [16:26:44] Warning: conflicting stereochemistry at atom 6 ignored.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "101001 molecules successfully imported\n" + "populating mongodb collection with compounds from SDF...\n", + "100000 molecules successfully imported\n", + "1 duplicates skipped\n" ] }, { "data": { "text/plain": [ - "101001" + "100000" ] }, - "execution_count": 15, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "# Write the first 100,000 compounds to molecules_100K. \n", - "write.writeFromSDF(db.molecules_100K, '../../../chembl_27.sdf', 'test', reg_option='standard_setting', \n", - " index_option='inchikey', chunk_size=1000, limit=100000)" + "# If necessary, write the first 100,000 compounds to molecules_100K.\n", + "if db.molecules_100K.count_documents({}) != 100000:\n", + " write.WriteFromSDF(db.molecules_100K, '../../../chembl_27.sdf', chunk_size=1000, limit=100000)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "populating mongodb collection with compounds from SDF...\n" + ] + } + ], "source": [ - "# Write the first 1,000,000 compounds to molecules_1M.\n", - "write.writeFromSDF(db.molecules_1M, '../../../chembl27_sdf', 'test', reg_option='standard_setting', \n", - " index_option='inchikey', chunk_size=1000, limit=1000000)" + "# If necessary, write the first 1,000,000 compounds to molecules_1M.\n", + "if db.molecules_1M.count_documents({}) != 1000000:\n", + " write.WriteFromSDF(db.molecules_1M, '../../../chembl_27.sdf', chunk_size=1000, limit=1000000)" ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "In molecules_100K: 101000 documents\n", - "In molecules_1M: 0 documents\n" + "In molecules_100K: 100000 documents\n", + "In molecules_1M: 180512 documents\n" ] } ], @@ -146,11 +134,22 @@ "print(f\"In molecules_1M: {db.molecules_1M.count_documents({})} documents\")" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Next, we have to prepare all of the documents in our collections for search by adding in fingerprints.\n", + "substructure.AddPatternFingerprints(db.molecules_100K)\n", + "substructure.AddPatternFingerprints(db.molecules_1M)" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Query Set Setup\n", + "### Query Set Setup\n", "For our queries, we'll use three sets of patterns identified by Greg Landrum in one of his [blog posts](http://rdkit.blogspot.com/2013/11/fingerprint-based-substructure.html) on substructure searching and discussed in this [mailing list](http://www.mail-archive.com/rdkit-discuss@lists.sourceforge.net/msg02066.html) and this [presentation](http://www.hinxton.wellcome.ac.uk/advancedcourses/MIOSS%20Greg%20Landrum.pdf). They are: \n", "- Fragments: 500 diverse molecules taken from the ZINC Fragments set\n", "- Leads: 500 diverse molecules taken from the ZINC Lead-like set\n", @@ -159,7 +158,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -184,12 +183,12 @@ "### Naive Substructure Search\n", "`substructure.SubSearchNaive` is a search that simply loops through the dataset and checks for a substructure match on each molecule. This method is not directly benchmarked here because searching through a single molecule takes upward of 5 seconds; this means that it is far too slow to feel directly interactive.\n", "### Substructure Search with Fingerprint Screening\n", - "Instead, we will benchmark the standard `SubSearch`, which makes use of fingerprint screening to dramatically increase efficiency. First, we want to see what kinds of times we are dealing with. For each of our query sets, we will search all of their elements against `molecules_100K` and `molecules_1M`, then return the median and mean query times in seconds. " + "Instead, we will benchmark the standard `SubSearch`, which makes use of fingerprint screening to dramatically increase efficiency. For each of our query sets, we will search all of their elements against `molecules_100K` and `molecules_1M`, then return the median and mean query times in seconds. " ] }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -199,34 +198,118 @@ " start = time.time()\n", " substructure.SubSearch(pattern, dataset)\n", " end = time.time()\n", - " results.append(end - start)" + " results.append(end - start)\n", + " return results" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
meanmedian
fragments0.0627400.062074
leads0.0625920.062289
pieces0.0627390.061950
\n", + "
" + ], + "text/plain": [ + " mean median\n", + "fragments 0.062740 0.062074\n", + "leads 0.062592 0.062289\n", + "pieces 0.062739 0.061950" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# Benchmark for search of all three query sets against 100K and 1M.\n", - "# This should take around five minutes; these calls can be split up if necessary.\n", + "# This should take around five minutes; these calls commented out if necessary.\n", "frag_times_100K = benchmark_query_set(fragments, db.molecules_100K)\n", - "frag_times_1M = benchmark_query_set(fragments, db.molecules_1M)\n", "lead_times_100K = benchmark_query_set(leads, db.molecules_100K)\n", - "lead_times_1M = benchmark_query_set(leads, db.molecules_1M)\n", "pieces_times_100K = benchmark_query_set(pieces, db.molecules_100K)\n", - "pieces_times_1M = benchmark_query_set(pieces, db.molecules_1M)\n", "\n", - "results = [frag_times_100K, frag_times_1M, lead_times_100K, lead_times_1M, pieces_times_100K, pieces_times_1M]\n", + "results = [frag_times_100K, lead_times_100K, pieces_times_100K]\n", + "means_100K = [np.mean(times) for times in results]\n", + "medians_100K = [np.median(times) for times in results]\n", "\n", - "means = [mean(times) for times in results]\n", - "medians = [median(times) for times in results]\n", + "data = {'mean (100K)': means, 'median (100K)': medians}\n", + "df = pd.DataFrame(data, index =['fragments', 'leads', 'pieces']) \n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Benchmark for search of all three query sets against 1M. \n", + "# This should take around five minutes; these calls can be commented out if necessary.\n", + "frag_times_1M = benchmark_query_set(fragments, db.molecules_1M)\n", + "lead_times_1M = benchmark_query_set(leads, db.molecules_1M)\n", + "pieces_times_1M = benchmark_query_set(pieces, db.molecules_1M)\n", + "\n", + "results = [frag_times_1M, lead_times_1M, pieces_times_1M]\n", + "means_1M = [np.mean(times) for times in results]\n", + "medians_1M = [np.median(times) for times in results]\n", "\n", - "data = {'mean': means, 'median': medians}\n", + "data = {'mean (1M)': means, 'median (1M)': medians}\n", "df = pd.DataFrame(data, index =['fragments', 'leads', 'pieces']) \n", "df" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Discussion\n", + "\n", + "A median search time of less than 70ms indicates decent performance, certainly fast enough to have interactive search performance on large datasets with single molecules (the traditional UI benchmark for instant feedback being 100ms). " + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -248,18 +331,6 @@ "display_name": "py37_rdkit_beta", "language": "python", "name": "py37_rdkit_beta" - }, - "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.7.7" } }, "nbformat": 4, diff --git a/docs/testing.md b/docs/testing.md index a118563..ce75d74 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -7,10 +7,15 @@ pip install -U pytest ``` ## Running Tests While you are in the top-level directory (`/your path here/mongo-rdkit`), -you can run all tests simply by opening a command line and running: +you can run all tests on OS/Linux systems simply by opening a command line and running: ``` pytest ``` +On Windows, you may have to run the following instead: +``` +python -m pytest +``` + Directory position is important because as of 7/10/20, the tests have explicit file paths to test data in the `/data` directory. @@ -21,6 +26,10 @@ a MongoDB URI to the testing framework: ``` pytest --server="YOUR_MONGO_URI" ``` +On Windows: +``` +python -m pytest --server="YOUR_MONGO_URI" +``` Passing in `"local"` will run the tests on your locally hosted MongoDB instance. diff --git a/mongordkit/Database/__pycache__/write.cpython-37.pyc b/mongordkit/Database/__pycache__/write.cpython-37.pyc deleted file mode 100644 index b0fdab4676615f4b04e22791685b637ac7ee2719..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4377 zcmeHKOLH4V5Z={uwR%`U!mD@;;gJZ4TyVj-s8nLh#x86ng`9#?6{uD_BWuw<RZbjFac?YyogX)7EEm8BX-mNaQm1zaqYP3pgceU;k zU7~e(*Qwso8jm~xtF(4Q7lk#)xA+7~x%DCQ;9cT$H*mMCa0rzmr;cwAod-JfZ)8OU zKD7e7V?$piYFpPjTfNPj?e)Fw>+Oy>_kQcW?Y-V&>jMfy?E+2+R}CI4ufr2w0-$&d1U?}nC`&|>h953VGc<6>go(~ruDc5KjGQbrv#Gs^P2Nr~p)(vC{9 zS4sA&B*kMhso*S$A-@_?IVs-JliVo7uOx+I=z(9+(t|4>XzHuf_v`I9lOkC3>QObd z=zeO^{TtfB_b^sZs`Hu;zK8MP+v93t+>`5vS`lg`RRfD_G^a*@&kXDJtfrX+t`E2q zv5-VVM(n_km>-2C7?4hDlSBd8y}r|1zrM4xA-zH@pAwrh3r5JnmQNg?vfCu^r3O_A z$INyHj?E~1C7t!HjopnVxjv4Zz_(m7wz%c7i1Bb$D!EMTIE(_%Ib?(ecI<%-B#d}$ zM=@ulKOsut#PRoumFgq&!9#-nC(MqTsk&RZBxz45V=Mg(#=wd!5;C*^df0*M!Z5Jv z)Fkh3ygRq*soE1Ohruo4S^k800Vs%Fz|R6p9Y16|f>m1)OcObtGM+^dTE4z@v;AJL zv)$d8Ds&ysiKLx=?DZK(+)p&(D!?5GAwrO9+1cLR-ct%zC6G9xce0XIat)yI_k-5j z-1-&NmPCHcA&`Zstm_3n6J-_WJs~l?=+YIa;zmu>76VjdA^t=`SuARcQ6bC|r;EJw zmngw_waG+Yeig>l&%!)GNaQ(%p1h3fHKt1ty7RThFGAZd>&rJ`dxp#QkVDu8<00eA zEf$WTxGWudnbVOIsj@1ztjOwHAzPLwN^?9B6?t54f_K5WB~Tk)1)3yO>V90W z!=2F$cuf7#^lies0(B+pdM;x^y#}|b^9JZRo7OJ;JzBe)ED~BfrH}TE&^|m^0Yb~q z2(7R{XrIpr4SOltLqao75n5?RXe&TU<{Y7|03pe*lF)ws1EKwxTJ$3j+IMFV+IK0T zl@|!DJV$7i1wtbb=zm6NJKLST{~1m3xH{72dH0ON^k2kiE^O#IO2aC0sXP!;Dhd~v zK%GASJraBS;Ykd^oUxcZUH>tMRe1%@J6=VBIXquNQAhD8ipNl#Ljiw68h;$c6DXcU z@f3(gjXw=9kwfeFGuZqrisw)~kAk3h0mTIrFQRw}1@Z%b8O19okQ$V@1SL_Qo$tGW zy93JCp!Li%-h9|I{x#5KXF%YEZ_EqU;R*5oPX0<|4u6wJ*bUdR*)VV^WIT3283Ae~ z78%68%2uNxWSEkZAn}}~hPDOiER_m68+&`(?RW9KQ;Gd7(Y-jIwOz#IQf7Q9(UI2L z!akw>RhVF!Pts{G;NQsd?Nf=N%206txY5Q5l2j;APZ7yqbbWx{F&z%q&$y3D)S)lBDNbSFddSa s498HH?vS(1*(i6L+-Sx-UO?f`=?Xe2#4TQjbV%LjvN^rJf{$VT4i~5T3IG5A diff --git a/mongordkit/Database/registration.py b/mongordkit/Database/registration.py index 876321d..acf9b26 100644 --- a/mongordkit/Database/registration.py +++ b/mongordkit/Database/registration.py @@ -14,10 +14,9 @@ DEFAULT_PREPROCESS = False DEFAULT_INDEX = 'inchikey_standard' - -RDKIT_HASH_FUNCTIONS = rdkit.Chem.rdMolHash.HashFunction.names HASH_FUNCTIONS = {} -HASH_FUNCTIONS['MoleculeHashString'] = rdMolHash.GenerateMoleculeHashString +for k, v in rdMolHash.HashFunction.names.items(): + HASH_FUNCTIONS[k] = lambda rdmol, f=v: rdMolHash.MolHash(rdmol, f) HASH_FUNCTIONS['inchi_standard'] = Chem.MolToInchi HASH_FUNCTIONS['inchikey_standard'] = Chem.MolToInchiKey HASH_FUNCTIONS['inchi_KET_15T'] = lambda rdmol: Chem.MolToInchi(rdmol, options='-KET -15T') @@ -33,7 +32,6 @@ def __init__(self): self.author = DEFAULT_AUTHOR self.pre_processed = DEFAULT_PREPROCESS self.index_option = DEFAULT_INDEX - self.rdkit_hashes = set(RDKIT_HASH_FUNCTIONS.keys()) self.hashes = set(HASH_FUNCTIONS.keys()) self.fingerprints = {} self.value_fields = {} @@ -46,16 +44,15 @@ def __repr__(self): '}' def set_index(self, new_index): - if new_index not in HASH_FUNCTIONS.keys() and new_index not in RDKIT_HASH_FUNCTIONS.keys(): + if new_index not in HASH_FUNCTIONS.keys(): raise Exception("Please add this hash first.") else: self.index_option = new_index + return def get_index_value(self, rdmol): if self.index_option in HASH_FUNCTIONS.keys(): return HASH_FUNCTIONS[self.index_option](rdmol) - elif self.index_option in RDKIT_HASH_FUNCTIONS.keys(): - return rdMolHash.MolHash(rdmol, RDKIT_HASH_FUNCTIONS[self.index_option]) else: raise Exception("Specified index option does not exist.") @@ -73,9 +70,6 @@ def remove_field(self, field_name): if field_name in self.value_fields.keys(): self.value_fields.pop(field_name) print(f'removed {field_name} from scheme') - if field_name in self.rdkit_hashes: - self.rdkit_hashes.remove(field_name) - print(f'removed {field_name} from scheme') def generate_mol_doc(self, rdmol): molDoc = { @@ -84,8 +78,6 @@ def generate_mol_doc(self, rdmol): 'smiles': Chem.MolToSmiles(rdmol), 'scheme': self.scheme_name, 'hashes': {hash_name: HASH_FUNCTIONS[hash_name](rdmol) for hash_name in self.hashes}, - 'rdkit_hashes': {hash_name: rdMolHash.MolHash(rdmol, RDKIT_HASH_FUNCTIONS[hash_name]) - for hash_name in self.rdkit_hashes}, 'fingerprints': {fp: fp_method(rdmol) for fp, fp_method in self.fingerprints.items()}, 'value_data': {field_name: value for field_name, value in self.value_fields.items()} } diff --git a/mongordkit/Database/write.py b/mongordkit/Database/write.py index 02dad52..50d37e2 100644 --- a/mongordkit/Database/write.py +++ b/mongordkit/Database/write.py @@ -1,13 +1,14 @@ import pymongo, pickle from bson import Binary from rdkit import Chem +import rdkit from rdkit.Chem import rdMolHash from rdkit.Chem import rdinchi -from .registration import MolDocScheme, HASH_FUNCTIONS, RDKIT_HASH_FUNCTIONS +from .registration import MolDocScheme, HASH_FUNCTIONS def WriteFromSDF(mol_collection, sdf, scheme=MolDocScheme(), - reg_collection=None, chunk_size=100, limit=None): + reg_collection=None, chunk_size=100, limit=None, warnings=False): """ Writes the contents of SDF to MOL_COLLECTION and creates an index on the index specificed in SCHEME. Optional parameters: @@ -22,14 +23,10 @@ def WriteFromSDF(mol_collection, sdf, scheme=MolDocScheme(), :param chunk_size: Integer indicating how many molecules inserted at a time. :param limit: Integer indicating how many molecules to insert. """ + if not warnings: + rdkit.RDLogger.DisableLog('rdApp.*') molecules = mol_collection print('populating mongodb collection with compounds from SDF...') - # This is placeholder code for when more registration options exist. - # if index_option not in VALID_HASHES: - # options = ', '.join(VALID_HASHES) - # raise ValueError("index_option must be one of {}".format(options)) - # else: - # hash = HASH_FUNCTIONS[index_option] chunk = [] inserted = 0 duplicates = 0 @@ -81,12 +78,6 @@ def WriteFromMolList(mol_collection, list, scheme=MolDocScheme(), """ molecules = mol_collection print('populating mongodb collection with compounds from list...') - # This is placeholder code for when more registration options exist. - # if index_option not in VALID_HASHES: - # options = ', '.join(VALID_HASHES) - # raise ValueError("index_option must be one of {}".format(options)) - # else: - # hash = HASH_FUNCTIONS[index_option] chunk = [] inserted = 0 duplicates = 0 diff --git a/mongordkit/Search/similarity.py b/mongordkit/Search/similarity.py index b31ac43..e31c495 100644 --- a/mongordkit/Search/similarity.py +++ b/mongordkit/Search/similarity.py @@ -210,7 +210,7 @@ def AddHashCollections(db, mol_collection): {'$push': {'molecules': moldoc['_id']}}, True) -def SimSearchLSH(mol, db, mol_collection, perm_collection, threshold=DEFAULT_THRESHOLD): +def SimSearchLSH(mol, db, mol_collection, perm_collection, count_collection, threshold=DEFAULT_THRESHOLD): """ Conducts a similarity search for query molecule MOL in MOL_COLLECTION with Tanimoto threshold THRESHOLD. @@ -236,8 +236,8 @@ def SimSearchLSH(mol, db, mol_collection, perm_collection, threshold=DEFAULT_THR except ZeroDivisionError: fp_max = float('inf') req_common_count = qfp_count - fp_min + 1 - if 'mfp' in db.list_collection_names(): - req_common_bits = [count['_id'] for count in db.mfp_counts.find( + if count_collection: + req_common_bits = [count['_id'] for count in count_collection.find( {'_id': {'$in': qfp}}).sort('count', 1).limit(req_common_count)] else: req_common_bits = qfp[:req_common_count] diff --git a/mongordkit/Search/tests/test_similarity.py b/mongordkit/Search/tests/test_similarity.py index 52bc7dc..ee59854 100644 --- a/mongordkit/Search/tests/test_similarity.py +++ b/mongordkit/Search/tests/test_similarity.py @@ -139,7 +139,7 @@ def test_similarity_accuracy_LSH(mongoURI): smiles = Chem.MolToSmiles(mol) search_python = [result[1] for result in utils.similaritySearchPython(mol, db_python, t)] search_mongo_LSH = [result[1] for result in - similarity.SimSearchLSH(mol, db_mongo, db_mongo.molecules, db_mongo.permutations, t)] + similarity.SimSearchLSH(mol, db_mongo, db_mongo.molecules, db_mongo.permutations, db_mongo.mfp_counts, t)] assert set(search_mongo_LSH).issubset(search_python) print(counter) counter += 1 \ No newline at end of file From be283f88865ab10780ce9a87b0cc662a8577b587 Mon Sep 17 00:00:00 2001 From: Christopher Zou Date: Tue, 18 Aug 2020 15:20:03 -0400 Subject: [PATCH 4/7] fix hash test --- mongordkit/Database/tests/test_write.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mongordkit/Database/tests/test_write.py b/mongordkit/Database/tests/test_write.py index 1acbe63..d09b240 100644 --- a/mongordkit/Database/tests/test_write.py +++ b/mongordkit/Database/tests/test_write.py @@ -32,7 +32,7 @@ def test_hashes(self): data_scheme = registration.MolDocScheme() data_scheme.set_index("CanonicalSmiles") assert 200 == write.WriteFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', data_scheme) - data_scheme.set_index("MoleculeHashString") + data_scheme.set_index("inchi_standard") assert 200 == write.WriteFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', data_scheme) def test_uniqueInsertion(self): From 6cc6321fde8685ae11847b6a775ff977d5eb9976 Mon Sep 17 00:00:00 2001 From: Christopher Zou Date: Tue, 25 Aug 2020 12:54:52 -0400 Subject: [PATCH 5/7] Push up write benchmarks --- ...ng and Writing to MongoDB-checkpoint.ipynb | 18 +- ...y and Substructure Search-checkpoint.ipynb | 5 +- .../Creating and Writing to MongoDB.ipynb | 18 +- docs/notebooks/Similarity Benchmarking.ipynb | 25 +- .../Similarity and Substructure Search.ipynb | 5 +- .../notebooks/Substructure Benchmarking.ipynb | 28 +- .../Write and Registration Benchmarking.ipynb | 427 ++++++++++++++++++ mongordkit/Database/registration.py | 15 +- mongordkit/Database/tests/test_write.py | 2 +- requirements.txt | 24 - setup.txt | 56 --- 11 files changed, 505 insertions(+), 118 deletions(-) create mode 100644 docs/notebooks/Write and Registration Benchmarking.ipynb delete mode 100644 requirements.txt delete mode 100644 setup.txt diff --git a/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb b/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb index c581d97..fdbf379 100644 --- a/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb +++ b/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb @@ -41,7 +41,10 @@ "source": [ "client = pymongo.MongoClient()\n", "client.drop_database('demo_db')\n", - "demo_db = client.demo_db" + "demo_db = client.demo_db\n", + "\n", + "# Disable rdkit warnings\n", + "rdkit.RDLogger.DisableLog('rdApp.*')" ] }, { @@ -90,7 +93,7 @@ "\n", "It does this in two parts. First, it defines the global variable `HASH_FUNCTIONS` as a dictionary that maps hash function names to methods. It also defines the global variables `DEFAULT_SCHEME_NAME`, `DEFAULT_AUTHOR`, `DEFAULT_PREPROCESS`, and `DEFAULT_INDEX`, which are used in scheme creation and are thus defined for easy configuration. \n", "\n", - "Second, the file defines the `MolDocScheme` object, which stores scheme information in its instance variables and is passed into `.write` methods in order to specify molecule document format. By default, `MolDocScheme` includes scheme name, author, whether or not the molecule has been pre-processed, an index option, hashes, fingerprints, and value fields. All of the information contained in a `MolDocScheme` object can be used directly to generate documents for molecules:" + "Second, the file defines the `MolDocScheme` object, which stores scheme information in its instance variables and is passed into `.write` methods in order to specify molecule document format. By default, `MolDocScheme` includes scheme name, author, whether or not the molecule has been pre-processed, an index option, two hashes, fingerprints, and value fields. All of the information contained in a `MolDocScheme` object can be used directly to generate documents for molecules:" ] }, { @@ -201,7 +204,8 @@ } ], "source": [ - "scheme.remove_field('AnonymousGraph')\n", + "scheme.remove_field('CanonicalSmiles')\n", + "scheme.add_hash_field('MolFormula')\n", "scheme.set_index('MolFormula')\n", "scheme.generate_mol_doc(rdmol)" ] @@ -583,6 +587,7 @@ "- get_index_value(self, rdmol) --> *calculated index value*\n", "- add_hash_field(self, field_name, field_method) --> *None*\n", "- add_value_field(self, field_name, field_value) --> *None*\n", + "- add_all_hashes(self) --> *None*\n", "- remove_field(self, field_name) --> *None*\n", "- generate_mol_doc(self, rdmol) --> *Dict: document representing molecule according to scheme*" ] @@ -602,13 +607,6 @@ "\n", "mongordkit.Database.write.**WriteFromMolList**(database, list, scheme=MolDocScheme(), reg_collection=None, chunk_size=100, limit=None) --> *int: number of molecules imported*" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/docs/notebooks/.ipynb_checkpoints/Similarity and Substructure Search-checkpoint.ipynb b/docs/notebooks/.ipynb_checkpoints/Similarity and Substructure Search-checkpoint.ipynb index 82c3f12..33285bc 100644 --- a/docs/notebooks/.ipynb_checkpoints/Similarity and Substructure Search-checkpoint.ipynb +++ b/docs/notebooks/.ipynb_checkpoints/Similarity and Substructure Search-checkpoint.ipynb @@ -41,7 +41,10 @@ "source": [ "client = pymongo.MongoClient()\n", "client.drop_database('demo_db')\n", - "demo_db = client.demo_db" + "demo_db = client.demo_db\n", + "\n", + "# Disable rdkit warnings\n", + "rdkit.RDLogger.DisableLog('rdApp.*')" ] }, { diff --git a/docs/notebooks/Creating and Writing to MongoDB.ipynb b/docs/notebooks/Creating and Writing to MongoDB.ipynb index c581d97..fdbf379 100644 --- a/docs/notebooks/Creating and Writing to MongoDB.ipynb +++ b/docs/notebooks/Creating and Writing to MongoDB.ipynb @@ -41,7 +41,10 @@ "source": [ "client = pymongo.MongoClient()\n", "client.drop_database('demo_db')\n", - "demo_db = client.demo_db" + "demo_db = client.demo_db\n", + "\n", + "# Disable rdkit warnings\n", + "rdkit.RDLogger.DisableLog('rdApp.*')" ] }, { @@ -90,7 +93,7 @@ "\n", "It does this in two parts. First, it defines the global variable `HASH_FUNCTIONS` as a dictionary that maps hash function names to methods. It also defines the global variables `DEFAULT_SCHEME_NAME`, `DEFAULT_AUTHOR`, `DEFAULT_PREPROCESS`, and `DEFAULT_INDEX`, which are used in scheme creation and are thus defined for easy configuration. \n", "\n", - "Second, the file defines the `MolDocScheme` object, which stores scheme information in its instance variables and is passed into `.write` methods in order to specify molecule document format. By default, `MolDocScheme` includes scheme name, author, whether or not the molecule has been pre-processed, an index option, hashes, fingerprints, and value fields. All of the information contained in a `MolDocScheme` object can be used directly to generate documents for molecules:" + "Second, the file defines the `MolDocScheme` object, which stores scheme information in its instance variables and is passed into `.write` methods in order to specify molecule document format. By default, `MolDocScheme` includes scheme name, author, whether or not the molecule has been pre-processed, an index option, two hashes, fingerprints, and value fields. All of the information contained in a `MolDocScheme` object can be used directly to generate documents for molecules:" ] }, { @@ -201,7 +204,8 @@ } ], "source": [ - "scheme.remove_field('AnonymousGraph')\n", + "scheme.remove_field('CanonicalSmiles')\n", + "scheme.add_hash_field('MolFormula')\n", "scheme.set_index('MolFormula')\n", "scheme.generate_mol_doc(rdmol)" ] @@ -583,6 +587,7 @@ "- get_index_value(self, rdmol) --> *calculated index value*\n", "- add_hash_field(self, field_name, field_method) --> *None*\n", "- add_value_field(self, field_name, field_value) --> *None*\n", + "- add_all_hashes(self) --> *None*\n", "- remove_field(self, field_name) --> *None*\n", "- generate_mol_doc(self, rdmol) --> *Dict: document representing molecule according to scheme*" ] @@ -602,13 +607,6 @@ "\n", "mongordkit.Database.write.**WriteFromMolList**(database, list, scheme=MolDocScheme(), reg_collection=None, chunk_size=100, limit=None) --> *int: number of molecules imported*" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/docs/notebooks/Similarity Benchmarking.ipynb b/docs/notebooks/Similarity Benchmarking.ipynb index 7ebd8fb..701d377 100644 --- a/docs/notebooks/Similarity Benchmarking.ipynb +++ b/docs/notebooks/Similarity Benchmarking.ipynb @@ -47,13 +47,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# Initialize the client that will connect to the database.\n", "client = pymongo.MongoClient()\n", - "db = client.test" + "db = client.test\n", + "chembl = '../../../chembl_27.sdf'\n", + "\n", + "# Disable rdkit warnings\n", + "rdkit.RDLogger.DisableLog('rdApp.*')" ] }, { @@ -64,7 +68,7 @@ "source": [ "# If necessary, write the first 100,000 compounds to molecules_100K.\n", "if db.molecules_100K.count_documents({}) != 100000:\n", - " write.WriteFromSDF(db.molecules_100K, '../../../chembl_27.sdf', chunk_size=1000, limit=100000)" + " write.WriteFromSDF(db.molecules_100K, chembl, chunk_size=1000, limit=100000)" ] }, { @@ -75,14 +79,23 @@ "source": [ "# If necessary, write the first 1,000,000 compounds to molecules_1M.\n", "if db.molecules_1M.count_documents({}) != 1000000:\n", - " write.writeFromSDF(db.molecules_1M, '../../../chembl_27.sdf', chunk_size=1000, limit=1000000)" + " write.writeFromSDF(db.molecules_1M, chembl, chunk_size=1000, limit=1000000)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "In molecules_100K: 100000 documents\n", + "In molecules_1M: 629512 documents\n" + ] + } + ], "source": [ "# Let's ensure that there are actually 100,000 and 1M documents in these collections, respectively.\n", "print(f\"In molecules_100K: {db.molecules_100K.count_documents({})} documents\")\n", diff --git a/docs/notebooks/Similarity and Substructure Search.ipynb b/docs/notebooks/Similarity and Substructure Search.ipynb index 82c3f12..33285bc 100644 --- a/docs/notebooks/Similarity and Substructure Search.ipynb +++ b/docs/notebooks/Similarity and Substructure Search.ipynb @@ -41,7 +41,10 @@ "source": [ "client = pymongo.MongoClient()\n", "client.drop_database('demo_db')\n", - "demo_db = client.demo_db" + "demo_db = client.demo_db\n", + "\n", + "# Disable rdkit warnings\n", + "rdkit.RDLogger.DisableLog('rdApp.*')" ] }, { diff --git a/docs/notebooks/Substructure Benchmarking.ipynb b/docs/notebooks/Substructure Benchmarking.ipynb index ef27503..53a5ef7 100644 --- a/docs/notebooks/Substructure Benchmarking.ipynb +++ b/docs/notebooks/Substructure Benchmarking.ipynb @@ -52,16 +52,22 @@ "metadata": {}, "source": [ "### Database Setup\n", - "Here we set up a database called `test` that will hold our molecules. We will construct a collection called `molecules_100K` to hold the first 100,000 molecules in the ChEMBL_27 dataset and a collection called `molecules_1M` to hold the first 1,000,000 molecules in the ChEMBL_27 dataset. If you have already run benchmarks from `mongo-rdkit` on your local MongoDB instance, these should have been set up already." + "Here we set up a database called `test` that will hold our molecules. We will construct a collection called `molecules_100K` to hold the first 100,000 molecules in the ChEMBL_27 dataset and a collection called `molecules_1M` to hold the first 1,000,000 molecules in the ChEMBL_27 dataset. If you have already run search or similarity benchmarks from `mongo-rdkit` on your local MongoDB instance, these should have been set up already." ] }, { - "cell_type": "raw", + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "# Initialize the client that will connect to the database.\n", "client = pymongo.MongoClient()\n", - "db = client.test" + "db = client.test\n", + "chembl = '../../../chembl_27.sdf'\n", + "\n", + "# Disable rdkit warnings\n", + "rdkit.RDLogger.DisableLog('rdApp.*')" ] }, { @@ -92,7 +98,7 @@ "source": [ "# If necessary, write the first 100,000 compounds to molecules_100K.\n", "if db.molecules_100K.count_documents({}) != 100000:\n", - " write.WriteFromSDF(db.molecules_100K, '../../../chembl_27.sdf', chunk_size=1000, limit=100000)" + " write.WriteFromSDF(db.molecules_100K, chembl, chunk_size=1000, limit=100000)" ] }, { @@ -111,7 +117,7 @@ "source": [ "# If necessary, write the first 1,000,000 compounds to molecules_1M.\n", "if db.molecules_1M.count_documents({}) != 1000000:\n", - " write.WriteFromSDF(db.molecules_1M, '../../../chembl_27.sdf', chunk_size=1000, limit=1000000)" + " write.WriteFromSDF(db.molecules_1M, chembl, chunk_size=1000, limit=1000000)" ] }, { @@ -331,6 +337,18 @@ "display_name": "py37_rdkit_beta", "language": "python", "name": "py37_rdkit_beta" + }, + "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.7.7" } }, "nbformat": 4, diff --git a/docs/notebooks/Write and Registration Benchmarking.ipynb b/docs/notebooks/Write and Registration Benchmarking.ipynb new file mode 100644 index 0000000..468c5d0 --- /dev/null +++ b/docs/notebooks/Write and Registration Benchmarking.ipynb @@ -0,0 +1,427 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Write and Registration Benchmarks\n", + "\n", + "These benchmarks were originally run on an early 2015 MacBook Pro with a 2.7 GHz dual-core i5 processor and 8GB of memory. All molecules are written into a data directory stored locally via `--dbpath`.\n", + "\n", + "They make use of molecules found in the data folder. \n", + "\n", + "Last updated: 8/24/20 by Christopher Zou\n", + "\n", + "## Setup Work\n", + "### Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from mongordkit.Database import write, registration\n", + "from rdkit import Chem\n", + "import rdkit\n", + "import numpy as np\n", + "import time\n", + "import pymongo\n", + "import mongomock\n", + "import matplotlib\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Database Setup\n", + "Here we set up a database called `test` that will hold our molecules. We will construct a collection called `molecules_write_testing` to benchmark the speed of writing to a collection." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# Initialize the client that will connect to the database.\n", + "client = pymongo.MongoClient()\n", + "db = client.test\n", + "db.molecules_write_testing.drop()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Defining Some Useful Variables" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "hash_functions = registration.HASH_FUNCTIONS\n", + "first_200_mols = '../../data/test_data/first_200.props.sdf'\n", + "chembl = '../../../chembl_27.sdf'\n", + "\n", + "# Disable RDLogger to reduce system output.\n", + "rdkit.RDLogger.DisableLog('rdApp.*')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Benchmarking Write" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We want to know the performance of `write.WriteFromSDF`. To find out, let's write the first 1000-10000 (incrementing by 1000 every time) molecules of a ChEMBL dataset using a scheme that contains all 23 available hashes and take median write times:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "testing 1000\n", + "populating mongodb collection with compounds from SDF...\n", + "1000 molecules successfully imported\n", + "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n", + "1000 molecules successfully imported\n", + "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n", + "1000 molecules successfully imported\n", + "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n", + "1000 molecules successfully imported\n", + "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n", + "1000 molecules successfully imported\n", + "0 duplicates skipped\n", + "testing 2000\n", + "populating mongodb collection with compounds from SDF...\n", + "2000 molecules successfully imported\n", + "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n", + "2000 molecules successfully imported\n", + "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n", + "2000 molecules successfully imported\n", + "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n", + "2000 molecules successfully imported\n", + "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n", + "2000 molecules successfully imported\n", + "0 duplicates skipped\n", + "testing 3000\n", + "populating mongodb collection with compounds from SDF...\n", + "3000 molecules successfully imported\n", + "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n" + ] + } + ], + "source": [ + "repetitions = 5\n", + "scheme = registration.MolDocScheme()\n", + "scheme.add_all_hashes()\n", + "times = []\n", + "limits = [1000 + (i * 1000) for i in range(11)]\n", + "for number in limits:\n", + " temp_times = []\n", + " print(f'testing {number}')\n", + " for i in range(repetitions):\n", + " mol_collection = db.molecules_write_testing\n", + " start = time.time()\n", + " write.WriteFromSDF(mol_collection, chembl, scheme, limit=number)\n", + " end = time.time()\n", + " duration = end - start\n", + " mol_collection.drop()\n", + " temp_times.append(duration)\n", + " times.append([number, np.mean(temp_times)])" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[2000, 14.187205600738526],\n", + " [2100, 14.940004205703735],\n", + " [2200, 15.965514373779296],\n", + " [2300, 16.910987186431885],\n", + " [2400, 23.27452983856201],\n", + " [2500, 21.29524955749512],\n", + " [2600, 23.414347171783447],\n", + " [2700, 25.251486158370973],\n", + " [2800, 28.250892400741577],\n", + " [2900, 28.316519117355348],\n", + " [3000, 32.57432060241699]]" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "x_values = [i[0] for i in times]\n", + "y_values = [i[1] for i in times]\n", + "plt.plot(x_values, y_values)\n", + "times" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's also divide each mean value by the number of molecules written to get a measure of how long it takes to write each molecule:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "time_per_molecule = []\n", + "for i in range(times):\n", + " time_per_molecule.append(y_values[i] / x_values[i])\n", + " \n", + "plt.plot(x_values, time_per_molecule)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The amount of time required to insert each molecule appears to stay relatively constant between 0.02 and 0.025 seconds; " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Breaking Down Write Times\n", + "### Hashes\n", + "`mongordkit.registration` provides (as of time of writing) 23 different molecular hash options. Calculating all of these hash options when writing molecules into a database results in extremely long write times. Here, we calculate the median time required to calculate each hash for the first 200 molecules in a ChEMBL database. " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "median_times = []\n", + "\n", + "for key in hash_functions: \n", + " times = []\n", + " for rdmol in Chem.ForwardSDMolSupplier(first_200_mols):\n", + " start = time.time()\n", + " _ = hash_functions[key](rdmol)\n", + " end = time.time()\n", + " times.append(end - start)\n", + " median_times.append([key, np.median(times)])" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAACP4AAAJNCAYAAACrlCnmAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjMsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+AADFEAAAgAElEQVR4nOzdb6ye933X8c83PiTdGMtoa4k2KTopcVW5ogwR+mTiybopqTwUxJLNkYAKdQS2RENMAhxtKlKkgKMJ+qBqhYKSEIWiJIumzcwekUZBQwiauKh/kkBUK3GpaRGuUqVDWxKcfnngu+LInHN8zHL1Pt/m9ZKOfN+/63f9/L2ev3Xd1d0BAAAAAAAAAABmuWrdAwAAAAAAAAAAAFdO+AMAAAAAAAAAAAMJfwAAAAAAAAAAYCDhDwAAAAAAAAAADCT8AQAAAAAAAACAgTbWPcA6vfOd7+zNzc11jwEAAAAAAAAAANv6/Oc//83uPrjdtbd0+LO5uZnTp0+vewwAAAAAAAAAANhWVX11p2t+6gsAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADCQ8AcAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADCQ8AcAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADDQxroHAAAAAAAAgLeCzWMn1z3CvnX2+JF1jwAAI3njDwAAAAAAAAAADCT8AQAAAAAAAACAgYQ/AAAAAAAAAAAwkPAHAAAAAAAAAAAGEv4AAAAAAAAAAMBAwh8AAAAAAAAAABhI+AMAAAAAAAAAAAMJfwAAAAAAAAAAYCDhDwAAAAAAAAAADCT8AQAAAAAAAACAgYQ/AAAAAAAAAAAwkPAHAAAAAAAAAAAGEv4AAAAAAAAAAMBAwh8AAAAAAAAAABhI+AMAAAAAAAAAAAMJfwAAAAAAAAAAYCDhDwAAAAAAAAAADCT8AQAAAAAAAACAgYQ/AAAAAAAAAAAw0KLhT1XdUlUvVNWZqjq2zfVrqurx1fXPVdXmlmv3rNZfqKqbL3dmVf3zqnqpqr6w+vvRJZ8NAAAAAAAAAADWaWOpg6vqQJJPJfnJJOeSPFNVJ7r7+S3bPpbkW919Y1UdTXJ/kp+tqsNJjib5QJJ3J/mdqnrf6p7dzvy73f3kUs8EAAAAAAAAAAD7xZJv/PlQkjPd/WJ3v57ksSS3XrLn1iSPrD4/meTDVVWr9ce6+7XufinJmdV5ezkTAAAAAAAAAAC+7y0Z/lyX5Gtbvp9brW27p7svJHklyTt2ufdyZ95XVV+qqk9U1TXbDVVVd1bV6ao6ff78+St/KgAAAAAAAAAA2AeWDH9qm7Xe454rXU+Se5K8P8mfT/L2JH9/u6G6+4Huvqm7bzp48OB2WwAAAAAAAAAAYN9bMvw5l+Q9W75fn+TrO+2pqo0k1yZ5eZd7dzyzu7/RF72W5OFc/FkwAAAAAAAAAAD4vrRk+PNMkkNVdUNVXZ3kaJITl+w5keSjq8+3Jflsd/dq/WhVXVNVNyQ5lOTp3c6sqnet/q0kfynJsws+GwAAAAAAAAAArNXGUgd394WqujvJU0kOJHmou5+rqnuTnO7uE0keTPJoVZ3JxTf9HF3d+1xVPZHk+SQXktzV3W8kyXZnrv7Lz1TVwVz8ObAvJPlbSz0bAAAAAAAAAACs22LhT5J096kkpy5Z+/iWz68muX2He+9Lct9ezlyt//gfdl4AAAAAAAAAAJhiyZ/6AgAAAAAAAAAAFiL8AQAAAAAAAACAgYQ/AAAAAAAAAAAwkPAHAAAAAAAAAAAGEv4AAAAAAAAAAMBAwh8AAAAAAAAAABhI+AMAAAAAAAAAAAMJfwAAAAAAAAAAYCDhDwAAAAAAAAAADCT8AQAAAAAAAACAgYQ/AAAAAAAAAAAwkPAHAAAAAAAAAAAGEv4AAAAAAAAAAMBAwh8AAAAAAAAAABhI+AMAAAAAAAAAAAMJfwAAAAAAAAAAYCDhDwAAAAAAAAAADCT8AQAAAAAAAACAgYQ/AAAAAAAAAAAwkPAHAAAAAAAAAAAGEv4AAAAAAAAAAMBAwh8AAAAAAAAAABhI+AMAAAAAAAAAAAMJfwAAAAAAAAAAYCDhDwAAAAAAAAAADCT8AQAAAAAAAACAgYQ/AAAAAAAAAAAwkPAHAAAAAAAAAAAGEv4AAAAAAAAAAMBAwh8AAAAAAAAAABhI+AMAAAAAAAAAAAMJfwAAAAAAAAAAYCDhDwAAAAAAAAAADCT8AQAAAAAAAACAgYQ/AAAAAAAAAAAwkPAHAAAAAAAAAAAGEv4AAAAAAAAAAMBAwh8AAAAAAAAAABhI+AMAAAAAAAAAAAMJfwAAAAAAAAAAYCDhDwAAAAAAAAAADCT8AQAAAAAAAACAgYQ/AAAAAAAAAAAwkPAHAAAAAAAAAAAGEv4AAAAAAAAAAMBAwh8AAAAAAAAAABhI+AMAAAAAAAAAAAMJfwAAAAAAAAAAYCDhDwAAAAAAAAAADCT8AQAAAAAAAACAgYQ/AAAAAAAAAAAwkPAHAAAAAAAAAAAGEv4AAAAAAAAAAMBAG+seAAAAAAAAgPXbPHZy3SPsW2ePH1n3CAAA2/LGHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADCQ8AcAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADCQ8AcAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADCQ8AcAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADCQ8AcAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMtGj4U1W3VNULVXWmqo5tc/2aqnp8df1zVbW55do9q/UXqurmKzjzk1X1v5Z6JgAAAAAAAAAA2A8WC3+q6kCSTyX5SJLDSe6oqsOXbPtYkm91941JPpHk/tW9h5McTfKBJLck+XRVHbjcmVV1U5IfWeqZAAAAAAAAAABgv1jyjT8fSnKmu1/s7teTPJbk1kv23JrkkdXnJ5N8uKpqtf5Yd7/W3S8lObM6b8czV1HQryb5ews+EwAAAAAAAAAA7AtLhj/XJfnalu/nVmvb7unuC0leSfKOXe7d7cy7k5zo7m/sNlRV3VlVp6vq9Pnz56/ogQAAAAAAAAAAYL9YMvypbdZ6j3uuaL2q3p3k9iSfvNxQ3f1Ad9/U3TcdPHjwctsBAAAAAAAAAGBfWjL8OZfkPVu+X5/k6zvtqaqNJNcmeXmXe3da/7NJbkxypqrOJvnBqjrzZj0IAAAAAAAAAADsN0uGP88kOVRVN1TV1UmOJjlxyZ4TST66+nxbks92d6/Wj1bVNVV1Q5JDSZ7e6czuPtndf6K7N7t7M8nvd/eNCz4bAAAAAAAAAACs1cZSB3f3haq6O8lTSQ4keai7n6uqe5Oc7u4TSR5M8ujq7Twv52LIk9W+J5I8n+RCkru6+40k2e7MpZ4BAAAAAAAAAAD2q8XCnyTp7lNJTl2y9vEtn19NcvsO996X5L69nLnNnh/6/5kXAAAAAAAAmGvz2Ml1j7BvnT1+ZN0jALCAJX/qCwAAAAAAAAAAWIjwBwAAAAAAAAAABhL+AAAAAAAAAADAQMIfAAAAAAAAAAAYSPgDAAAAAAAAAAADCX8AAAAAAAAAAGAg4Q8AAAAAAAAAAAwk/AEAAAAAAAAAgIGEPwAAAAAAAAAAMJDwBwAAAAAAAAAABhL+AAAAAAAAAADAQMIfAAAAAAAAAAAYSPgDAAAAAAAAAAADCX8AAAAAAAAAAGAg4Q8AAAAAAAAAAAwk/AEAAAAAAAAAgIGEPwAAAAAAAAAAMJDwBwAAAAAAAAAABhL+AAAAAAAAAADAQMIfAAAAAAAAAAAYaGPdAwAAAAAAAAAww+axk+seYd86e/zIukcA3oK88QcAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADCQ8AcAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADCQ8AcAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADCQ8AcAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADCQ8AcAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADCQ8AcAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADCQ8AcAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADCQ8AcAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADCQ8AcAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgoEXDn6q6papeqKozVXVsm+vXVNXjq+ufq6rNLdfuWa2/UFU3X+7Mqnqwqr5YVV+qqier6oeWfDYAAAAAAAAAAFinxcKfqjqQ5FNJPpLkcJI7qurwJds+luRb3X1jkk8kuX917+EkR5N8IMktST5dVQcuc+bf6e4/090fTPLfkty91LMBAAAAAAAAAMC6LfnGnw8lOdPdL3b360keS3LrJXtuTfLI6vOTST5cVbVaf6y7X+vul5KcWZ2345nd/e0kWd3/A0l6wWcDAAAAAAAAAIC1WjL8uS7J17Z8P7da23ZPd19I8kqSd+xy765nVtXDSf5Hkvcn+eR2Q1XVnVV1uqpOnz9//sqfCgAAAAAAAAAA9oElw5/aZu3St/DstOdK1y9+6P7rSd6d5L8k+dnthuruB7r7pu6+6eDBg9ttAQAAAAAAAACAfW/J8Odckvds+X59kq/vtKeqNpJcm+TlXe697Jnd/UaSx5P89B/6CQAAAAAAAAAAYJ9aMvx5Jsmhqrqhqq5OcjTJiUv2nEjy0dXn25J8trt7tX60qq6pqhuSHEry9E5n1kU3JklVVZK/mOS/LvhsAAAAAAAAAACwVhtLHdzdF6rq7iRPJTmQ5KHufq6q7k1yurtPJHkwyaNVdSYX3/RzdHXvc1X1RJLnk1xIctfqTT7Z4cyrkjxSVT+ciz8H9sUkP7/UswEAAAAAAAAAwLotFv4kSXefSnLqkrWPb/n8apLbd7j3viT37fHM7yT5sTdhZAAAAAAAAAAAGGHJn/oCAAAAAAAAAAAWIvwBAAAAAAAAAICBLvtTX1V1fZKjSf5Ckncn+YMkzyY5meS3Vz+zBQAAAAAAAAAAfA/tGv5U1cNJrkvyW0nuT/I/k7wtyfuS3JLkl6vqWHf/7tKDAgAAAAAAAAAA/9fl3vjzj7v72W3Wn03y61V1dZI/+eaPBQAAAAAAAAAA7Oaq3S5uF/1U1R+vqg+urr/e3WeWGg4AAAAAAAAAANjeruHPd1XVv6uqH66qtyf5YpKHq+qfLDsaAAAAAAAAAACwkz2FP0mu7e5vJ/nLSR7u7j+X5CeWGwsAAAAAAAAAANjNXsOfjap6V5KfSfJbC84DAAAAAAAAAADswV7Dn3uTPJXkTHc/U1XvTfKV5cYCAAAAAAAAAAB2s7GXTd39a0l+bcv3F5P89FJDAQAAAAAAAAAAu9v1jT9V9StV9fZdrv94Vf3Umz8WAAAAAAAAAACwm8u98efLSf5VVb2a5D8nOZ/kbUkOJfnRJL+T5B8uOiEAAAAAAAAAAPD/2DX86e7fTPKbVXUoyY8leVeSbyf5F0nu7O4/WH5EAAAAAAAAAADgUpd740+SpLu/kuQrC88CAAAAAAAAAADs0VXrHgAAAAAAAAAAALhywh8AAAAAAAAAABhI+AMAAAAAAAAAAAPtKfypqvdV1b+pqmdX3z9YVb+y7GgAAAAAAAAAAMBO9vrGn3+W5J4k/ztJuvtLSY4uNRQAAAAAAAAAALC7vYY/P9jdT1+yduHNHgYAAAAAAAAAANibvYY/36yqP5Wkk6SqbkvyjcWmAgAAAAAAAAAAdrWxx313JXkgyfur6r8neSnJX1lsKgAAAAAAAAAAYFd7Cn+6+8UkP1FVfzTJVd39e8uOBQAAAAAAAAAA7GZP4U9V/UiSv5ZkM8lGVSVJuvsXF5sMAAAAAAAAAADY0V5/6utUkv+U5MtJvrPcOAAAAAAAAAAAwF7sNfx5W3f/0qKTAAAAAAAAAAAAe3bVHvc9WlV/o6reVVVv/+7fopMBAAAAAAAAAAA72usbf15P8qtJfjlJr9Y6yXuXGAoAAAAAAAAAANjdXsOfX0pyY3d/c8lhAAAAAAAAAACAvdnrT309l+T3lxwEAAAAAAAAAADYu72+8eeNJF+oqn+b5LXvLnb3Ly4yFQAAAAAAAAAAsKu9hj+/sfoDAAAAAAAAAAD2gT2FP939yNKDAAAAAMB+tHns5LpH2LfOHj+y7hEAAADgLW3X8Keqnujun6mqLyfpS6939wcXmwwAAAAAAAAAANjR5d7487dX//7U0oMAAAAAAAAAAAB7d9VuF7v7G6uPv9DdX936l+QXlh8PAAAAAAAAAADYzq7hzxY/uc3aR97MQQAAAAAAAAAAgL3b9ae+qurnc/HNPu+tqi9tufTHkvyHJQcDAAAAAAAAAAB2tmv4k+RfJvntJP8oybEt67/X3S8vNhUAAAAAAAAAALCrXcOf7n4lyStJ7vjejAMAAAAAAAAAAOzFVeseAAAAAAAAAAAAuHLCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADCQ8AcAAAAAAAAAAAYS/gAAAAAAAAAAwEDCHwAAAAAAAAAAGEj4AwAAAAAAAAAAAwl/AAAAAAAAAABgIOEPAAAAAAAAAAAMJPwBAAAAAAAAAICBhD8AAAAAAAAAADCQ8AcAAAAAAAAAAAbaWPcAsNXmsZPrHmHfOnv8yLpHAAAAAAAAAAD2EW/8AQAAAAAAAACAgYQ/AAAAAAAAAAAwkPAHAAAAAAAAAAAGEv4AAAAAAAAAAMBAwh8AAAAAAAAAABhI+AMAAAAAAAAAAAMJfwAAAAAAAAAAYCDhDwAAAAAAAAAADCT8AQAAAAAAAACAgTbWPQAAAACsy+axk+seYd86e/zIukcAAAAAAC7DG38AAAAAAAAAAGAg4Q8AAAAAAAAAAAwk/AEAAAAAAAAAgIGEPwAAAAAAAAAAMJDwBwAAAAAAAAAABhL+AAAAAAAAAADAQMIfAAAAAAAAAAAYSPgDAAAAAAAAAAADCX8AAAAAAAAAAGAg4Q8AAAAAAAAAAAwk/AEAAAAAAAAAgIGEPwAAAAAAAAAAMJDwBwAAAAAAAAAABhL+AAAAAAAAAADAQBvrHgAAAIDtbR47ue4R9q2zx4+sewQAAAAAgLXzxh8AAAAAAAAAABhI+AMAAAAAAAAAAAMJfwAAAAAAAAAAYCDhDwAAAAAAAAAADCT8AQAAAAAAAACAgYQ/AAAAAAAAAAAwkPAHAAAAAAAAAAAGWjT8qapbquqFqjpTVce2uX5NVT2+uv65qtrccu2e1foLVXXz5c6sqs+s1p+tqoeq6o8s+WwAAAAAAAAAALBOi4U/VXUgyaeSfCTJ4SR3VNXhS7Z9LMm3uvvGJJ9Icv/q3sNJjib5QJJbkny6qg5c5szPJHl/kj+d5AeS/NxSzwYAAAAAAAAAAOu25Bt/PpTkTHe/2N2vJ3ksya2X7Lk1ySOrz08m+XBV1Wr9se5+rbtfSnJmdd6OZ3b3qV5J8nSS6xd8NgAAAAAAAAAAWKslw5/rknxty/dzq7Vt93T3hSSvJHnHLvde9szVT3z91ST/eruhqurOqjpdVafPnz9/hY8EAAAAAAAAAAD7w5LhT22z1nvcc6XrW306ye9297/fbqjufqC7b+rumw4ePLjdFgAAAAAAAAAA2Pc2Fjz7XJL3bPl+fZKv77DnXFVtJLk2ycuXuXfHM6vqHyQ5mORvvgnzAwAAAAAAAADAvrXkG3+eSXKoqm6oqquTHE1y4pI9J5J8dPX5tiSf7e5erR+tqmuq6oYkh5I8vduZVfVzSW5Ockd3f2fB5wIAAAAAAAAAgLVb7I0/3X2hqu5O8lSSA0ke6u7nqureJKe7+0SSB5M8WlVncvFNP0dX9z5XVU8keT7JhSR3dfcbSbLdmav/8p8m+WqS/1hVSfLr3X3vUs8HAAAAAAAAAADrtORPfaW7TyU5dcnax7d8fjXJ7Tvce1+S+/Zy5mp90WcBAAAAAAAAAID9ZMmf+gIAAAAAAAAAABYi/AEAAAAAAAAAgIGEPwAAAAAAAAAAMJDwBwAAAAAAAAAABhL+AAAAAAAAAADAQMIfAAAAAAAAAAAYSPgDAAAAAAAAAAADbax7AAAAAAAAAACA75XNYyfXPcK+dfb4kXWPwBXyxh8AAAAAAAAAABhI+AMAAAAAAAAAAAMJfwAAAAAAAAAAYKCNdQ8AAAAAfP/aPHZy3SPsW2ePH1n3CAAAAAAM540/AAAAAAAAAAAwkPAHAAAAAAAAAAAG8lNfAIzj5yJ25uciAAAAAAAA4K3DG38AAAAAAAAAAGAg4Q/wf9i783BbjrJe/N+XRJIwhVFFBMMoBsQIAVQGwyiKMki4EFGJoogXZBIUxYsBFUG4NwqIIghBRAYBQwCZBCISGRLIHEADRAUEQZEfswz1+6NqZffZZ609nb1yzgqfz/Oc56zdq4da1d3V1dVvVQMAAAAAAAAAK8irvgCAvXid2mJepwYAAAAAAMCBwog/AAAAAAAAAACwggT+AAAAAAAAAADAChL4AwAAAAAAAAAAK0jgDwAAAAAAAAAArCCBPwAAAAAAAAAAsIIE/gAAAAAAAAAAwAoS+AMAAAAAAAAAACvo4P2dAAAAAAB27ojHvW5/J+GAddFT7r6/kwAAAACwVEb8AQAAAAAAAACAFSTwBwAAAAAAAAAAVpDAHwAAAAAAAAAAWEECfwAAAAAAAAAAYAUdvL8TAHBpc8TjXre/k3DAuugpd9/fSQAAAAAAAAC41DDiDwAAAAAAAAAArCCBPwAAAAAAAAAAsIIE/gAAAAAAAAAAwAo6eH8nALhkHfG41+3vJBywLnrK3fd3EgAAAAAAAABgy4z4AwAAAAAAAAAAK0jgDwAAAAAAAAAArCCBPwAAAAAAAAAAsIIE/gAAAAAAAAAAwAoS+AMAAAAAAAAAACtI4A8AAAAAAAAAAKwggT8AAAAAAAAAALCCBP4AAAAAAAAAAMAKEvgDAAAAAAAAAAArSOAPAAAAAAAAAACsIIE/AAAAAAAAAACwggT+AAAAAAAAAADAChL4AwAAAAAAAAAAK0jgDwAAAAAAAAAArCCBPwAAAAAAAAAAsIIE/gAAAAAAAAAAwAoS+AMAAAAAAAAAACtI4A8AAAAAAAAAAKwggT8AAAAAAAAAALCCBP4AAAAAAAAAAMAKEvgDAAAAAAAAAAArSOAPAAAAAAAAAACsIIE/AAAAAAAAAACwggT+AAAAAAAAAADAChL4AwAAAAAAAAAAK0jgDwAAAAAAAAAArCCBPwAAAAAAAAAAsIIE/gAAAAAAAAAAwAoS+AMAAAAAAAAAACtI4A8AAAAAAAAAAKwggT8AAAAAAAAAALCCBP4AAAAAAAAAAMAKEvgDAAAAAAAAAAArSOAPAAAAAAAAAACsIIE/AAAAAAAAAACwggT+AAAAAAAAAADAChL4AwAAAAAAAAAAK0jgDwAAAAAAAAAArCCBPwAAAAAAAAAAsIIE/gAAAAAAAAAAwAoS+AMAAAAAAAAAACtI4A8AAAAAAAAAAKwggT8AAAAAAAAAALCCBP4AAAAAAAAAAMAKEvgDAAAAAAAAAAAr6OD9nQAAAAAAAAAAoDvica/b30k4YF30lLvv7yTAAceIPwAAAAAAAAAAsIIE/gAAAAAAAAAAwAoS+AMAAAAAAAAAAOyeQDkAACAASURBVCtI4A8AAAAAAAAAAKwggT8AAAAAAAAAALCCBP4AAAAAAAAAAMAKEvgDAAAAAAAAAAArSOAPAAAAAAAAAACsIIE/AAAAAAAAAACwgpYa+FNVd6uqD1bVhVX1uDnfH1JVLxvfv7uqjph89xtj+ger6kc2W2dVPWxMa1V19WX+LgAAAAAAAAAA2N+WFvhTVQcl+eMkP5rkyCTHVdWR62Z7UJLPtNZukOTEJE8dyx6Z5P5JbpLkbkmeXVUHbbLO05LcOcm/LOs3AQAAAAAAAADAgWKZI/7cKsmFrbUPt9b+J8lLk9xz3Tz3TPLC8fkVSe5UVTWmv7S19pXW2keSXDjWt3CdrbUzW2sXLfH3AAAAAAAAAADAAWOZgT/XSvJvk78/OqbNnae19rUkn01ytQ2W3co6N1RVD66qM6rqjE996lPbWRQAAAAAAAAAAA4Yywz8qTnT2hbn2e70LWut/Vlr7ejW2tHXuMY1trMoAAAAAAAAAAAcMJYZ+PPRJNee/P2dST6+aJ6qOjjJ4Un+a4Nlt7JOAAAAAAAAAAC41Ftm4M/pSW5YVdetqssmuX+SU9bNc0qSB47PxyZ5a2utjen3r6pDquq6SW6Y5D1bXCcAAAAAAAAAAFzqLS3wp7X2tSQPS/LGJO9P8vLW2vlV9aSquseY7c+TXK2qLkzy6CSPG8uen+TlSS5I8oYkD22tfX3ROpOkqh5eVR9NHwXonKp63rJ+GwAAAAAAAAAA7G8HL3PlrbW/TfK366Y9YfL5y0nuu2DZ30vye1tZ55j+jCTP2MckAwAAAAAAAADASljmq74AAAAAAAAAAIAlEfgDAAAAAAAAAAArSOAPAAAAAAAAAACsIIE/AAAAAAAAAACwggT+AAAAAAAAAADAChL4AwAAAAAAAAAAK0jgDwAAAAAAAAAArCCBPwAAAAAAAAAAsIIE/gAAAAAAAAAAwAoS+AMAAAAAAAAAACtI4A8AAAAAAAAAAKwggT8AAAAAAAAAALCCBP4AAAAAAAAAAMAKEvgDAAAAAAAAAAArSOAPAAAAAAAAAACsIIE/AAAAAAAAAACwggT+AAAAAAAAAADAChL4AwAAAAAAAAAAK0jgDwAAAAAAAAAArCCBPwAAAAAAAAAAsIIE/gAAAAAAAAAAwAoS+AMAAAAAAAAAACtI4A8AAAAAAAAAAKwggT8AAAAAAAAAALCCBP4AAAAAAAAAAMAKEvgDAAAAAAAAAAArSOAPAAAAAAAAAACsIIE/AAAAAAAAAACwggT+AAAAAAAAAADAChL4AwAAAAAAAAAAK0jgDwAAAAAAAAAArCCBPwAAAAAAAAAAsIIE/gAAAAAAAAAAwAoS+AMAAAAAAAAAACtI4A8AAAAAAAAAAKwggT8AAAAAAAAAALCCBP4AAAAAAAAAAMAKEvgDAAAAAAAAAAArSOAPAAAAAAAAAACsIIE/AAAAAAAAAACwggT+AAAAAAAAAADACjp4fycAAAAAAPjmdsTjXre/k3DAuugpd9/fSYADhrJiMWUFAMA3LyP+AAAAAAAAAADACjLiDwDAfqCX4mK71UtRHi8mj5dPb1sAAAAAAC4JRvwBAAAAAAAAAIAVZMQfAAAAAIBLOaM1Lma0RgAAYJUZ8QcAAAAAAAAAAFaQEX8AAAAAAGAfGVVpMaMqAQDA8hjxBwAAAAAAAAAAVpDAHwAAAAAAAAAAWEECfwAAAAAAAAAAYAUJ/AEAAAAAAAAAgBUk8AcAAAAAAAAAAFaQwB8AAAAAAAAAAFhBAn8AAAAAAAAAAGAFCfwBAAAAAAAAAIAVJPAHAAAAAAAAAABWkMAfAAAAAAAAAABYQQJ/AAAAAAAAAABgBQn8AQAAAAAAAACAFSTwBwAAAAAAAAAAVpDAHwAAAAAAAAAAWEECfwAAAAAAAAAAYAUJ/AEAAAAAAAAAgBUk8AcAAAAAAAAAAFaQwB8AAAAAAAAAAFhBAn8AAAAAAAAAAGAFCfwBAAAAAAAAAIAVJPAHAAAAAAAAAABWkMAfAAAAAAAAAABYQQJ/AAAAAAAAAABgBQn8AQAAAAAAAACAFSTwBwAAAAAAAAAAVpDAHwAAAAAAAAAAWEECfwAAAAAAAAAAYAUJ/AEAAAAAAAAAgBUk8AcAAAAAAAAAAFaQwB8AAAAAAAAAAFhBAn8AAAAAAAAAAGAFCfwBAAAAAAAAAIAVJPAHAAAAAAAAAABWkMAfAAAAAAAAAABYQQJ/AAAAAAAAAABgBQn8AQAAAAAAAACAFSTwBwAAAAAAAAAAVpDAHwAAAAAAAAAAWEECfwAAAAAAAAAAYAUJ/AEAAAAAAAAAgBUk8AcAAAAAAAAAAFaQwB8AAAAAAAAAAFhBSw38qaq7VdUHq+rCqnrcnO8PqaqXje/fXVVHTL77jTH9g1X1I5uts6quO9bxz2Odl13mbwMAAAAAAAAAgP1paYE/VXVQkj9O8qNJjkxyXFUduW62ByX5TGvtBklOTPLUseyRSe6f5CZJ7pbk2VV10CbrfGqSE1trN0zymbFuAAAAAAAAAAC4VFrmiD+3SnJha+3DrbX/SfLSJPdcN889k7xwfH5FkjtVVY3pL22tfaW19pEkF471zV3nWOaOYx0Z67zXEn8bAAAAAAAAAADsV9VaW86Kq45NcrfW2i+Mv38mya1baw+bzHPemOej4+8PJbl1khOSvKu19pdj+p8nef1YbK91Tua/wZh+7SSvb63ddE66HpzkwePP707ywV382Vz6XD3Jp/d3Ii7l5PHyyePlk8fLJ4+XTx4vnzxePnm8fPJ4+eTx8snj5ZPHyyePl08eL588Xj55vHzyePnk8fLJ4+WTx8snj5dPHi+fPGYz39Vau8a8Lw5e4kZrzrT1UUaL5lk0fd4IRRvNv/fE1v4syZ/N+w7Wq6ozWmtH7+90XJrJ4+WTx8snj5dPHi+fPF4+ebx88nj55PHyyePlk8fLJ4+XTx4vnzxePnm8fPJ4+eTx8snj5ZPHyyePl08eL588Xj55zL5Y5qu+Pprk2pO/vzPJxxfNU1UHJzk8yX9tsOyi6Z9OcuWxjkXbAgAAAAAAAACAS41lBv6cnuSGVXXdqrpskvsnOWXdPKckeeD4fGySt7b+7rFTkty/qg6pqusmuWGS9yxa51jmbWMdGet89RJ/GwAAAAAAAAAA7FdLe9VXa+1rVfWwJG9MclCS57fWzq+qJyU5o7V2SpI/T/KiqrowfaSf+49lz6+qlye5IMnXkjy0tfb1JJm3zrHJX0/y0qr63SRnjnXDvvJauOWTx8snj5dPHi+fPF4+ebx88nj55PHyyePlk8fLJ4+XTx4vnzxePnm8fPJ4+eTx8snj5ZPHyyePl08eL588Xj55vHzymB2rPlgOAAAAAAAAAACwSpb5qi8AAAAAAAAAAGBJBP4AAAAAAAAAAMAKEvjDJa6q7l1VrapuvL/TsixVdauqOrWq/rmq3ldVr6uq792ldR9RVeft4zq+XlVnTf49bkw/taqO3o107iBNx1fVd0z+PriqnjzycJbOx+/i9k6qqmN3aV3fXlUvraoPVdUFVfW3VXWj3Vj3Jts9uqqescNlL97XVfXzVXVuVZ1TVedV1T23ua5/HP/v87G5hW21qnrR5O+Dq+pTVfXaXVr/CVX1mG3M/wNV9e5xfL6/qk7Y4XZvV1Xnj/UcVlVPG38/bbtp3cl+WFQmbDD/b25n/VvY/ue3Of/Fv32cy1+sqitOvv+jcaxcfRfStvTjeoNt7+h4H+Xps8bnE6rqY5N9+5Rlp3tdWnatrN3CtvaoX4x991O7uP6TquojIx8/UFW/vYvrvmh2vF4S15SqOqaqfmiX1zkrR86vqrOr6tFVtV/uNca+/+j67Y/03WoH69vVMu+Ssuxr5qpYf42ZlpEbLDP3HBnH9kvmrO871s+7g3R+76Ss/q9JefN3O1zfz1fVt+9ruraxvZXI57GuI6rqSyN/L6iqP91OeVVVV66q/70badmfJuX2eVX1mqq68jaX31a9ed2yp1bVB8e+Pq2qvnuT+Z9UVXfeybYuCfual+vWtelvrarnVdWRO93GpcG4xv3fyd+PqU3uxeaVOVX1s2O/nT/Kg9k9xn5rG9muqnr8SP854zi89S6s8/Pj/4vvharqzKo6anw+uKq+UFU/PVnmvVV1821s45hFdZJ1dePt3isuXO8Wlj1+1JXOqqpPVtVnq7eVnFVVz621+6oLquq4Haz/myZfa3Jvti5fz6+qV1TVNavqf9fa/eqFVfW5ab7WNu8la5vtM7XNe/2qutdulr27WbeZrPMmVfXWqvqn6u2p/6eqaovLrky5BwDAfAJ/2B+OS/KOJPff3wlZhqr6tiQvT/KbrbUbttZunuT3k1x/zrwHX9LpG77UWjtq8u8SfRC8wPFJpje8vzv+/t7W2lFJbpfkW9YvVN1+K8vGDfTfJDm1tXb91tqRSX4zybcte9uttTNaaw/fl3VU1XcmeXyS27bWbpbkB5Kcs8107OrD4018IclNq+qw8fddknxsOyvY5WPmhUkePI7Rm6af+zvxgCRPH+fjl5L8UpKbt9Yeu0vp3Mx2y4QD7SH4hUnumSRj394h2z8u9ld5vJF9Pt6HEyf7dsOgrqmqOmgH29qf1tcvjkiya4E/w2PH+X5UkgdW1XV3c+WX4DXlmCS7XXbPypGbpB+rP5ZkV4KjtnssttYuSvJv6XWH2TpunOSKrbX37CAJ2yrz9nfdZGK3ypBLxAFWDh+TdedIVX1P+v3z7avq8pOvjs+eddgdaa2dOyurk5ySUd601nYa7PDzSS6xwJ/k4mvwdhyTSzifJz408vpmSY5Mcq916dio3Llykks08GdJ58es3L5pkv9K8tAlbGMjD2itfV96fXphsHuStNae0FrbKwjuAKqr7FpeLvqt6+b5hdbaBTvdxm44APL+K0l+srYX6H9MJmVOVf1okkcmueuov9w8yWf3NWGXZN5U1Q8m+fH0e8ebJblzeh1oGf4xa/n3fUk+OPt7lNfXS3L2VlZ0gF3z13tZkl9O8uEkr0/y/9Lz9f/LuK9Kv/d8TlXt1Ua1A5fWfF1/b/ayyb3CV9PbQGbX0hOT/EKS07PDfB3n3W61zyxyr/Q6w7zt7yTvj8826zYbbWfU+U9J8pTW2o3Sj6cfypw6y1bSW6OT3wbfzy3raoPg7+qdWrYbaPzIqrrcdpbZZH0XbfPasX75LQXBbZZ/Gyy3af5tN2htX9UuB73vRvprGwHoy9wXGyz7+cnnHxuBeNepvTvnnVVV95t8/nz14PizquovFqz7alX1tjHvs9Z9d+pk+bOq6lurBwjP/p52/NzSM4VVPZbXn6tV9btV9caqOmROPr1iu/lUVbev3uH/a7UuSHXd8qeMaX8z/r6wemDx7PtL5LlKHSAdKabpKAGnO1KTTiD7ek3j0ulAaJDmm0hVXSHJbZI8KOPmb1yETx0X2A9U1Yurem+EqrpT9d4v51bV86vqkDH9oqp64ri4nlu9B8llRiXqGmOey4wL6dWr9xL5k1Ep+nBV/fBY3/ur6qRJ+o4b6zuvqp46mT6trB07W6aq7jvmPbuq3j5meViSF7bWLq4Utdbe0Vo7eSxzUlX9v6p6W5KnVh8d6B/H7/zHGr0dR+Xo1VX1hlERmT48O6h6b6Pzq+pNtfZAZ9dU1V2r6p0jj/967LtZ3j95fHdGVd18VJo+VFUPmSz/2Ko6vXqvsyeOaUeMPN8j7aNydHSSF48Kz+WT/GKSX2mtfXnk4edaayesW8+zk7wvybXH/j1jrPeJk3RcVFVPrar3jH83mPzM2488//D6Cto23CHJV1trfzqb0Fo7K8mZVfWWyTE6C0qYmwfju6Oq6l0jz/6mqq4ypp86+Q3/VFW3G9MvrsBW1RWq6gW1NnLPfcb0ufky8a1JPpfk8yPtn2+tfWSy3ROr6u0jzbesqleN8+x3J3m8V0+xqjqo+qg1s2Pgl8b0a471zXrE3m79slvw+iR3H5+PS3Jxj/Bad+M3tnHEgmPmbmP/nF1Vb5nzG36xql4/jtG5+2bk37+PvPv6rAF+O/ujqn4hyf9K8oTq5d8pSS6f5N3Vb/6+axxL54z/rzMnrbcYv+Od2aWHNlV1ePWyZ1YmvWTkyVOSHDb24YvHdz89js+zquo5NRqAqt+E/t5I27uqB0amqq5bvQw5vap+Z9129yo7xvTHj/T8XZL1vcJfkuR+4/MxSU5L8rWx3B43kTXpDTyO8SdX1d8neURVfdvYv2ePf+sfRl6vell9y6o6dLKPz6yqO+xLfm9go+P9qlV18sird1XVzba60tr4+vqEqnpHkvtupRzYKI/XbfMJY9+eV1V/VrW1nodb/D171S+SPCXJ7cZx+ahF+6z69fbk6j30P1JVD6s+Ws2ZI1+vOmeTh47/vzDWseX6yph+terl/5lV9Zwks7yYe01prf1DdU8b+XduVd1vrGt9Y8azqur4RduvqiOSPCTJo0be3K7m12d2rLX2H0kenORhI92LrgmXqapnVy8TX1u98efYSdqnx+L1q9eJ3ltV/zDJy2tU1SvHuk+vqtuMZLwkewaZ339MW7hMzSm7a36Z9+iRX+dV1SPHtL2uM/uaj7tkozLk8uN4PX0ci7O6yk1qrUw/p6puOKYv+t0fqN7wcF7169idq4/g8c81RljaYFvHV69nvibJmy65bLk4D/Y6FuadI2P2n0ryopHOe4zl19dhD6uNy4NN69AL0nml6r233zf2yY+P6TeoqrMm8z2uqn6revlwVJKXjXRdtqruMj6fW70eetmxzEerX6vfNfLg5tXLpw9V1S+uW/d7xvafMNn+eVX1p0kOS3LNVcvn1trX0h+63qB6efq2qvqrJOeO9e113KdfX64/0vK06haVz39fVS+vXod/SlU9YOTjuVV1/UX5M6afUP16+aYkcxv+d9E7k1xr9kdtsz5Wc+rK1UeuOL2qjhnz/H5V/d6cbb89yQ3GPHPrCjUZ9aHWXR92Pyv22Vbz8v9ULz/fXL2ePR3NcvZbFx3np1Yf/fWgMf/s2HvU+H6j+8qt3N9tVLd/UlW9O8kPLj8rN/S1JH+W5FHrv5h3TtX8Muc3kjymtfbxJGmtfbm19tzJqu5be9+DH1G9HvK+8W8WoDGv/Fi0j+fWaXbomkk+3Vr7yvgNn26tfby2UBZWr/fs1WaxgdOyFqDyQ0n+NP1akyS3SvK+1trXa8E9ykZlWi2uG0/nOaYWtx3ebUx7R5KfnCyzqP7x6Kp6/vj8veMcmgYWXDPJf6Zf2z7TWvt0ervJb1bVk0f6D0tvU5Kv6/K1+r3ZD6d3XpiN4HOtcY68JD1Y7Z7pHSQfMv5O+nOKyya5oEa9e6x3S/euWdw+c0LNaScafx5cVS8c+fqK2XFQ/Zp9wZj+9HGu3yPJ06qXIdevvdsTLi6/xzqmbcm/NtJ/9lj3vLrNRbU2ItPRVXXqvH1cC+6t0utQp7XW3jTy4IvpbdSPW7Cew6qPNHtOVb0s/Ziepfeu/b+5bcI7vga31n6stfbf21zskUl2LfBnu2qHwZzL6CS5w/zbDZd40PvUTvfBzP7cF1V1pyTPTHK31tq/jsnTznlHtdZmgZFHJTkjPTj+qNbazy5Y7ZeT/J8kiwKfHjBZ93+01n5vsv5px88tvUXg0nAsV3+LxG2S3GtWZ8qe+XTsDvLpX9MDOP9qznfT5e+RJK21e491/0KSf5h8v6PAqu3aSueCb6Z0rLIDoRMIB7jWmn/+XWL/kvx0kj8fn/8xvUfVMem9qr4z/SbvnUlum/5Q7d+S3GjM/xdJHjk+X5QeFJL0iufzxuffnsxz1ySvHJ9PSvLS9Jvce6b31Pnesb33pt9Uf0f6BfsaSQ5O8tb0ykCSfH7yG45NctL4fG6Sa43PVx7/vyrJPTfIg5OSvDbJQePvKyU5eHy+8yTNx6ffsF4t/ebrvPSbwiPSG7mOGvO9PMlPb3M/fD3JWZN/9xvTTx3buHp6A+zlx/RfT/KESd7/8vh8YvroMFcc+fYfk7z/s5Hflxm/9/YbpX227fH5ZknO3CD9RyT5RpIfmEy76vj/oLGum03S+/jx+WeTvHayH/56pO/IJBfu8Jh+eHqFff30g5NcaXy+evqIJLVJHpyT5IfH5ycl+cNJ3vzf8fnHkvzd+HzM5Pc8dTb/+Psqm+TLbF8flOSN6cf+C5L8xGQdpyZ56vj8iCQfT28AOyTJR5NcbXp+jN923vj84CS/NT4fkn7jct0kvzrZHwelj76wnfz+/Dg+XpFeRpy1Lh9OSG+8nc1/3kjXHsdM+vH6b0muuy6fTki/cXpYek+pQzbZN09I8pn0ETp+KcmhO9wfJyU5dvo7J59fk+SB4/PPJzl5/W9dl76nzfbDLpQJd0kvk++f5A0L0vc9I43fMv5+dpKfHZ9bxjGV5A8mx8Qpk3keOjmGFpUdt0gvby+XXmZeOPntJ6WXy+9KcpUkz01vZLwo/dw7YpofY/+eMDnGnz357mVZu4YclOTw2fLpD7fOzNq5+6tJXjA+3zj9HDp0J+XIPhzvz0zy2+PzHZOcNT4fn+RZk+PkY5N9+yPZ/Pr6a9spBzbJ45Myju2M4398flEm5c0u5NWi+sVrJ/PM3Wcjvy7M2rXss0keMuY7cZI3JyX5yMjHzyd58pi+k/rKM7J2Xb17+rly9Sy4poz57pPkzenH5reN9F9zzu98VpLjN9n+CdmzrNyrPrOT43XOtM+MtC66Jhyb5G/Tz/dvH/MfO0n79Fh8S5Ibjs+3TvLW8fmv0ketS5LrJHn/+Pzt6fWoWR3r/Uluuskyi8ruaZk3K48un+QKSc5P8v2ZUzfZ3/+yeRny5KzVQa6c5J/G73pmeiNY0h++HLbJ7/5a9qxXPz9rde6TN9nW8ellyVWXmA/rr3H/mrUyctGxcEIm58iY9k9Jviv9WnXKZPqpWavDblYebFiHnqzzpOxZL/iWjDpT+kOtfx6fb5BR9o+/H5e1c+0dWbtmXW6k6/rj7xcnedj4/NEkvzg+PzP9Wnf59HP3E2P6j6Vf32fX5zekP5y8Qfpxf8tVyufsWWe9XPoIAz+afn58IWv1w42O++l1b6Py+b+zdt38WJInjmUekbX65Eb5894khy2rjBj/H5R+X3S38fdO6mOL6so3SS9/75J+bF12zv58bPpIEMmCukL2rE9clMn14UD4t4O8PDr9PDlsHJ//nL3rthsd56eOddwiyZsn6Zi1SWx0X7lZvW6zuv3/2t/5PcvzcRxelF5nn9Y/t1TmpI/OdPiC9Z+a+ffgl8vaPd8Nk5wxPh+TPcuPjfbx3DrNDvPhCmM7/zT21Wy/X5TNy8K5bRbrjukjslZeHpHkw+PzS9Lr028b6318kieN7xbdo5yQSZmWPeskc+vG69JyTDZuO7xh+rn28mxe17lMepvXvdPrpbcZ8xyf5FMjv76a5ItJ/iT9/vKE9GPml9PvNT4mXxfm64kjH2+Tfm/22+nXw6+P6f+QPpLReVlrgzkmPbjq3ZN0/G164NBW710Xtc+ckMXtRC1r+//5Iy1XTR95abbfZmXrSdmzfnZq9mxPWP/9LI9/dOTD5cbfV50sf/Rk/osm++fo9FFgZ+mf7uNF91b/L8kj5pQTn0kvL9ev59FJnj8+3yy9Tj9tE56l/znp98GvSD8v3jfJm1uO33Z2kvekH7fHp7eNvyG97PuDeb9xTjovn+R1Y13npXfueniS/0mvf7xtzPcn4zefn1Gvmqz7iSN95ya58Zh+tfSA8jPHb/mXST6fPPLk/PTRoqbXmCelH4+3TXK3JB9Ir18/I5P7742uU5Nz7NSRfx9Ir4fvU/5lzzLkeuO33TK9HvK09LrtOUl+aczzokyeVYw03GNBum8y0nLWWMcN05+pfGlMe1r6tectk7y+56Q8e396u9z5I99nx9stxu98ZybtlmOZfxjrel+SH5rk29vSr+kXjGmPTz83/y69vHzMZvth2ftio22mj0D84YxjcV55NGe5UzMpFzb5Xcdn3G9tdfnMabe5FB/Lx6TXvX81Pcj2CsvIp6wr+zdbPuva8Hb6LwvOt/TnnO8a+fY3WWvXujid6R1ZLhjzPH1M+6708/qc8f91Ntj2fdPL6bOTvH1yPJ6cfh/xkfRnK48e+/RdWbv2TdNx8X5Iv296Z3o58Nez/TUvrQfKv/RnjeeMfHhRkldn7b7pl5K8eINlHz75XS8d005IH73wTeMc+cn05ynnpp9Hs/uzab5dlLVr2k9nrfx+Tvp5dNDI8/PGeh61v/PNv+X/O5CGAOWbw3FJ/nB8fun4+3VJ3tNa+2iSVO+1ekT6Dd9HWmv/NOZ/YfoD4tnyrxr/vzdrPU+en17A/mH6A/IXTLb9mtZaq6pzk3yytTbrhXX+2N53pd9UfWpMf3F6o9zJG/ye05KcVFUvn6RnD9V7w10pyZtaa48Yk/+6tfb18fnwJC+s3pu6Zc/XWb25tfafYz2vSr/ZOHnky6x373tH+rfjS61HGC/yA+nBMKeNjj6XTb/wzpwy/j83/SL8uSSfq6ovVx/m8q7j35ljviuk3yj8607SXlU/l94webWs9YT6l9bauyaz/a+qenB6I8s1R/pnr6x6yeT/EyfLnNxa+0Z6b6Ldfo1KJXlyVd0+/YHItbL2qpa98qCqDk9vTPj7Mf2F6ZWcmenxfsSc7d05k5ENWmufGR83ype03nPsbumV6jslObGqbtHG6ErZc1+f31r79ySpqg+nj2bwnwt+/12T3GzS2+nw9GPg9CTPrz5088mTfNiy1to5o3fWcekNQVs1PWZ+IL1i+pGxzv+azPcz6Q3f92qtfXWjfdNae9IoK+6a3rvquPQK/I72xwI/mLUy7kXpFb6LzUnfi9IblrZjbpnQWntzVd03yR+nDxM9z53Sb+BPH+XFYUn+Y3z3P+k3BXZncgAAHHZJREFUWUk/du8yPt8m/SHZLL2zEdYWlR1XTPI3rfdYS41hUtd5VXqe3zq9cr1VL5t8vmN6pT2jjP5s9R7S10i/ttyntXb+mPe26Y2vaa19oKr+JcmNss1X5W1mk+P9thn52Fp76+jRefic1ZzYWnv67I+q+r5sfH192brlNysHttpL5w5V9WvpD0yumn5j+potLruZRfWLqUX7LOmNiLNr2Wcn6To3vRF05rGttVeMHo9vGT0/v5Dt11duP/vcWntdVc3KiI3cNslLxrH5ydGz9Jbpwcwbmbf99Tatz+zQrFfxomvCbdPrRN9I8onqoyFOvSy5eESnH0ry17U2UNQh4/87JzlyMv1KVXXF1tonRh3vTlX1yfSRlM7baJksLrunbpteHs1Ge3pVeoPeKdm7brLfbVKG3DXJPSY9oA9Nf0D6ziSPr/460Fe11v65qjb63R9ZV69+y6TOfcQm20p6fXd6Hd5te1zjqo+INRtOetGxsIequmWST7XW/qWqPppel7nKnGPku7NxebBhHbot7vVY6SOF3ja9Xnnt2t5wzt+THiz0ofH3X6SPkDYben2aroPHfv5CVX1jnH93Ta9bTK/PN0q/3n+otXZ6Va1MPo/vrj/uO1uSV7fWXl99ZJr3zOqH2fh8n9qofD59ct38UNZGtjo3fZS3zfLnlNZfA7sMh03uvd+bHryUbLM+tkld+fyqelH6dfUHW2v/M9n+i6vqSxlBqmPaVusK6+sq+9tO8vLVs31bfdSz9TY7zpP+MOl6VfXM9HrPm7ZwX7lZve62WVy3/3qSV24hPy4RrbX/r/prMB6e/kByZktlzhbMuwf/liTPqqqj0vPjRpP515cfe+3jTeo029Za+3xV3SK9bLpD+khvs1f7blYWfiHz2yw+sWBbF1UfQe7b04NTPph+f3/r8ZueOfnti+5RFpVpW60bz2s7/Hz6ufLPY/pfpgdGJAvqH62194/r1DlJntNaO22yjZe11h5WfYSJV6afsy9Lf2h1pfTAkOukn4tXlq9z8/Wf0q8Xp1XVS9ODJt6WHiR0x/T2hek9+6PSz6fLJ/nN1to3Rjpukt5Jc0v3rhu0z2zk3yb7/y/Ty5M/TB9R43lV9bqstWnMs5Xr0Z3TO6B8caRzJ/Xe6T5edG9V6fWaeWbTp+u5fXoQy+yeYdaWMWsTnl3brpy+H26XXrdrSW5TVe9J//33G3XBK2WtLD4qPVj6K0k+WFXPbK1t9hrCuyX5eGvt7kmvX7TWPltVj05yh9ZH3kp6Z8L/GufoW6rqZq21Wdo/3Vq7efXXUj0mfWSN307yjnF83D1rx3GS/PxY12Hp171Xtt4Of/n0YIQnVNWh6UELd0wP5NtJHeT704/nj6ffe+9K/lUfofulSX6utXZW9fbGz7bWbll9ZKzTqo/w9Lz08+zVo9z4oSQPXJDWhyT5o9bai6uPEHpQeueCm87q+tVfFXfvcR2+epJ31Vo73Q2THNda+8XRvnCf9HPrBemdkv6+qqaveP2PJHdprX25+rORl2TtHuJWY7sfGde6+498OTg9OOC9G2f7XEvZF3Mckt6OeExr7QPrvntUVf30+PyZ1tpujyD+gqqa1dl+t7W2qFzYiVU6lpPe/vzdSW7RWlv/xoLZvUjS2yQeu8282MihVXVGekDlU9p4E8gSzDvffi1r59qTMgZKmC1QfVTze6cHpLXJ/fGzkvxFa+2FVfXz6deHPV6HPfGEJD/SWvtY7fnKu5um7+9D08vLX2+tfX9VnZje3v6He68qGeXIbyW5c2vtC1X160keXf1VcfPSut9V1U3SgxFv01r79MjXb0k/Vj+SHnD2Axus4nHpHQa+su53XT+9Tn9ketvcfVprv1ZVf5MexD33WKr+yvT7jfR8tfpo5A9Iv5++VuuvpM6BlIcsj8AfLjFVdbX0SvJNq6qlVxxb+kOIr0xm/Xr6sbnZK0Bmy8zmT2vt36rqk1V1x/Sb5AfMmf8b67b3jbH81zbY1rSCdOjFE1t7SFXdOr3QPWs0/pyf3vvn1WOeW4+bsR+frOMLk8+/k/7A8d7VH8ycumC707/X59duv+qr0is8xy34frO8rCS/31p7zh4r7b9vK2m/MMl1qj+4+1xr7QXpldbz0o+bZJKHVXXd9Bu6W7bWPlP9VWyHTtbXFnyepmWnr5w5P71H5noPSA8WuMW42F40SdNO9t9ex/s6e93gbyFfkiTjBuA9Sd5TVW9Ovxk7Yd12F+3rRSq9kvnGvb7oDWB3T/Kiqnpaa20nry44JcnT0xtxrjaZ/rXs+RrL6e+dnncbNYicl35j8p3pEeobGg/R/qSqnpvkU6Os2/H+2IL16d7ot+yTqrpM+sPCL6U/fPnovNnSX2/4G3O+++rkBnP9sTsvzYvKjkcumH/qpek3/i8cDYWz6RsdE8mex8Uin03vZXib9HN+ltZLyqLjfV4atnIsbJb29XmylevnRnmc0Vj27PQeCf9W/VVgOzn+97JJ/WKPWTdYzfrfNf3Ne5V14yHLqekN8Ju9nmhR+T1vXy26piSL079Z/m92/ZhbnxkNnjtWVdcb2/yPLLgmjIbXjcyOxcsk+e82P2j5MukPk+c97Ji97uuTmbziatEy1QuOzc6hjY6jrZQn+8NGZch9WmsfXDf/+6sHrt89yRurv5JyX8+fudsax93+zLdFx8L6+Y5LcuNRn0v6g7/7pDc87rHoJtvbab3qZ9Mf6ty8tfa16kExh2b++T/vnmZf01XpjcZ/vsdK+yt0t7L/DsR8/tCCMmV9fXEr9vX82Ch/lnl+fKm1dtRoNH9t+oPUZ2Tf6mPzfG96kPD6jhYPaK2dMVn/duoKB1p5u9283Ov1VHNsevyNe4rvSx/R8aHprw/ebN1bOd8X1e2/3NY6MB0o/jD9HmDa6WurZc756UFOb12w7nl1qEel1yu+b2zny5P5t1J+bFSn2ZGxT05Ncmr1oNvZA7DN9vVGbRaLvDO9rvrv4wHMu9LvkW6VHhiTbHyPstG5u5XyZV7b4UbLLqrrJP1h2efTAxr2TkzvJPWc9MDEhyX5vfSAzlunB0z8efo96Ix87W6efj/2Y+O3H5QezPn2JF8Yv+816Q8mZ05MH8Hl6emvoLr+SMdlss171wXtMxvdL+3V7jrqWrdK7+R0//T9f8ctbP/i7Yz7isuO6Vtts5mmc6N2i0X3VtdJPzan066XPvLE5xbUKxa1y7w5fdS9o6oHRj++tfbRsY5z0oPDPpt+zJ6e9GDMsc2kdwT47Pj7gvTOtpsFS5yb5OlV9dT00TD+YcF8G3Wo226nm4dX1b3H52unlwv/mT0DXW+cxUFwWzUvuG5f829eB7W5QWGttTdV1R9X1beOvHhl66+7nWdeJ5D18+xrZ9dph8WtBtTeLpt3CNyKZeyLeb6aPgLOg9I7M0/t0Tlvlz1gBGNcMf0Y/pns7iuDV+lYTvozpquM9b1i3Xd73Ivssuu0/urV6yV5a1Wd29Y64eym9efb9bNxB4Ck12XmBbdu2PF4nUWdB9/Wttapcr1FgxAsSuuB4I5JXtFGUGobQb3VX4v+tvTgyI0Cfc9JDz47OXsG87x+1B/PTa9DvWFMn3asm2dRx+zXZF1Hke38SFbTZTafBXbNselRo9/VWjuitXbt9Ifqt10w/wfSK4c3GH//TJK/XzDv1PPSI8lfvs1GqXcn+eGqunr1XgPHTbb3yar6nvEQfHZDkKq6fmvt3a21JyT5dPpNwh8nOb7Gu96Hjd5FfHj6EMFJHxJv6i7V3+N9WHqE7Wm5ZLwrPWL7BklSVZerqhttsszUG5P8fK29A/pao0K2kc+l93zMqMT/eXrF/9CxjoOydtO83pXSb14/W33knvWjndxv8v87s7vemuSQqvrF2YTqvZW/K32o569W1R3G3wuNSvBnqup2Y9JWj/eZN6U3RszScJVsni+pqu+oqptPJh2VPuztvnpjkl+uPrJPqupG1d8DP8uX56bv45tvtJINPD99yOtz102/aLbO8buuu2D5d6af79cd81518t2Z6b3PTqmq79ho31TV3WvtDviG6Tep/50d7o8F/jFrI1A8IH1o4Yu1PjrAZ6uPAjCbZ7c8Kn3Y0OOyNlJTknx18vktSY6dneOjzNrweE8vy6a/aWZR2fH2JPeu/g76Kyb5ifUrbP1d2Y9Pf2A09ckk31q9R+Qh2TMIc723pA/dnqo6qHovlaSPXHSvJD9bVT81pr19lvZRPl4nvXfmMiw63qdpOCa9d9tmo78kO7++LrKVPJ41XH567N9FwS07sah+8Y2M68qwa/useg+3Wyf5UHaWn9O0/Gh6Q0Sy4JpSVT88lrnfODavkd6A+Z70MvvIqjpkNKjdaQs/4eJr7tjGvPrMjo30/Wn6sNMtC64J6eXZfarqMqNcPGbe+sZx/ZHqI5ClutkoZOvL2+mDtFemv57jftnzwcyiZeaV3cmeZd7bk9xr1I0un14vXNQofaBYVIa8McmvzK5jVfX94//rpb9y4hnpQUM3y77/7rnbOgAsOhYuPkdG/f++6a/nPKK1dkT6a8yOWz9vdr98nTk8vf70taq6S3rjetJHD/iOqrrKqDNPg+mm6bogyQ3Hvk36ENDbSdcbkzxo7PtU1XfW9kYcWpV8Xm/Rcb9HGZrF5fNWbVSOLd2o6z48yWNGWbet+tgmdeWfTA84vH2SZ9TGPQyXWVe4RGwjL9+R5Ceq6tDx3bxA2E2P83EeXqa19sok/yc9OHBf7yt3Urffb0aD+svTH6zNbFrmDL+f5A+qj7SSUZd6+CabPDz94dY30vP2oAXzzd3Hm9Rptq2qvrv6CAkz27mfn11bttRmMZyWfo84a1d5Z3pw6ifa2qh1O7lHWVQ33ooPJLlu9WCRZO26kSyu6xye5I/Sy6ar1dqDxYzvZ/l62/T6/lHpDzaTJK21V6Xfb9x4Tnq+2fP1WekjP5yW/jqba6e/3uuak+Vvm7VXLU99Ij0AaDp6w8eyxWt+LW6fuSiL24muU1U/OPmN7xjn7OGttb9NHyVhURmy3kXpD92SXoeZ3T+8Kf1acLmRhln70/r1TZe/TxZbdG/14iS3rao7j+mHpQehLnp4Oz0+bpq1h7KzwLNZXh6SPQPUpx12FwU0LQomW6j1UZ1mrxX9/eoPT/dQax3q7tRau1n6Q8xpkNSWO92M8+jO6YGi35feFjhb1/pA133tbLeow/O+5N+0g9rMLCjsqPHvuq212UPeF6Xv75/LnsGye2it/VWSe6R3AHxj9c7V600DHI9KbxNa1Nl1s986Dag9Onu2/W8lUG27lrEv5vlGekD2LavqN7ebyJ1qrX1s/P+59Nek3WqXN7Eyx/LwyfQ2oRPHNfkS0Vr7+Pj/w+nB2ctq/1ifv5uO5jICpW6V3l52r6wFluw16wbreEj6CD3XTu88OOtgtq1OlROzQQhm+/vI1tqDtpHW/WHRcf+96QGkcwPLJ+6e/hz5FkneW72dORl5Nu41ph2qt5KHL5zk4Xe31k5offTk70s/Dh+avTtVcSkk8IdL0nHp75WcemX68Kt7aa19Of0C/tfVIxy/kf4QaTOnpA+hvdmFf/32/j3Jb6RHZJ6d5H2ttVePrx+XHlH61iT/PlnsaVV1bvWRaN6e5OzW2ifSHzD9flVdWFX/mN5o+azM9wdj3tOyd6PRO9IrM2elRzDvVhTyYVV11uTfU6Zftv66s+OTvKT6UK/vyvwGjblGReyvkrxz7LtXZOOb46S/a/JPR3oOS3+A/+9JzquqM9Mb2V+YPpTk+u2dnX6Ddn76w631AVKHVO+5/ohs3gNyW8bF997pQVofqv6KixPSR5o4uvqwjg9IbzTZzAPTj6lz0hsWnrSNpPxukqtU1XlVdXb6MLib5UvSGyKeXlUfqB6pf7/s3RNhJ56X/pDpfeP8eE565eSY9ArhmekNGX+0k5W31j7aWpu37CuTXHX8ll9OH2J63vKfSu+h86qRXy9b9/070hsTXjca1Bftm59JH6r0rIwbj9E4sNP9Mc/Dk/zc2PbPZP7++bkkf1xV78yew9xv1V5lQvXAiF9I8qut97R6e3qlPkn+LMk5VfXi1toFY/qbRhrfnD0b9eZ5RJKHVtXp6Q2jSRaXHa2196Xvo7PS9/Hch82ttees70HRWvtq1t7N/tpsfC4+Iv0VE+em95S4yWQ9X0gPaHlUVd0zPcDooDHvy5Ic31r7ypx17rMNjvcT0suZc9LfebzR8LbT9e30+rpofZvm8Wiwfm56I97J6cPX75ZF9Yv7J/laVZ1dvWf9buyzp43z/Zz03/KqHebnE5Pcvqrel97z6F+TDa8pHx+/cfbu6Lcm+bXW2idaHyb55eO7F2ftdSIbeU36w9uzxoPBveozW8uOPczKkfOT/F16A/cTx3eLrgmvTB9JbDbt3Zk8VFnnAemBB2enl6P3HNMfnnEeVO9B9pDZAuO4e1f6K16nI7gtWmavsntMn5Z570uvs7xnpPd5rbWt5Pl+s0EZ8jvp9YBzxn75nTH9fun1r7PS639/sQu/e9G29rdFx8LF50h6nfRjs0bU4e3pAXfXzKQOm97Ysmvl68SLkvzQqFfeN/11A7Py/MnpZeop6efZzAvSe8adld6D/EHp9Z5z0xuTnrvVjY8HX69IH8b/3PQy5wrbSP+q5PMeFh33rY+IdtooK56WBeXzNja1sBy7pIzz+ewk999hfWyvuvKoQz8lyYPGw7xnZYO6/5LrCpeYLebl7Jw9O72X7BlZd/3bYv3iWumjvJyVfqzORunZ8X3lDuv2+9v/TTINRty0zKmq242y7Y+T/N2ov7w3mz/Qe3aSB1YfkeVGWTDSyib7eFGdZieukP7q+AvG/joya6P3bubF2X6bxWlJrpcRoDLa0Q5K76wyc0K2f48yt268FeNceXD6vfs7smfg06L6x4lJnj3KpgcleUqtdVa7X/q+Oyv9WLpjer6eum7Tr05yVPXA1alv9nz9XHp5NM3XM9If6N9upP/706/7pyX539mz48iTkjx68vez0nutX1BVX8jG1/xF7TMbtRO9P/2cPid9lOM/SW+/fO2Y9vdZa0d8aZLHVtWZtRYQNfXc9A5m70nvJPKFkZdvSD+mzhhpmL0i7aTs2Q76xCR/VFX/kP4Ad5G591atj3J2zyS/VVUfTL+enp7F7dF/kuQK43f+WkbQ8qRN+NDx3bMzv973gfQA9FsmSVVdsdYeXG5bVX1Hki+21v4yffSnWUfBaYDUTjrULQqAOzz9NUtfrKobZ/ErWTYKgtsX+5p/8zqoLQoKS/rx9sikv4p10UprfieQ9UFq2wpwbBt3WNxqQO2mHQL3wa4eyzOtd2z+8SQPqKoHbTb/vqqqg0f9O+MY+PH0tpZlOyCP5Zlxrf/JJH9Zl0AHi+qdcg4Zn6+eHtB0wcZL7ZpNOwDU4uDWDTser1vHrnYezIJBCDZI64HgLekj0F0tubizxK3Sr0vfn94RZG6H9FF3vHZr7W3p198rZ3vtK4vSs1fnjZrTUWQft8MKqLarr3iE/a+qjk4fMvF2m858AKv+XuyjW2sP22xeFqs+tPDRbe1d0ADAAaKqrtD6q9Oult7YfJttPjAHgJUzuf7NXoHz4BFcxaWEfQyssqr6fGvtCtVHxnlMa+3Hx/RnJTmjtXbSeND/zPTgrC+lj6BzbCbt2VX12iRPb62dulEbbVX9SJKnpQd3fTXJL7fWzqiqX0kfpeDfW2t3qKqT0gOrPpwezH7KSMvF6x7PBp7eWjtm3Ge+JD1A9O/TAwBukR7McnJ6EO0H00ewOWGk8/OttStM0na39FdLfjr9YfhNZ/mxP/Iv/QHxa1trN60+muKb0zuxvGb8/xPpgfKfSnKvtvaqpTckObm1tjBgvqp+I3100K+mj8L1U621/6qqv0oPAnp9kqeObX1LepDkbbIWhPXa1tpNx7oek+QKrbUTquoW6Z0gv5ge1HHsSP8N04PzvpjeGftX5uXbWN/j00dD+5f0DkQXtC28MuuSPpan2xyfr51eD3hkekDAL6bvm5l7tdYuGvOeOtK4Yefvsf0rpY+Q9N/pwZ3/MrbzLekBVH+X5NFtMnrV+mN7K1b4WF6f3rumB07eIf0tBNfMWufZT7fW7rydfBq/+W/Sgwm/nD5K302qvwXkOell2WWS/GGbvDJ73rG9E1V1ROacb+nl2p+mv4Hkw0l+rvXXA5+U3lnztPTg5UPT8/bprbUXjvU9P72s/NRYbm7AcFW9Kn1kvUoPOHlkekDydH9flLUy+fjZd7N0tNZeMT3eq48u9tT0UeaS3hHh9Hlp3Zd8201V9cAkj00P1r0gPVD851pr76uqe6QHDt+xrQvCGAFtb0sPfKwkf9lae0r1V11/flaurStHLv5uXb5dlLV8vl96R5DLpJfhD00/xl+QtUFgfqO19vqlZAgHDIE/XKpU1ePSe288oPURO1aWwJ/dIfAHAP7/9u4f5M6zDAP4daXR2BIxc0EMWKWUDi2IDjqIEVFc2qGguGQpOHRopy42k6KmRSzGyULTqWBoQLH/lCxCqEEqSdMGioXiUEQ04B9EM8jd4XtDP4JJTP2+nO8kv9/08rznvc/9nPddzjkXz7NzLV9Y92XjB6vDM3N0pQ0BwHWw/IF2VzZ+yH5mZr674pbYYu4xADvFEkI9m/e2BYW15FkGuDLBHwAAAAAAALiBtP1iNlby+MHM/HDV/cD75VkGuDrBHwAAAAAAALbNsvXWif9y6sDMnL/e/dyslq3Vvn/J8Nszc/8q+llH2/0su0f/m+3+nJYt5h64ZPjYzHxnK+rvZDfz3LdK2x9nYzvEzZ6cmadX0Q83B8EfAAAAAAAAAABYQ7tW3QAAAAAAAAAAAHDtBH8AAAAAAAAAAGANCf4AAAAAkCRpu7/t6/9njYNtj2xVTwAAAABcnuAPAAAAAAAAAACsIcEfAAAAADa7pe1P2r7R9pdtb237YNvftj3T9rm2tyVJ2wfavr6M/3pTjdvbvtT2920PXxxs+6W2r7T9Xdtjbfcu499re67ta22fuM7zBQAAAFhbnZlV9wAAAADADtB2f5K3knxqZk63/WmSnyd5cWbOL6/5dpI/zcyP2p5N8uWZeaftvpn5a9uDSQ4luTfJhSRvJvlckn8lOZ7kKzPzz7aPJtmT5EiSV5LcOTNzsc51nDYAAADA2tq96gYAAAAA2FHenpnTy/GrSfYnuXsJ/OxLsjfJy8v5k0mOLgGh45tqnJiZvyVJ23NJPrZce1eSk22T5IPZCPz8Pcm/kzzV9vkkv9i+qQEAAADcWAR/AAAAANjswqbj/yS5NcnRJPfNzJllRZ/PJ8nMfLPtZ5J8NcnptvdcpsbuJE3yq5n5+qVv2PbTSQ4k+VqSh5J8YQvnAwAAAHDD2rXqBgAAAADY8T6c5I9tP5DkGxcH2358Zk7NzKEkf0ny0SvU+E2Sz7a9Y7n2trafbLs3yUdm5oUkDye55wo1AAAAANjEij8AAAAAXM1jSU4l+UOSs9kIAiXJ420/kY3VfE4kOZPLBHdm5s/LakHPtt2zDH8ryT+S/Kzth5Y6j2zXJAAAAABuNJ2ZVfcAAAAAAAAAAABcI1t9AQAAAAAAAADAGhL8AQAAAAAAAACANST4AwAAAAAAAAAAa0jwBwAAAAAAAAAA1pDgDwAAAAAAAAAArCHBHwAAAAAAAAAAWEOCPwAAAAAAAAAAsIbeBfTCN0uo1NaFAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig = plt.figure(figsize=(40, 10))\n", + "x_list = [v[0] for v in median_times]\n", + "y_list = [v[1] for v in median_times]\n", + "plt.xlabel('hashes')\n", + "plt.ylabel('time (s)')\n", + "plt.bar(x_list, y_list)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is evident that some of the hashes take significantly longer (those with the inchikeys being almost eight times as expensive as MolFormula or DegreeVector. With this in mind, let's take a look at how long it takes to generate a mol document. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### MolDocuments\n", + "By default, `mongordkit.registration` includes only `CanonicalSmiles` and `inchikey_standard` in the hashes it generates. Let's look at time to generate mol documents for the first 200 mols in a ChEMBL dataset from above for this default scheme:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Median required time: 0.0010679960250854492, Mean required time: 0.0011445283889770508\n" + ] + } + ], + "source": [ + "scheme = registration.MolDocScheme()\n", + "times = []\n", + "for rdmol in Chem.ForwardSDMolSupplier(first_200_mols):\n", + " start = time.time()\n", + " _ = scheme.generate_mol_doc(rdmol)\n", + " end = time.time()\n", + " times.append(end - start)\n", + "print(f\"Median required time: {np.median(times)}, Mean required time: {np.mean(times)}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What if we add all the hashes back in?" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Median required time: 0.0047119855880737305, Mean required time: 0.00495597243309021\n" + ] + } + ], + "source": [ + "scheme.add_all_hashes()\n", + "times = []\n", + "for rdmol in Chem.ForwardSDMolSupplier(first_200_mols):\n", + " start = time.time()\n", + " _ = scheme.generate_mol_doc(rdmol)\n", + " end = time.time()\n", + " times.append(end - start)\n", + "print(f\"Median required time: {np.median(times)}, Mean required time: {np.mean(times)}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Adding all the hashes increases the required time by a factor of between 4 and 5. However, this is still a negligible amount (around 5%) of time compared to the time that it takes to actually write the molecule into the database from above. In fact, the total time required to generate all of these mol documents for a million molecules would be less than two hours. These benchmarks were run because writing a million molecules had taken more than three days. \n", + "\n", + "Evidently, most of the work happens in the insertion step. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "py37_rdkit_beta", + "language": "python", + "name": "py37_rdkit_beta" + }, + "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.7.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/mongordkit/Database/registration.py b/mongordkit/Database/registration.py index acf9b26..3144990 100644 --- a/mongordkit/Database/registration.py +++ b/mongordkit/Database/registration.py @@ -32,7 +32,7 @@ def __init__(self): self.author = DEFAULT_AUTHOR self.pre_processed = DEFAULT_PREPROCESS self.index_option = DEFAULT_INDEX - self.hashes = set(HASH_FUNCTIONS.keys()) + self.hashes = {'CanonicalSmiles', 'inchikey_standard'} self.fingerprints = {} self.value_fields = {} @@ -56,9 +56,16 @@ def get_index_value(self, rdmol): else: raise Exception("Specified index option does not exist.") - def add_hash_field(self, field_name, field_method): - self.hashes.add(field_name) - HASH_FUNCTIONS[field_name] = field_method + def add_hash_field(self, field_name, field_method=None): + if field_name in HASH_FUNCTIONS: + self.hashes.add(field_name) + else: + HASH_FUNCTIONS[field_name] = field_method + self.hashes.add(field_name) + + def add_all_hashes(self): + for function in HASH_FUNCTIONS.keys(): + self.hashes.add(function) def add_value_field(self, field_name, field_value): self.value_fields[field_name] = field_value diff --git a/mongordkit/Database/tests/test_write.py b/mongordkit/Database/tests/test_write.py index d09b240..da0c9b9 100644 --- a/mongordkit/Database/tests/test_write.py +++ b/mongordkit/Database/tests/test_write.py @@ -32,7 +32,7 @@ def test_hashes(self): data_scheme = registration.MolDocScheme() data_scheme.set_index("CanonicalSmiles") assert 200 == write.WriteFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', data_scheme) - data_scheme.set_index("inchi_standard") + data_scheme.set_index("inchikey_standard") assert 200 == write.WriteFromSDF(db.molecules, 'data/test_data/first_200.props.sdf', data_scheme) def test_uniqueInsertion(self): diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 40f2f73..0000000 --- a/requirements.txt +++ /dev/null @@ -1,24 +0,0 @@ -attrs==19.3.0 -certifi==2019.11.28 -importlib-metadata==1.6.1 -mkl-fft==1.0.15 -mkl-random==1.1.0 -mkl-service==2.3.0 -mongomock==3.19.0 -more-itertools==8.3.0 -numpy==1.18.1 -olefile==0.46 -packaging==20.4 -pandas==1.0.3 -Pillow==7.0.0 -pluggy==0.13.1 -py==1.8.1 -pymongo==3.10.1 -pyparsing==2.4.7 -pytest==5.4.3 -python-dateutil==2.8.1 -pytz==2019.3 -sentinels==1.0.0 -six==1.14.0 -wcwidth==0.2.4 -zipp==3.1.0 diff --git a/setup.txt b/setup.txt deleted file mode 100644 index 0cbad19..0000000 --- a/setup.txt +++ /dev/null @@ -1,56 +0,0 @@ -Basic requirements for running mongo-rdkit: - -Packages currently installed in my Conda environment: -blas 1.0 mkl -bzip2 1.0.8 h1de35cc_0 -ca-certificates 2020.1.1 0 -cairo 1.14.12 hc4e6be7_4 -certifi 2019.11.28 py37_1 -fontconfig 2.13.0 h5d5b041_1 -freetype 2.9.1 hb4e5f40_0 -gettext 0.19.8.1 h15daf44_3 -glib 2.63.1 hd977a24_0 -icu 58.2 h4b95b61_1 -intel-openmp 2019.4 233 -jpeg 9b he5867d9_2 -libboost 1.67.0 hebc422b_4 -libcxx 4.0.1 hcfea43d_1 -libcxxabi 4.0.1 hcfea43d_1 -libedit 3.1.20181209 hb402a30_0 -libffi 3.2.1 h475c297_4 -libgfortran 3.0.1 h93005f0_2 -libiconv 1.15 hdd342a3_7 -libpng 1.6.37 ha441bb4_0 -libtiff 4.1.0 hcb84e12_0 -libxml2 2.9.9 hf6e021a_1 -mkl 2019.4 233 -mkl-service 2.3.0 py37hfbe908c_0 -mkl_fft 1.0.15 py37h5e564d8_0 -mkl_random 1.1.0 py37ha771720_0 -ncurses 6.2 h0a44026_0 -numpy 1.18.1 py37h7241aed_0 -numpy-base 1.18.1 py37h6575580_1 -olefile 0.46 py37_0 -openssl 1.1.1e h1de35cc_0 -pandas 1.0.3 py37h6c726b0_0 -pcre 8.43 h0a44026_0 -pillow 7.0.0 py37h4655f20_0 -pip 20.0.2 py37_1 -pixman 0.38.0 h1de35cc_0 -py-boost 1.67.0 py37h6440ff4_4 -pymongo 3.10.1 pypi_0 pypi -python 3.7.7 hc70fcce_0_cpython -python-dateutil 2.8.1 py_0 -pytz 2019.3 py_0 -rdkit 2020.03.1b1.0 py37h65625ec_1 rdkit/label/beta -readline 8.0 h1de35cc_0 -setuptools 46.1.1 py37_0 -six 1.14.0 py37_0 -sqlite 3.31.1 ha441bb4_0 -tk 8.6.8 ha441bb4_0 -wheel 0.34.2 py37_0 -xz 5.2.4 h1de35cc_4 -zlib 1.2.11 h1de35cc_3 -zstd 1.3.7 h5bba6e5_0 - -Most of these packages install by default when installing Anaconda. Will document for better reproducibility in the future. From d269d68127a37c02edace8ec93e52d222b19df1c Mon Sep 17 00:00:00 2001 From: Christopher Zou Date: Tue, 25 Aug 2020 13:00:01 -0400 Subject: [PATCH 6/7] Add write benchmarks and edit default registration --- .../Write and Registration Benchmarking.ipynb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/notebooks/Write and Registration Benchmarking.ipynb b/docs/notebooks/Write and Registration Benchmarking.ipynb index 468c5d0..cc4b856 100644 --- a/docs/notebooks/Write and Registration Benchmarking.ipynb +++ b/docs/notebooks/Write and Registration Benchmarking.ipynb @@ -133,6 +133,22 @@ "populating mongodb collection with compounds from SDF...\n", "3000 molecules successfully imported\n", "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n", + "3000 molecules successfully imported\n", + "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n", + "3000 molecules successfully imported\n", + "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n", + "3000 molecules successfully imported\n", + "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n", + "3000 molecules successfully imported\n", + "0 duplicates skipped\n", + "testing 4000\n", + "populating mongodb collection with compounds from SDF...\n", + "4000 molecules successfully imported\n", + "0 duplicates skipped\n", "populating mongodb collection with compounds from SDF...\n" ] } From 690eabb1c41f59946889ad0202693c03b6cadcf3 Mon Sep 17 00:00:00 2001 From: Christopher Zou Date: Tue, 25 Aug 2020 13:07:46 -0400 Subject: [PATCH 7/7] delete ipynb checkpoints --- .../.ipynb_checkpoints/.ipynb-checkpoint | 92 --- ...ng and Writing to MongoDB-checkpoint.ipynb | 633 ----------------- ...y and Substructure Search-checkpoint.ipynb | 648 ------------------ .../Write and Registration Benchmarking.ipynb | 16 + 4 files changed, 16 insertions(+), 1373 deletions(-) delete mode 100644 docs/notebooks/.ipynb_checkpoints/.ipynb-checkpoint delete mode 100644 docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb delete mode 100644 docs/notebooks/.ipynb_checkpoints/Similarity and Substructure Search-checkpoint.ipynb diff --git a/docs/notebooks/.ipynb_checkpoints/.ipynb-checkpoint b/docs/notebooks/.ipynb_checkpoints/.ipynb-checkpoint deleted file mode 100644 index 80af95b..0000000 --- a/docs/notebooks/.ipynb_checkpoints/.ipynb-checkpoint +++ /dev/null @@ -1,92 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Creating and Writing to MongoDB\n", - "\n", - "Methods that directly modify MongoDB database instances are included in the `mongordkit.Database` module.\n", - "\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "from mongordkit.Database import *" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating Databases\n", - "Users can opt to bring their own database instances, but `Database.create` provides a variety of ways to create a `mongordkit`-compatible MongoDB instance:" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "ename": "DuplicateKeyError", - "evalue": "E11000 duplicate key error collection: MyDatabase.registration index: _id_ dup key: { _id: ObjectId('5f0f64b2eaae47671ad2fb9d') }", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mDuplicateKeyError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mdb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mDatabase\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcreate\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcreateFromHostPort\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'MyDatabase'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mhost\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mport\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mdb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mDatabase\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcreate\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcreateFromURI\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'MyDatabase'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0murl\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/Desktop/mongo-rdkit/mongordkit/Database/create.py\u001b[0m in \u001b[0;36mcreateFromHostPort\u001b[0;34m(dbname, host, port)\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0mdb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mclient\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mdbname\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0mcollection\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdb\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'registration'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 19\u001b[0;31m \u001b[0mcollection\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minsert_one\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mSTANDARD_SETTING\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 20\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mdb\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 21\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/envs/py37_rdkit_beta/lib/python3.7/site-packages/pymongo/collection.py\u001b[0m in \u001b[0;36minsert_one\u001b[0;34m(self, document, bypass_document_validation, session)\u001b[0m\n\u001b[1;32m 696\u001b[0m \u001b[0mwrite_concern\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mwrite_concern\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 697\u001b[0m \u001b[0mbypass_doc_val\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mbypass_document_validation\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 698\u001b[0;31m session=session),\n\u001b[0m\u001b[1;32m 699\u001b[0m write_concern.acknowledged)\n\u001b[1;32m 700\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/envs/py37_rdkit_beta/lib/python3.7/site-packages/pymongo/collection.py\u001b[0m in \u001b[0;36m_insert\u001b[0;34m(self, docs, ordered, check_keys, manipulate, write_concern, op_id, bypass_doc_val, session)\u001b[0m\n\u001b[1;32m 610\u001b[0m return self._insert_one(\n\u001b[1;32m 611\u001b[0m \u001b[0mdocs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mordered\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcheck_keys\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmanipulate\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mwrite_concern\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mop_id\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 612\u001b[0;31m bypass_doc_val, session)\n\u001b[0m\u001b[1;32m 613\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 614\u001b[0m \u001b[0mids\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/envs/py37_rdkit_beta/lib/python3.7/site-packages/pymongo/collection.py\u001b[0m in \u001b[0;36m_insert_one\u001b[0;34m(self, doc, ordered, check_keys, manipulate, write_concern, op_id, bypass_doc_val, session)\u001b[0m\n\u001b[1;32m 598\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 599\u001b[0m self.__database.client._retryable_write(\n\u001b[0;32m--> 600\u001b[0;31m acknowledged, _insert_command, session)\n\u001b[0m\u001b[1;32m 601\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 602\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdoc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mRawBSONDocument\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/envs/py37_rdkit_beta/lib/python3.7/site-packages/pymongo/mongo_client.py\u001b[0m in \u001b[0;36m_retryable_write\u001b[0;34m(self, retryable, func, session)\u001b[0m\n\u001b[1;32m 1489\u001b[0m \u001b[0;34m\"\"\"Internal retryable write helper.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1490\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_tmp_session\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msession\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0ms\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1491\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_retry_with_session\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mretryable\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ms\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1492\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1493\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_reset_server\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maddress\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/envs/py37_rdkit_beta/lib/python3.7/site-packages/pymongo/mongo_client.py\u001b[0m in \u001b[0;36m_retry_with_session\u001b[0;34m(self, retryable, func, session, bulk)\u001b[0m\n\u001b[1;32m 1382\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mlast_error\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1383\u001b[0m \u001b[0mretryable\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1384\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msession\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msock_info\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mretryable\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1385\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mServerSelectionTimeoutError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1386\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mis_retrying\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/envs/py37_rdkit_beta/lib/python3.7/site-packages/pymongo/collection.py\u001b[0m in \u001b[0;36m_insert_command\u001b[0;34m(session, sock_info, retryable_write)\u001b[0m\n\u001b[1;32m 595\u001b[0m retryable_write=retryable_write)\n\u001b[1;32m 596\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 597\u001b[0;31m \u001b[0m_check_write_command_response\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 598\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 599\u001b[0m self.__database.client._retryable_write(\n", - "\u001b[0;32m~/anaconda3/envs/py37_rdkit_beta/lib/python3.7/site-packages/pymongo/helpers.py\u001b[0m in \u001b[0;36m_check_write_command_response\u001b[0;34m(result)\u001b[0m\n\u001b[1;32m 219\u001b[0m \u001b[0mwrite_errors\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"writeErrors\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 220\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mwrite_errors\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 221\u001b[0;31m \u001b[0m_raise_last_write_error\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mwrite_errors\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 222\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 223\u001b[0m \u001b[0merror\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"writeConcernError\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda3/envs/py37_rdkit_beta/lib/python3.7/site-packages/pymongo/helpers.py\u001b[0m in \u001b[0;36m_raise_last_write_error\u001b[0;34m(write_errors)\u001b[0m\n\u001b[1;32m 200\u001b[0m \u001b[0merror\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mwrite_errors\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 201\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0merror\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"code\"\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m11000\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 202\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mDuplicateKeyError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0merror\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"errmsg\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m11000\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0merror\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 203\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mWriteError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0merror\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"errmsg\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0merror\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"code\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0merror\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 204\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mDuplicateKeyError\u001b[0m: E11000 duplicate key error collection: MyDatabase.registration index: _id_ dup key: { _id: ObjectId('5f0f64b2eaae47671ad2fb9d') }" - ] - } - ], - "source": [ - "db = Database.create.createFromHostPort('MyDatabase', host=None, port=None)\n", - "db = Database.create.createFromURI('MyDatabase', url=None)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "py37_rdkit_beta", - "language": "python", - "name": "py37_rdkit_beta" - }, - "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.7.7" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb b/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb deleted file mode 100644 index fdbf379..0000000 --- a/docs/notebooks/.ipynb_checkpoints/Creating and Writing to MongoDB-checkpoint.ipynb +++ /dev/null @@ -1,633 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Creating and Writing to MongoDB\n", - "\n", - "Last updated: 8/10/20\n", - "\n", - "Methods that directly modify MongoDB database instances are included in the `mongordkit.Database` module.\n", - "\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "from mongordkit.Database import create, write, utils, registration\n", - "from rdkit import Chem\n", - "import pymongo" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Reset Cells\n", - "Run the contents of this cell to reset the local MongoDB database, `demo_db`, used in this notebook." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "client = pymongo.MongoClient()\n", - "client.drop_database('demo_db')\n", - "demo_db = client.demo_db\n", - "\n", - "# Disable rdkit warnings\n", - "rdkit.RDLogger.DisableLog('rdApp.*')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Creating Databases (DEPRECATED for now)\n", - "Users can opt to bring their own database instances, but `Database.create` provides methods that will create ready-made MongoDB instances, defaulting to your local MongoDB:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# # Return a database using a host port, such as the local port:\n", - "# db = create.createFromHostPort('demo_db', host='localhost', port=27017)\n", - "\n", - "# # Return a database using a MongoDB URI, such as that provided by Atlas:\n", - "# TestDB = create.createFromURL('demo_db', url=None)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "These databases are created with a `registration` collection. The registration collection includes several documents that consist of common pre-made settings, with the default being `STANDARD_SETTING`. All settings are documented in `Database.utils`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# print(utils.STANDARD_SETTING)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Data Registration\n", - "`Database.registration` constructs document representations of molecules according to configurable schemes and handles data registration settings.\n", - "\n", - "It does this in two parts. First, it defines the global variable `HASH_FUNCTIONS` as a dictionary that maps hash function names to methods. It also defines the global variables `DEFAULT_SCHEME_NAME`, `DEFAULT_AUTHOR`, `DEFAULT_PREPROCESS`, and `DEFAULT_INDEX`, which are used in scheme creation and are thus defined for easy configuration. \n", - "\n", - "Second, the file defines the `MolDocScheme` object, which stores scheme information in its instance variables and is passed into `.write` methods in order to specify molecule document format. By default, `MolDocScheme` includes scheme name, author, whether or not the molecule has been pre-processed, an index option, two hashes, fingerprints, and value fields. All of the information contained in a `MolDocScheme` object can be used directly to generate documents for molecules:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'rdmol': Binary(b'\\xef\\xbe\\xad\\xde\\x00\\x00\\x00\\x00\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x80\\x01\\x06\\x00`\\x00\\x00\\x00\\x01\\x03\\x06@(\\x00\\x00\\x00\\x03\\x04\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x0b\\x00\\x01\\x00\\x01\\x02h\\x0c\\x02\\x03h\\x0c\\x03\\x04h\\x0c\\x04\\x05h\\x0c\\x05\\x06h\\x0c\\x06\\x01h\\x0c\\x14\\x01\\x06\\x01\\x06\\x05\\x04\\x03\\x02\\x17\\x00\\x00\\x00\\x00\\x16', 0),\n", - " 'index': 'YXFVVABEGXRONW-UHFFFAOYSA-N',\n", - " 'smiles': 'Cc1ccccc1',\n", - " 'scheme': 'default',\n", - " 'hashes': {'MolFormula': 'C7H8',\n", - " 'SmallWorldIndexBRL': 'B7R1L5',\n", - " 'AtomBondCounts': '7,7',\n", - " 'cx_smiles': 'Cc1ccccc1',\n", - " 'NetCharge': '0',\n", - " 'CanonicalSmiles': 'Cc1ccccc1',\n", - " 'inchikey_standard': 'YXFVVABEGXRONW-UHFFFAOYSA-N',\n", - " 'inchikey_KET_15T': 'YXFVVABEGXRONW-UHFFFAOYNA-N',\n", - " 'SmallWorldIndexBR': 'B7R1',\n", - " 'DegreeVector': '0,1,5,1',\n", - " 'ElementGraph': 'CC1CCCCC1',\n", - " 'HetAtomTautomer': 'C[C]1[CH][CH][CH][CH][CH]1_0_0',\n", - " 'inchi_standard': 'InChI=1S/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", - " 'RedoxPair': 'C[C]1[CH][CH][CH][CH][CH]1',\n", - " 'AnonymousGraph': '**1*****1',\n", - " 'Mesomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", - " 'Regioisomer': '*C.c1ccccc1',\n", - " 'inchi_KET_15T': 'InChI=1/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", - " 'MurckoScaffold': 'c1ccccc1',\n", - " 'ArthorSubstructureOrder': '00070007010007000000002a000000',\n", - " 'noiso_smiles': 'Cc1ccccc1',\n", - " 'ExtendedMurcko': '*c1ccccc1',\n", - " 'HetAtomProtomer': 'C[C]1[CH][CH][CH][CH][CH]1_0'},\n", - " 'fingerprints': {},\n", - " 'value_data': {}}" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "rdmol = Chem.MolFromSmiles('Cc1ccccc1')\n", - "scheme = registration.MolDocScheme()\n", - "scheme.generate_mol_doc(rdmol)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `MolDocScheme` class also defines a series of instance methods, such as `MolDocScheme.set_index` and `MolDocScheme.remove_field`, that can be used to modify document schemes:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "removed AnonymousGraph from scheme\n" - ] - }, - { - "data": { - "text/plain": [ - "{'rdmol': Binary(b'\\xef\\xbe\\xad\\xde\\x00\\x00\\x00\\x00\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x80\\x01\\x06\\x00`\\x00\\x00\\x00\\x01\\x03\\x06@(\\x00\\x00\\x00\\x03\\x04\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x0b\\x00\\x01\\x00\\x01\\x02h\\x0c\\x02\\x03h\\x0c\\x03\\x04h\\x0c\\x04\\x05h\\x0c\\x05\\x06h\\x0c\\x06\\x01h\\x0c\\x14\\x01\\x06\\x01\\x06\\x05\\x04\\x03\\x02\\x17\\x00\\x00\\x00\\x00\\x16', 0),\n", - " 'index': 'C7H8',\n", - " 'smiles': 'Cc1ccccc1',\n", - " 'scheme': 'default',\n", - " 'hashes': {'MolFormula': 'C7H8',\n", - " 'SmallWorldIndexBRL': 'B7R1L5',\n", - " 'AtomBondCounts': '7,7',\n", - " 'cx_smiles': 'Cc1ccccc1',\n", - " 'NetCharge': '0',\n", - " 'CanonicalSmiles': 'Cc1ccccc1',\n", - " 'inchikey_standard': 'YXFVVABEGXRONW-UHFFFAOYSA-N',\n", - " 'inchikey_KET_15T': 'YXFVVABEGXRONW-UHFFFAOYNA-N',\n", - " 'SmallWorldIndexBR': 'B7R1',\n", - " 'DegreeVector': '0,1,5,1',\n", - " 'ElementGraph': 'CC1CCCCC1',\n", - " 'HetAtomTautomer': 'C[C]1[CH][CH][CH][CH][CH]1_0_0',\n", - " 'inchi_standard': 'InChI=1S/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", - " 'RedoxPair': 'C[C]1[CH][CH][CH][CH][CH]1',\n", - " 'Mesomer': 'C[C]1[CH][CH][CH][CH][CH]1_0',\n", - " 'Regioisomer': '*C.c1ccccc1',\n", - " 'inchi_KET_15T': 'InChI=1/C7H8/c1-7-5-3-2-4-6-7/h2-6H,1H3',\n", - " 'MurckoScaffold': 'c1ccccc1',\n", - " 'ArthorSubstructureOrder': '00070007010007000000002a000000',\n", - " 'noiso_smiles': 'Cc1ccccc1',\n", - " 'ExtendedMurcko': '*c1ccccc1',\n", - " 'HetAtomProtomer': 'C[C]1[CH][CH][CH][CH][CH]1_0'},\n", - " 'fingerprints': {},\n", - " 'value_data': {}}" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "scheme.remove_field('CanonicalSmiles')\n", - "scheme.add_hash_field('MolFormula')\n", - "scheme.set_index('MolFormula')\n", - "scheme.generate_mol_doc(rdmol)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Because `MolDocScheme` objects contain no functions—only references to functions—they can be pickled. In fact, the methods in `write` can save `MolDocSchemes` so that custom schemes are retrievable for later use." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Writing to a Database\n", - "`Database.write` provides write functionality. Its core method is `WriteFromSDF`, which relies on rdkit's `ForwardSDMolSupplier` to write data from an SDF file into a specified database.\n", - "\n", - "For each molecule in the SDF, `WriteFromSDF` inserts a document whose fields are specified by the `MolDocScheme` object passed into the function (one with default settings is created if the `scheme` argument is left blank)." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "populating mongodb collection with compounds from SDF...\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:46] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:46] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:46] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", - "RDKit WARNING: [15:39:46] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "200 molecules successfully imported\n", - "0 duplicates skipped\n" - ] - }, - { - "data": { - "text/plain": [ - "200" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Write the contents of first_200_props.sdf, a test dataset, into the collection demo_db.molecules.\n", - "# The index will default to the molecule's inchikey.\n", - "# Return the number of molecules succesfully imported.\n", - "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The above call is the most basic version of `writeFromSDF`. For additional flexibility, `writeFromSDF` takes several optional arguments—users can specify a custom scheme object, a registration collection to write scheme objects to, how many molecules are inserted at a time (this can affect performance), and limit the number of molecules written in." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "populating mongodb collection with compounds from SDF...\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:47] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:47] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:48] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:48] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:48] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:50] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:39:50] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", - "RDKit WARNING: [15:39:50] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:39:50] WARNING: Omitted undefined stereo\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "100 molecules successfully imported\n", - "0 duplicates skipped\n" - ] - }, - { - "data": { - "text/plain": [ - "100" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Write the first 100 molecules of first_200_props.sdf, a test dataset, into demo_db.molecules\n", - "# This write will use canonical SMILES as the identifying index and thus does not conflict with the above write. \n", - "# If we had used inchikey again, the write would have imported 0 molecules.\n", - "scheme = registration.MolDocScheme()\n", - "scheme.set_index('CanonicalSmiles')\n", - "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf', \n", - " scheme, reg_collection=demo_db.schema, chunk_size=50, limit=100)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In the case that users aren't working with an SDF, `.write` also provides `WriteFromMolList`, which will take a Python list of rdmol objects in place of the SDF argument in `WriteFromSDF`." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## `.create` Module Contents\n", - "\n", - "mongordkit.Database.create.**createFromHostPort**(database_name, host=None (*string*), port=None (*string*)) --> *a MongoDB database instance named database_name*\n", - "\n", - "mongordkit.Database.create.**createFromURL**(database_name, url=None (*string*)) --> *a MongoDB database instance named database_name*" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## `.registration` Module Contents" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'AnonymousGraph': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.AnonymousGraph)>,\n", - " 'ElementGraph': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.ElementGraph)>,\n", - " 'CanonicalSmiles': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.CanonicalSmiles)>,\n", - " 'MurckoScaffold': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.MurckoScaffold)>,\n", - " 'ExtendedMurcko': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.ExtendedMurcko)>,\n", - " 'MolFormula': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.MolFormula)>,\n", - " 'AtomBondCounts': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.AtomBondCounts)>,\n", - " 'DegreeVector': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.DegreeVector)>,\n", - " 'Mesomer': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.Mesomer)>,\n", - " 'HetAtomTautomer': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.HetAtomTautomer)>,\n", - " 'HetAtomProtomer': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.HetAtomProtomer)>,\n", - " 'RedoxPair': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.RedoxPair)>,\n", - " 'Regioisomer': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.Regioisomer)>,\n", - " 'NetCharge': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.NetCharge)>,\n", - " 'SmallWorldIndexBR': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.SmallWorldIndexBR)>,\n", - " 'SmallWorldIndexBRL': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.SmallWorldIndexBRL)>,\n", - " 'ArthorSubstructureOrder': (rdmol, f=rdkit.Chem.rdMolHash.HashFunction.ArthorSubstructureOrder)>,\n", - " 'inchi_standard': ,\n", - " 'inchikey_standard': ,\n", - " 'inchi_KET_15T': (rdmol)>,\n", - " 'inchikey_KET_15T': (rdmol)>,\n", - " 'noiso_smiles': (rdmol)>,\n", - " 'cx_smiles': }" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "registration.HASH_FUNCTIONS" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Class** mongordkit.Database.registration.**MolDocScheme()**\n", - "\n", - "**Instance variables**:\n", - "```\n", - "self.scheme_name = DEFAULT_SCHEME_NAME\n", - "self.author = DEFAULT_AUTHOR\n", - "self.pre_processed = DEFAULT_PREPROCESS\n", - "self.index_option = DEFAULT_INDEX\n", - "self.hashes = set(HASH_FUNCTIONS.keys())\n", - "self.fingerprints = {}\n", - "self.value_fields = {}\n", - "```\n", - "**Instance methods**:\n", - "- set_index(self, new_index) --> *None*\n", - "- get_index_value(self, rdmol) --> *calculated index value*\n", - "- add_hash_field(self, field_name, field_method) --> *None*\n", - "- add_value_field(self, field_name, field_value) --> *None*\n", - "- add_all_hashes(self) --> *None*\n", - "- remove_field(self, field_name) --> *None*\n", - "- generate_mol_doc(self, rdmol) --> *Dict: document representing molecule according to scheme*" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## `.write` Module Contents" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "mongordkit.Database.write.**WriteFromSDF**(database, sdf, scheme=MolDocScheme(), reg_collection=None, chunk_size=100, limit=None, warnings=False (*Make this true to turn on rdkit warnings*) --> *int: number of molecules imported*\n", - "\n", - "mongordkit.Database.write.**WriteFromMolList**(database, list, scheme=MolDocScheme(), reg_collection=None, chunk_size=100, limit=None) --> *int: number of molecules imported*" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "py37_rdkit_beta", - "language": "python", - "name": "py37_rdkit_beta" - }, - "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.7.7" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/docs/notebooks/.ipynb_checkpoints/Similarity and Substructure Search-checkpoint.ipynb b/docs/notebooks/.ipynb_checkpoints/Similarity and Substructure Search-checkpoint.ipynb deleted file mode 100644 index 33285bc..0000000 --- a/docs/notebooks/.ipynb_checkpoints/Similarity and Substructure Search-checkpoint.ipynb +++ /dev/null @@ -1,648 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Similarity and Substructure Search\n", - "\n", - "Last updated: 8/11/20\n", - "\n", - "Methods for similarity and substructure search are included in the `mongordkit.Search` module." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "from mongordkit.Search import similarity, substructure, utils\n", - "from mongordkit import Search\n", - "from mongordkit.Database import create, write\n", - "from rdkit import Chem\n", - "import pymongo" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Reset Cells\n", - "\n", - "Run these cells to reset the MongoDB database used in this notebook." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "client = pymongo.MongoClient()\n", - "client.drop_database('demo_db')\n", - "demo_db = client.demo_db\n", - "\n", - "# Disable rdkit warnings\n", - "rdkit.RDLogger.DisableLog('rdApp.*')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Preparing for Search\n", - "Adequately preparing the database for searching requires adding a variety of fingerprints and hashes. You can easily perform all of the setup work required for similarity and substructure search by calling the method `Search.PrepareForSearch`. Generally, workflow will follow straight from the following two lines into search calls:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "populating mongodb collection with compounds from SDF...\n", - "200 molecules successfully imported\n", - "0 duplicates skipped\n", - "Preparing database and collections for search...\n", - "Added pattern fps, morgan fps, and support for LSH.\n" - ] - } - ], - "source": [ - "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf')\n", - "Search.PrepareForSearch(demo_db, demo_db.molecules, demo_db.mfp_counts, demo_db.permutations)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "However, the rest of this notebook will explicitly note the addition of fingerprints and hashes in an effort to better communicate how the code actually works. Let's reset the database again so that we can insert the hashes step by step without any issues." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "client.drop_database('demo_db')\n", - "demo_db = client.demo_db" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Similarity Search\n", - "\n", - "`mongordkit.Search.similarity` supports similarity search best on a MongoDB collection prepared by `mongordkit.Database.write`. For the general level of similarity search, users can also use any collection that has documents with the following fields:\n", - "- `'rdmol': binary pickle object`\n", - "- `'index': a unique identifier for each molecule`\n", - "- `'fingerprints': {a nested document that can be blank at the start}'`" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's run through an example of similarity search. First, we'll write into the database 200 molecules from a data file included in the `mongordkit` package. We will use default write settings." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "populating mongodb collection with compounds from SDF...\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:23] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:23] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:38] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:38] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", - "RDKit WARNING: [15:43:38] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected\n", - "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:38] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Accepted unusual valence(s): Cu(4); Metal was disconnected; Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged; Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:39] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:39] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:40] WARNING: Charges were rearranged\n", - "RDKit WARNING: [15:43:40] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:40] WARNING: Omitted undefined stereo\n", - "RDKit WARNING: [15:43:40] WARNING: Omitted undefined stereo\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "200 molecules successfully imported\n", - "0 duplicates skipped\n" - ] - }, - { - "data": { - "text/plain": [ - "200" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "write.WriteFromSDF(demo_db.molecules, '../../data/test_data/first_200.props.sdf')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`similarity.SimSearchNaive` will directly loop through the database and display results. This is good for purposes of verifying accuracy. However, this implementation is extremely slow for any decently-sized database. Instead, `similarity` supports precalculating the following kinds of fingerprints for screening: \n", - "- Morgan (default radius 2, length 2048)\n", - "\n", - "through `similarity.AddMorganFingerprints`. For each document in a passed in collection, this method adds the nested field `{morgan_fp: {bits: }, {count: }}` to the document's `fingerprint` field. `AddMorganFingerprints` also creates indices on `morgan_fp[bits]` and `morgan_fp[count]` to speed search. " - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "similarity.AddMorganFingerprints(demo_db.molecules, demo_db.mfp_counts)" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'bits': [84,\n", - " 314,\n", - " 356,\n", - " 547,\n", - " 650,\n", - " 747,\n", - " 967,\n", - " 1057,\n", - " 1080,\n", - " 1154,\n", - " 1337,\n", - " 1380,\n", - " 1722,\n", - " 1768,\n", - " 1873,\n", - " 1877],\n", - " 'count': 16}" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "demo_db.molecules.find_one()['fingerprints']['morgan_fp']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "From here, we can directly perform similarity search. `similarity` provides two methods that take advantage of fingerprint screening: `similaritySearch` and `similaritySearchAggregate`. The latter shifts much of the computation into the MongoDB server by using an aggregation pipeline and can dramatically improve performance when working with sharded MongoDB servers." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "similaritySearch: [[0.4117647058823529, 'WLHCBQAPPJAULW-UHFFFAOYSA-N']]\n", - "\n", - "\n", - "similaritySearchAggregate: [[0.4117647058823529, 'WLHCBQAPPJAULW-UHFFFAOYSA-N']]\n" - ] - } - ], - "source": [ - "q_mol = Chem.MolFromSmiles('Cc1ccccc1')\n", - "\n", - "# Perform a similarity search on TestDB for q_mol with a Tanimoto threshold of 0.4. \n", - "results1 = similarity.SimSearch(q_mol, demo_db.molecules, demo_db.mfp_counts, 0.4)\n", - "\n", - "# Do the same thing, but use the MongoDB Aggregation Pipeline. \n", - "results2 = similarity.SimSearchAggregate(q_mol, demo_db.molecules, demo_db.mfp_counts, 0.4)\n", - "\n", - "print('similaritySearch: {}'.format(results1))\n", - "print('\\n')\n", - "print('similaritySearchAggregate: {}'.format(results2))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that the search returns only the index for the molecule, which in this case is the inchikey; users should find it easy to go from the index to the full molecule document by way of a quick search. This also makes it easier for users to retrieve molecules when indices represent multiple tautomers or isomers in the collection.\n", - "\n", - "`SimSearch` and `SimSearchAggregate` both make use of the conventional fingerprint screening method. `similarity` also supports searching using Locality Sensitive Hashing, as developed by ChemBL in an excellent [blog post](http://chembl.blogspot.com/2015/08/lsh-based-similarity-search-in-mongodb.html). The method here is called `SimSearchLSH` and requires a little bit more setup work:" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "# Generate 100 different permutations of length 2048 and save them in demo_db.permutations as separate documents.\n", - "similarity.AddRandPermutations(demo_db.permutations)\n", - "\n", - "# Add locality-sensitive hash values to each documents in demo_db.molecules by splitting the 100 different permutations\n", - "# in demo_db.permutations into 25 different buckets. \n", - "similarity.AddLocalityHashes(demo_db.molecules, demo_db.permutations, 25)\n", - "\n", - "# Create 25 different collections in db_demo each store a subset of hash values for molecules in demo_db.molecules.\n", - "similarity.AddHashCollections(demo_db, demo_db.molecules)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's try a search using the query molecule from earlier:" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "similaritySearchLSH: []\n" - ] - } - ], - "source": [ - "q_mol = Chem.MolFromSmiles('Cc1ccccc1')\n", - "\n", - "results3 = similarity.SimSearchLSH(q_mol, demo_db, demo_db.molecules, \n", - " demo_db.permutations, demo_db.mfp_counts, threshold=0.8)\n", - "\n", - "print('similaritySearchLSH: {}'.format(results3))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The LSH algorithm relies on random permutations using the `numpy` module, so it yields non-deterministic results. This means that LSH is well-suited for *scanning* datasets (its performance on large datasets is faster than either similarity search method), but is less accurate than regular similarity search, especially below thresholds of 0.7. Specific notes on benchmarks can be found in \"Benchmarking Similarity Search.\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Substructure Search\n", - "\n", - "`mongordkit.Search.substructure` supports substructure search best on collections prepared by `write`. Requirements are identical to those for similarity search: a `molecules` collection whose documents have `rdmol` and `index` fields. \n", - "\n", - "`substructure.SubSearchNaive` provides a fingerprint-less, slower implementation of substructure search suitable for very small databases:" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['RUTYZGCHBCCSKD-UHFFFAOYSA-N',\n", - " 'WECJUPODCKXNQK-UHFFFAOYSA-N',\n", - " 'GZZJZWYIOOPHOV-UHFFFAOYSA-N',\n", - " 'FXOSHPAYNZBSFO-RMKNXTFCSA-N',\n", - " 'KWLUBKHLCNCFQI-UHFFFAOYSA-N',\n", - " 'VDAJDWUTRXNYMU-RUDMXATFSA-N',\n", - " 'PACGLQCRGWFBJH-UHFFFAOYSA-N',\n", - " 'CDCRUVGWQJYTFO-UHFFFAOYSA-N']" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "q_mol = Chem.MolFromSmiles('C1=CC=CC=C1OC')\n", - "\n", - "# Perform a substructure search for q_mol on TestDB. \n", - "substructure.SubSearchNaive(q_mol, demo_db.molecules, chirality=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "By adding pattern fingerprints, which are optimized for substructure search, we can use `substructure.SubSearch`, which takes advantage of fingerprint screening to avoid as many expensive calls to `HasSubstructMatch` as possible. " - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['RUTYZGCHBCCSKD-UHFFFAOYSA-N',\n", - " 'WECJUPODCKXNQK-UHFFFAOYSA-N',\n", - " 'GZZJZWYIOOPHOV-UHFFFAOYSA-N',\n", - " 'FXOSHPAYNZBSFO-RMKNXTFCSA-N',\n", - " 'KWLUBKHLCNCFQI-UHFFFAOYSA-N',\n", - " 'VDAJDWUTRXNYMU-RUDMXATFSA-N',\n", - " 'PACGLQCRGWFBJH-UHFFFAOYSA-N',\n", - " 'CDCRUVGWQJYTFO-UHFFFAOYSA-N']" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "substructure.AddPatternFingerprints(demo_db.molecules)\n", - "substructure.SubSearch(q_mol, demo_db.molecules, chirality=False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## `.Search` contents" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "mongordkit.Search.**PrepareForSearch**(db (*MongoDB database for hash information*), mol_collection (*MongoDB collection*), count_collection (*MongoDB collection*), perm_collection (*MongoDB collection*)) --> None" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## `.similarity` Contents\n", - "\n", - "### Constants:\n", - "- DEFAULT_THRESHOLD = 0.8\n", - "- DEFAULT_MORGAN_RADIUS = 2\n", - "- DEFAULT_MORGAN_LENGTH = 2048\n", - "- DEFAULT_BIT_N = 2048\n", - "- DEFAULT_BUCKET_N = 25\n", - "- DEFAULT_PERM_LEN = 2048\n", - "- DEFAULT_PERM_N = 100\n", - "\n", - "mongordkit.Search.similarity.**AddMorganFingerprints**(mol_collection (*MongoDB collection*), count_collection (*MongoDB collection*), radius=2 (*int: radius of Morgan fingerprint*), length=2048 (*int: length of Morgan fingerprint bit vector*)) --> None\n", - "\n", - "mongordkit.Search.similarity.**SimSearchNaive**(mol (*rdmol object*), mol_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, index]*\n", - "\n", - "mongordkit.Search.similarity.**SimSearch**(mol (*rdmol object*), mol_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, index]*\n", - "\n", - "mongordkit.Search.similarity.**SimSearchAggregate**(mol (*rdmol object*), mol_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, index]*\n", - "\n", - "mongordkit.Search.similarity.**AddRandPermutations**(perm_collection (*MongoDB collection*), len=2048 (*int: length corresponding to length of fingerprint bit vectors*), num=100 (*int: number of permutations*)) --> None\n", - "\n", - "mongordkit.Search.similarity.**AddLocalityHashes**(mol_collection (*MongoDB collection*), perm_collection (*MongoDB collection*), nBuckets=25 (*int: number of hash buckets. The number of permutations (mod NBuckets) must be 0*)) --> None\n", - "\n", - "mongordkit.Search.similarity.**AddHashCollections**(db (*MongoDB database*), mol_collection (*MongoDB collection*)) --> None\n", - "\n", - "mongordkit.Search.similarity.**SimSearchLSH**(mol (*rdmol object*), db (*MongoDB database containing hash collections*), mol_collection (*MongoDB collection*), perm_collection (*MongoDB collection*), count_collection (*MongoDB collection*), threshold=0.8 (*Tanimoto threshold between 0 and 1, float*)) --> *list: results with format [tanimoto, index]*" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## `.substructure` Contents\n", - "\n", - "mongordkit.Search.substructure.**AddPatternFingerprints**(mol_collection (MongoDB collection), length=2048 (*int: length of Pattern fingerprint bit vector*)) --> None\n", - "\n", - "mongordkit.Search.similarity.**SubSearchNaive**(pattern (*rdmol object*), db, chirality=False (*boolean: include chirality in search or not*)) --> *list: results with format [smiles]*\n", - "\n", - "mongordkit.Search.similarity.**SubSearch**(pattern (*rdmol object*), db, chirality=False (*boolean: include chirality in search or not*)) --> *list: results with format [smiles]*" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "py37_rdkit_beta", - "language": "python", - "name": "py37_rdkit_beta" - }, - "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.7.7" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/docs/notebooks/Write and Registration Benchmarking.ipynb b/docs/notebooks/Write and Registration Benchmarking.ipynb index cc4b856..a849c11 100644 --- a/docs/notebooks/Write and Registration Benchmarking.ipynb +++ b/docs/notebooks/Write and Registration Benchmarking.ipynb @@ -149,6 +149,22 @@ "populating mongodb collection with compounds from SDF...\n", "4000 molecules successfully imported\n", "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n", + "4000 molecules successfully imported\n", + "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n", + "4000 molecules successfully imported\n", + "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n", + "4000 molecules successfully imported\n", + "0 duplicates skipped\n", + "populating mongodb collection with compounds from SDF...\n", + "4000 molecules successfully imported\n", + "0 duplicates skipped\n", + "testing 5000\n", + "populating mongodb collection with compounds from SDF...\n", + "5000 molecules successfully imported\n", + "0 duplicates skipped\n", "populating mongodb collection with compounds from SDF...\n" ] }