diff --git a/.gitignore b/.gitignore index 6996e69..5d2fa4a 100644 --- a/.gitignore +++ b/.gitignore @@ -138,6 +138,6 @@ tests/data/ # setuptools_scm version scikit_mol/_version.py -notebooks/sandbox.py .vscode notebooks/SLC6A4_active_excape_export.csv +sandbox/ diff --git a/CONTRIBUTION.md b/CONTRIBUTION.md index 3e39632..1b9aa61 100644 --- a/CONTRIBUTION.md +++ b/CONTRIBUTION.md @@ -5,7 +5,7 @@ Thanks for your interest in contributing to the project. Please read on in the s ## Slack channel We have a slack channel for communication, ask for an invite: esbenbjerrum+scikit_mol@gmail.com -It's not really active and Slack wan't to be paid now. Maybe we can use Discord instead. +It's not really active and Slack wan't to be paid now. Maybe we can use Discord instead as slack is now deleting old threads. ## Installation @@ -22,12 +22,13 @@ The projects transformers subclasses the BaseEstimator and Transformer mixin cla - The arguments accepted by **init** should all be keyword arguments with a default value. - Every keyword argument accepted by **init** should correspond to an attribute on the instance. -- - There should be no logic, not even input validation, and the parameters should not be changed. +- - There should be no logic, not even input validation, and the parameters should not be changed inside the **init** function. Scikit-learn classes depends on this in order to for e.g. the .get_params(), .set_params(), cloning abilities and representation rendering to work. +- With the new error handling, falsy objects need to return masked arrays or arrays with np.nan (for float dtype) ### Tips -- We have observed that some external tools used "exotic" types such at np.int64 when doing hyperparameter tuning. It is thus necessary to cast to standard types before making calls to rdkit functions. This behaviour is tested in the test_parameter_types test +- We have observed that some external tools used "exotic" types such at np.int64 when doing hyperparameter tuning. It is thus necessary do defensive programming to cast parameters to standard types before making calls to rdkit functions. This behaviour is tested in the test_parameter_types test - @property getters and setters can be used if additional logic are needed when setting the attributes from the keywords while at the same time adhering to the sklearn requisites. @@ -48,6 +49,7 @@ parameters and output of methods should preferably be using typehints ## Testing New transformer classes should be added to the pytest tests in the tests directory. A lot of tests are made general, and tests aspects of the transformers that are needed for sklearn compliance or other features. The transformer is then added to a fixture and can be added to the lists of transformer objects that are run by these test. Specific tests may also be necessary to set up. As exampe the assert_transformer_set_params needs a list of non-default parameters in order to set the set_params functionality of the object. +Scikit-Learn has a check_estimator that we should strive to get to work, some classes of scikit-mol currently does not pass all tests. ## Notebooks diff --git a/README.md b/README.md index d59717d..7c6255f 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,12 @@ There are a collection of notebooks in the notebooks directory which demonstrate We also put a software note on ChemRxiv. [https://doi.org/10.26434/chemrxiv-2023-fzqwd](https://doi.org/10.26434/chemrxiv-2023-fzqwd) -## Contributing +## Roadmap and Contributing + +_Help wanted!_ Are you a PhD student that want a "side-quest" to procrastinate your thesis writing or are you simply interested in computational chemistry, cheminformatics or simply with an interest in QSAR modelling, Python Programming open-source software? Do you want to learn more about machine learning with Scikit-Learn? Or do you use scikit-mol for your current work and would like to pay a little back to the project and see it improved as well? +With a little bit of help, this project can be improved much faster! Reach to me (Esben), for a discussion about how we can proceed. + +Currently we are working on fixing some deprecation warnings, its not the most exciting work, but it's important to maintain a little. Later on we need to go over the scikit-learn compatibility and update to some of their newer features on their estimator classes. We're also brewing on some feature enhancements and tests, such as new fingerprints and a more versatile standardizer. There are more information about how to contribute to the project in [CONTRIBUTION.md](https://github.com/EBjerrum/scikit-mol/CONTRIBUTION.md) diff --git a/notebooks/01_basic_usage.ipynb b/notebooks/01_basic_usage.ipynb index 4c62abe..e254859 100644 --- a/notebooks/01_basic_usage.ipynb +++ b/notebooks/01_basic_usage.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "8a3e313c", + "id": "aa079ac3", "metadata": {}, "source": [ "# Scikit-Mol\n", @@ -13,7 +13,7 @@ }, { "cell_type": "markdown", - "id": "7bcbed23", + "id": "76d24789", "metadata": {}, "source": [ "The transformer classes are easy to load, configure and use to process molecular information into vectorized formats using fingerprinters or collections of descriptors. For demonstration purposes, let's load a MorganTransformer, that can convert a list of RDKit molecular objects into a numpy array of morgan fingerprints. First create some molecules from SMILES strings." @@ -22,13 +22,13 @@ { "cell_type": "code", "execution_count": 1, - "id": "f8025236", + "id": "2c8cad03", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:09.802220Z", - "iopub.status.busy": "2024-04-12T12:10:09.802030Z", - "iopub.status.idle": "2024-04-12T12:10:09.808949Z", - "shell.execute_reply": "2024-04-12T12:10:09.808440Z" + "iopub.execute_input": "2024-11-24T09:27:16.292725Z", + "iopub.status.busy": "2024-11-24T09:27:16.292083Z", + "iopub.status.idle": "2024-11-24T09:27:16.306663Z", + "shell.execute_reply": "2024-11-24T09:27:16.304935Z" } }, "outputs": [], @@ -39,32 +39,34 @@ { "cell_type": "code", "execution_count": 2, - "id": "58a33f4d", + "id": "8d5b2333", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:09.811277Z", - "iopub.status.busy": "2024-04-12T12:10:09.811060Z", - "iopub.status.idle": "2024-04-12T12:10:09.936897Z", - "shell.execute_reply": "2024-04-12T12:10:09.936201Z" + "iopub.execute_input": "2024-11-24T09:27:16.313611Z", + "iopub.status.busy": "2024-11-24T09:27:16.313028Z", + "iopub.status.idle": "2024-11-24T09:27:16.510254Z", + "shell.execute_reply": "2024-11-24T09:27:16.509620Z" } }, "outputs": [], "source": [ "from rdkit import Chem\n", "\n", - "smiles_strings = [\"C12C([C@@H](OC(C=3C=CC(=CC3)F)C=4C=CC(=CC4)F)CC(N1CCCCCC5=CC=CC=C5)CC2)C(=O)OC\", \n", - "\"O(C1=NC=C2C(CN(CC2=C1)C)C3=CC=C(OC)C=C3)CCCN(CC)CC\",\n", - "\"O=S(=O)(N(CC=1C=CC2=CC=CC=C2C1)[C@@H]3CCNC3)C\",\n", - "\"C1(=C2C(CCCC2O)=NC=3C1=CC=CC3)NCC=4C=CC(=CC4)Cl\",\n", - "\"C1NC[C@@H](C1)[C@H](OC=2C=CC(=NC2C)OC)CC(C)C\",\n", - "\"FC(F)(F)C=1C(CN(C2CCNCC2)CC(CC)CC)=CC=CC1\"]\n", + "smiles_strings = [\n", + " \"C12C([C@@H](OC(C=3C=CC(=CC3)F)C=4C=CC(=CC4)F)CC(N1CCCCCC5=CC=CC=C5)CC2)C(=O)OC\",\n", + " \"O(C1=NC=C2C(CN(CC2=C1)C)C3=CC=C(OC)C=C3)CCCN(CC)CC\",\n", + " \"O=S(=O)(N(CC=1C=CC2=CC=CC=C2C1)[C@@H]3CCNC3)C\",\n", + " \"C1(=C2C(CCCC2O)=NC=3C1=CC=CC3)NCC=4C=CC(=CC4)Cl\",\n", + " \"C1NC[C@@H](C1)[C@H](OC=2C=CC(=NC2C)OC)CC(C)C\",\n", + " \"FC(F)(F)C=1C(CN(C2CCNCC2)CC(CC)CC)=CC=CC1\",\n", + "]\n", "\n", "mols = [Chem.MolFromSmiles(smiles) for smiles in smiles_strings]" ] }, { "cell_type": "markdown", - "id": "0228c878", + "id": "b9a588c7", "metadata": {}, "source": [ "Next we import the Morgan fingerprint transformer" @@ -73,13 +75,13 @@ { "cell_type": "code", "execution_count": 3, - "id": "cdb821a1", + "id": "0a625dda", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:09.939980Z", - "iopub.status.busy": "2024-04-12T12:10:09.939552Z", - "iopub.status.idle": "2024-04-12T12:10:10.505528Z", - "shell.execute_reply": "2024-04-12T12:10:10.504885Z" + "iopub.execute_input": "2024-11-24T09:27:16.513123Z", + "iopub.status.busy": "2024-11-24T09:27:16.512856Z", + "iopub.status.idle": "2024-11-24T09:27:17.089043Z", + "shell.execute_reply": "2024-11-24T09:27:17.088357Z" } }, "outputs": [ @@ -100,10 +102,10 @@ }, { "cell_type": "markdown", - "id": "e8ebae67", + "id": "355610d1", "metadata": {}, "source": [ - "It actually renders as a cute little interactive block in the Jupyter notebook and lists the options that are not the default values. If we print it, it also gives the information on the settings. \n", + "It actually renders as a cute little interactive block in the Jupyter notebook and lists the options that are not the default values. If we print it, it also gives the information on the settings.\n", "\n", "![An image of the interactive transformer widget](images/Transformer_Widget.jpg \"Transformer object rendering in Jupyter\")\n", "\n", @@ -113,20 +115,424 @@ { "cell_type": "code", "execution_count": 4, - "id": "c3a24f4e", + "id": "9a801d0f", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:10.508400Z", - "iopub.status.busy": "2024-04-12T12:10:10.508055Z", - "iopub.status.idle": "2024-04-12T12:10:10.514636Z", - "shell.execute_reply": "2024-04-12T12:10:10.514117Z" + "iopub.execute_input": "2024-11-24T09:27:17.091942Z", + "iopub.status.busy": "2024-11-24T09:27:17.091571Z", + "iopub.status.idle": "2024-11-24T09:27:17.098501Z", + "shell.execute_reply": "2024-11-24T09:27:17.097922Z" } }, "outputs": [ { "data": { "text/html": [ - "
MorganFingerprintTransformer(radius=3)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" + "
MorganFingerprintTransformer(radius=3)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" ], "text/plain": [ "MorganFingerprintTransformer(radius=3)" @@ -143,7 +549,7 @@ }, { "cell_type": "markdown", - "id": "c6e5de37", + "id": "556858b4", "metadata": {}, "source": [ "If we want to get all the settings explicitly, we can use the .get_params() method." @@ -152,22 +558,23 @@ { "cell_type": "code", "execution_count": 5, - "id": "112afff2", + "id": "500dc6f7", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:10.517110Z", - "iopub.status.busy": "2024-04-12T12:10:10.516867Z", - "iopub.status.idle": "2024-04-12T12:10:10.521207Z", - "shell.execute_reply": "2024-04-12T12:10:10.520689Z" + "iopub.execute_input": "2024-11-24T09:27:17.101153Z", + "iopub.status.busy": "2024-11-24T09:27:17.100929Z", + "iopub.status.idle": "2024-11-24T09:27:17.105319Z", + "shell.execute_reply": "2024-11-24T09:27:17.104586Z" } }, "outputs": [ { "data": { "text/plain": [ - "{'nBits': 2048,\n", + "{'fpSize': 2048,\n", " 'parallel': False,\n", " 'radius': 3,\n", + " 'safe_inference_mode': False,\n", " 'useBondTypes': True,\n", " 'useChirality': False,\n", " 'useCounts': False,\n", @@ -186,7 +593,7 @@ }, { "cell_type": "markdown", - "id": "45296da6", + "id": "d453fa33", "metadata": {}, "source": [ "The corresponding .set_params() method can be used to update the settings from options or from a dictionary (via ** unpackaging). The get_params and set_params methods are sometimes used by sklearn, as example hyperparameter search objects." @@ -195,13 +602,13 @@ { "cell_type": "code", "execution_count": 6, - "id": "4229d3d3", + "id": "3a27b07a", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:10.523546Z", - "iopub.status.busy": "2024-04-12T12:10:10.523347Z", - "iopub.status.idle": "2024-04-12T12:10:10.527067Z", - "shell.execute_reply": "2024-04-12T12:10:10.526450Z" + "iopub.execute_input": "2024-11-24T09:27:17.107710Z", + "iopub.status.busy": "2024-11-24T09:27:17.107495Z", + "iopub.status.idle": "2024-11-24T09:27:17.111268Z", + "shell.execute_reply": "2024-11-24T09:27:17.110754Z" } }, "outputs": [ @@ -209,20 +616,20 @@ "name": "stdout", "output_type": "stream", "text": [ - "MorganFingerprintTransformer(nBits=256)\n" + "MorganFingerprintTransformer(fpSize=256)\n" ] } ], "source": [ "parameters[\"radius\"] = 2\n", - "parameters[\"nBits\"] = 256\n", + "parameters[\"fpSize\"] = 256\n", "transformer.set_params(**parameters)\n", "print(transformer)" ] }, { "cell_type": "markdown", - "id": "1d38c224", + "id": "3dd372d3", "metadata": {}, "source": [ "Transformation is easy, simply use the .transform() method. For sklearn compatibility the scikit-learn transformers also have a .fit_transform() method, but it is usually not fitting anything." @@ -231,13 +638,13 @@ { "cell_type": "code", "execution_count": 7, - "id": "d2276e30", + "id": "0f141920", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:10.529451Z", - "iopub.status.busy": "2024-04-12T12:10:10.529229Z", - "iopub.status.idle": "2024-04-12T12:10:10.533310Z", - "shell.execute_reply": "2024-04-12T12:10:10.532819Z" + "iopub.execute_input": "2024-11-24T09:27:17.113572Z", + "iopub.status.busy": "2024-11-24T09:27:17.113344Z", + "iopub.status.idle": "2024-11-24T09:27:17.117356Z", + "shell.execute_reply": "2024-11-24T09:27:17.116845Z" } }, "outputs": [ @@ -245,7 +652,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "fps is a with shape (6, 256) and data type int8\n" + "fps is a with shape (6, 256) and data type uint8\n" ] } ], @@ -256,7 +663,7 @@ }, { "cell_type": "markdown", - "id": "666bf64b", + "id": "9cb75226", "metadata": {}, "source": [ "For sklearn compatibility, the transform function can be given a second parameter, usually representing the targets in the machine learning, but it is simply ignored most of the time" @@ -265,13 +672,13 @@ { "cell_type": "code", "execution_count": 8, - "id": "d3b01806", + "id": "481e527f", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:10.535668Z", - "iopub.status.busy": "2024-04-12T12:10:10.535455Z", - "iopub.status.idle": "2024-04-12T12:10:10.540535Z", - "shell.execute_reply": "2024-04-12T12:10:10.539917Z" + "iopub.execute_input": "2024-11-24T09:27:17.119855Z", + "iopub.status.busy": "2024-11-24T09:27:17.119584Z", + "iopub.status.idle": "2024-11-24T09:27:17.124520Z", + "shell.execute_reply": "2024-11-24T09:27:17.124025Z" } }, "outputs": [ @@ -283,7 +690,7 @@ " [1, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 1],\n", " [1, 1, 0, ..., 0, 0, 0],\n", - " [1, 1, 0, ..., 0, 0, 0]], dtype=int8)" + " [1, 1, 0, ..., 0, 0, 0]], dtype=uint8)" ] }, "execution_count": 8, @@ -298,7 +705,7 @@ }, { "cell_type": "markdown", - "id": "1e5c385f", + "id": "500cec09", "metadata": {}, "source": [ "Sometimes we may want to transform SMILES into molecules, and scikit-mol also has a transformer for that. It simply takes a list of SMILES and produces a list of RDKit molecules, this may come in handy when building pipelines for machine learning models, as we will demo in another notebook." @@ -307,13 +714,13 @@ { "cell_type": "code", "execution_count": 9, - "id": "26081bb2", + "id": "7773a5a0", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:10.542876Z", - "iopub.status.busy": "2024-04-12T12:10:10.542661Z", - "iopub.status.idle": "2024-04-12T12:10:10.546656Z", - "shell.execute_reply": "2024-04-12T12:10:10.546143Z" + "iopub.execute_input": "2024-11-24T09:27:17.126934Z", + "iopub.status.busy": "2024-11-24T09:27:17.126713Z", + "iopub.status.idle": "2024-11-24T09:27:17.131063Z", + "shell.execute_reply": "2024-11-24T09:27:17.130539Z" } }, "outputs": [ @@ -327,6 +734,7 @@ ], "source": [ "from scikit_mol.conversions import SmilesToMolTransformer\n", + "\n", "smi2mol = SmilesToMolTransformer()\n", "print(smi2mol)" ] @@ -334,13 +742,13 @@ { "cell_type": "code", "execution_count": 10, - "id": "6b0e5f4a", + "id": "fa484453", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:10.548964Z", - "iopub.status.busy": "2024-04-12T12:10:10.548714Z", - "iopub.status.idle": "2024-04-12T12:10:10.553416Z", - "shell.execute_reply": "2024-04-12T12:10:10.552805Z" + "iopub.execute_input": "2024-11-24T09:27:17.133328Z", + "iopub.status.busy": "2024-11-24T09:27:17.133133Z", + "iopub.status.idle": "2024-11-24T09:27:17.137378Z", + "shell.execute_reply": "2024-11-24T09:27:17.136857Z" } }, "outputs": [ @@ -348,12 +756,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "[[]\n", - " []\n", - " []\n", - " []\n", - " []\n", - " []]\n" + "[[]\n", + " []\n", + " []\n", + " []\n", + " []\n", + " []]\n" ] } ], diff --git a/notebooks/01_basic_usage.py b/notebooks/01_basic_usage.py index d6ca01c..65631a3 100644 --- a/notebooks/01_basic_usage.py +++ b/notebooks/01_basic_usage.py @@ -29,12 +29,14 @@ # %% from rdkit import Chem -smiles_strings = ["C12C([C@@H](OC(C=3C=CC(=CC3)F)C=4C=CC(=CC4)F)CC(N1CCCCCC5=CC=CC=C5)CC2)C(=O)OC", -"O(C1=NC=C2C(CN(CC2=C1)C)C3=CC=C(OC)C=C3)CCCN(CC)CC", -"O=S(=O)(N(CC=1C=CC2=CC=CC=C2C1)[C@@H]3CCNC3)C", -"C1(=C2C(CCCC2O)=NC=3C1=CC=CC3)NCC=4C=CC(=CC4)Cl", -"C1NC[C@@H](C1)[C@H](OC=2C=CC(=NC2C)OC)CC(C)C", -"FC(F)(F)C=1C(CN(C2CCNCC2)CC(CC)CC)=CC=CC1"] +smiles_strings = [ + "C12C([C@@H](OC(C=3C=CC(=CC3)F)C=4C=CC(=CC4)F)CC(N1CCCCCC5=CC=CC=C5)CC2)C(=O)OC", + "O(C1=NC=C2C(CN(CC2=C1)C)C3=CC=C(OC)C=C3)CCCN(CC)CC", + "O=S(=O)(N(CC=1C=CC2=CC=CC=C2C1)[C@@H]3CCNC3)C", + "C1(=C2C(CCCC2O)=NC=3C1=CC=CC3)NCC=4C=CC(=CC4)Cl", + "C1NC[C@@H](C1)[C@H](OC=2C=CC(=NC2C)OC)CC(C)C", + "FC(F)(F)C=1C(CN(C2CCNCC2)CC(CC)CC)=CC=CC1", +] mols = [Chem.MolFromSmiles(smiles) for smiles in smiles_strings] @@ -48,7 +50,7 @@ print(transformer) # %% [markdown] -# It actually renders as a cute little interactive block in the Jupyter notebook and lists the options that are not the default values. If we print it, it also gives the information on the settings. +# It actually renders as a cute little interactive block in the Jupyter notebook and lists the options that are not the default values. If we print it, it also gives the information on the settings. # # ![An image of the interactive transformer widget](images/Transformer_Widget.jpg "Transformer object rendering in Jupyter") # @@ -69,7 +71,7 @@ # %% parameters["radius"] = 2 -parameters["nBits"] = 256 +parameters["fpSize"] = 256 transformer.set_params(**parameters) print(transformer) @@ -92,6 +94,7 @@ # %% from scikit_mol.conversions import SmilesToMolTransformer + smi2mol = SmilesToMolTransformer() print(smi2mol) diff --git a/notebooks/02_descriptor_transformer.ipynb b/notebooks/02_descriptor_transformer.ipynb index 268e235..43b3075 100644 --- a/notebooks/02_descriptor_transformer.ipynb +++ b/notebooks/02_descriptor_transformer.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "80ef57b6", + "id": "e3cf34ca", "metadata": {}, "source": [ "# Desc2DTransformer: RDKit descriptors transformer\n", @@ -13,13 +13,13 @@ { "cell_type": "code", "execution_count": 1, - "id": "51b69a7e", + "id": "81745b1f", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:11.861457Z", - "iopub.status.busy": "2024-04-12T12:10:11.861246Z", - "iopub.status.idle": "2024-04-12T12:10:12.860086Z", - "shell.execute_reply": "2024-04-12T12:10:12.859376Z" + "iopub.execute_input": "2024-11-24T09:27:18.828147Z", + "iopub.status.busy": "2024-11-24T09:27:18.827339Z", + "iopub.status.idle": "2024-11-24T09:27:19.887178Z", + "shell.execute_reply": "2024-11-24T09:27:19.886482Z" }, "lines_to_next_cell": 0 }, @@ -33,7 +33,7 @@ }, { "cell_type": "markdown", - "id": "1e253d9e", + "id": "2293e9e6", "metadata": {}, "source": [ "After instantiation of the descriptor transformer, we can query which descriptors it found available in the RDKit framework." @@ -42,13 +42,13 @@ { "cell_type": "code", "execution_count": 2, - "id": "f1d8fc37", + "id": "dd9a2ad0", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:12.863149Z", - "iopub.status.busy": "2024-04-12T12:10:12.862837Z", - "iopub.status.idle": "2024-04-12T12:10:12.868668Z", - "shell.execute_reply": "2024-04-12T12:10:12.868151Z" + "iopub.execute_input": "2024-11-24T09:27:19.890505Z", + "iopub.status.busy": "2024-11-24T09:27:19.889986Z", + "iopub.status.idle": "2024-11-24T09:27:19.896597Z", + "shell.execute_reply": "2024-11-24T09:27:19.896028Z" } }, "outputs": [ @@ -56,7 +56,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "There are 209 available descriptors\n", + "There are 210 available descriptors\n", "The first five descriptor names: ['MaxAbsEStateIndex', 'MaxEStateIndex', 'MinAbsEStateIndex', 'MinEStateIndex', 'qed']\n" ] } @@ -70,7 +70,7 @@ }, { "cell_type": "markdown", - "id": "5bb186e5", + "id": "110c00c0", "metadata": {}, "source": [ "We can transform molecules to their descriptor profiles" @@ -79,19 +79,31 @@ { "cell_type": "code", "execution_count": 3, - "id": "702168a7", + "id": "4431a910", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:12.871338Z", - "iopub.status.busy": "2024-04-12T12:10:12.870842Z", - "iopub.status.idle": "2024-04-12T12:10:13.031911Z", - "shell.execute_reply": "2024-04-12T12:10:13.031258Z" + "iopub.execute_input": "2024-11-24T09:27:19.899516Z", + "iopub.status.busy": "2024-11-24T09:27:19.899244Z", + "iopub.status.idle": "2024-11-24T09:27:20.125197Z", + "shell.execute_reply": "2024-11-24T09:27:20.123935Z" } }, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:19] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:19] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:19] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:19] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:19] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:19] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAh8AAAGdCAYAAACyzRGfAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAABn50lEQVR4nO3deXwb9Zk/8M/M6PAV27lsx8QJIQ0knC0pDS60peASssDCkm2BZVugbNm2gS4JvbK/BlraEmB3gUJDaPtLA/21lDbsQgtb0gVDwlKSAAHKHRIIJODYIYdvW9d8f3/MoZnRyLakGWnkfN6vl7EtKaORZDSPnuf5PiMJIQSIiIiIikQu9Q4QERHRoYXBBxERERUVgw8iIiIqKgYfREREVFQMPoiIiKioGHwQERFRUTH4ICIioqJi8EFERERFFSr1DjipqoqOjg5MmDABkiSVeneIiIhoDIQQ6OvrQ3NzM2R55NxG4IKPjo4OtLS0lHo3iIiIKA+7d+/G9OnTR7xN4IKPCRMmANB2vra2tsR7Q0RERGPR29uLlpYW8zg+ksAFH0appba2lsEHERFRmRlLywQbTomIiKiocgo+UqkUVqxYgVmzZqGyshKzZ8/GD3/4Q1hPjCuEwHXXXYdp06ahsrISbW1t2L59u+c7TkREROUpp+Dj5ptvxurVq/HTn/4Ub7zxBm6++WbccsstuPPOO83b3HLLLbjjjjtw9913Y8uWLaiursbChQsxPDzs+c4TERFR+ZGENW0xinPOOQeNjY1Ys2aNednixYtRWVmJX//61xBCoLm5Gddeey2++c1vAgB6enrQ2NiIe+65BxdddNGo99Hb24u6ujr09PSw54OIiKhM5HL8zinz8clPfhLt7e146623AAB//etf8fTTT2PRokUAgJ07d6KzsxNtbW3mv6mrq8OCBQuwadOmXB8HERERjUM5rXb57ne/i97eXsydOxeKoiCVSuHHP/4xLrnkEgBAZ2cnAKCxsdH27xobG83rnGKxGGKxmPl7b29vTg+AiIiIyktOmY/f//73+M1vfoP77rsPL7zwAu699178+7//O+699968d2DlypWoq6szvzhgjIiIaHzLKfj41re+he9+97u46KKLcNxxx+GLX/wili5dipUrVwIAmpqaAABdXV22f9fV1WVe57R8+XL09PSYX7t3787ncRAREVGZ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sQWNjz32GGpra3H00UcX54HkqtQdr8Vw//33i2g0Ku655x7x+uuviyuvvFLU19fbOoOpdK699lqxYcMGsXPnTvGXv/xFtLW1iSlTpoi9e/cKIYT46le/KmbMmCGeeOIJ8fzzz4vW1lbR2tpa4r0+dPT19YkXX3xRvPjiiwKAuPXWW8WLL74o3nvvPSGEEDfddJOor68Xf/jDH8TLL78szjvvPDFr1iwxNDRkbuOss84SH/vYx8SWLVvE008/LebMmSMuvvjiUj2kcW2k16uvr09885vfFJs2bRI7d+4Ujz/+uDjxxBPFnDlzxPDwsLkNvl7F87WvfU3U1dWJDRs2iD179phfg4OD5m1Gew9MJpPi2GOPFWeeeaZ46aWXxPr168XUqVPF8uXLS/GQxuSQCD6EEOLOO+8UM2bMEJFIRHziE58QmzdvLvUuke7CCy8U06ZNE5FIRBx22GHiwgsvFDt27DCvHxoaEl//+tfFxIkTRVVVlfi7v/s7sWfPnhLu8aHlySefFAAyvi699FIhhLbcdsWKFaKxsVFEo1FxxhlniG3bttm2sX//fnHxxReLmpoaUVtbKy6//HLR19dXgkcz/o30eg0ODoozzzxTTJ06VYTDYTFz5kzxla98JeODGF+v4nF7rQCItWvXmrcZy3vgu+++KxYtWiQqKyvFlClTxLXXXisSiUSRH83YSUIIUexsCxERER26xn3PBxEREQULgw8iIiIqKgYfREREVFQMPoiIiKioGHwQERFRUTH4ICIioqJi8EFERERFxeCDiIiIiorBBxERERUVgw8iIiIqKgYfREREVFQMPoiIiKio/j+HZKvLSQUNfwAAAABJRU5ErkJggg==", + "image/png": "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", "text/plain": [ "
" ] @@ -110,7 +122,7 @@ }, { "cell_type": "markdown", - "id": "ea6f1325", + "id": "fdcb0698", "metadata": {}, "source": [ "If we only want some of them, this can be specified at object instantiation." @@ -119,13 +131,13 @@ { "cell_type": "code", "execution_count": 4, - "id": "ab72d398", + "id": "6caa9a54", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:13.034545Z", - "iopub.status.busy": "2024-04-12T12:10:13.034315Z", - "iopub.status.idle": "2024-04-12T12:10:13.038330Z", - "shell.execute_reply": "2024-04-12T12:10:13.037823Z" + "iopub.execute_input": "2024-11-24T09:27:20.131216Z", + "iopub.status.busy": "2024-11-24T09:27:20.130932Z", + "iopub.status.idle": "2024-11-24T09:27:20.135202Z", + "shell.execute_reply": "2024-11-24T09:27:20.134644Z" } }, "outputs": [ @@ -145,7 +157,7 @@ }, { "cell_type": "markdown", - "id": "c974320e", + "id": "52eaef77", "metadata": {}, "source": [ "If we want to update the selected descriptors on an already existing object, this can be done via the .set_params() method" @@ -154,13 +166,13 @@ { "cell_type": "code", "execution_count": 5, - "id": "4af5488d", + "id": "78fc5691", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:13.040697Z", - "iopub.status.busy": "2024-04-12T12:10:13.040482Z", - "iopub.status.idle": "2024-04-12T12:10:13.044948Z", - "shell.execute_reply": "2024-04-12T12:10:13.044445Z" + "iopub.execute_input": "2024-11-24T09:27:20.138477Z", + "iopub.status.busy": "2024-11-24T09:27:20.138022Z", + "iopub.status.idle": "2024-11-24T09:27:20.151081Z", + "shell.execute_reply": "2024-11-24T09:27:20.150278Z" } }, "outputs": [ @@ -180,7 +192,7 @@ { "cell_type": "code", "execution_count": null, - "id": "29367a7f", + "id": "4796a16e", "metadata": {}, "outputs": [], "source": [] diff --git a/notebooks/03_example_pipeline.ipynb b/notebooks/03_example_pipeline.ipynb index f2c9fbd..858eaf0 100644 --- a/notebooks/03_example_pipeline.ipynb +++ b/notebooks/03_example_pipeline.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "f3f842d3", + "id": "e7c43298", "metadata": {}, "source": [ "# Pipelining the scikit-mol transformer\n", @@ -15,13 +15,13 @@ { "cell_type": "code", "execution_count": 1, - "id": "b92c5a96", + "id": "79139b10", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:14.474481Z", - "iopub.status.busy": "2024-04-12T12:10:14.474256Z", - "iopub.status.idle": "2024-04-12T12:10:15.156429Z", - "shell.execute_reply": "2024-04-12T12:10:15.155756Z" + "iopub.execute_input": "2024-11-24T09:27:21.863626Z", + "iopub.status.busy": "2024-11-24T09:27:21.863272Z", + "iopub.status.idle": "2024-11-24T09:27:22.718519Z", + "shell.execute_reply": "2024-11-24T09:27:22.717789Z" } }, "outputs": [], @@ -39,13 +39,13 @@ { "cell_type": "code", "execution_count": 2, - "id": "0d79bc45", + "id": "17a9cdd7", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:15.159285Z", - "iopub.status.busy": "2024-04-12T12:10:15.158830Z", - "iopub.status.idle": "2024-04-12T12:10:15.164599Z", - "shell.execute_reply": "2024-04-12T12:10:15.163957Z" + "iopub.execute_input": "2024-11-24T09:27:22.722219Z", + "iopub.status.busy": "2024-11-24T09:27:22.721369Z", + "iopub.status.idle": "2024-11-24T09:27:22.727326Z", + "shell.execute_reply": "2024-11-24T09:27:22.726709Z" }, "lines_to_next_cell": 0 }, @@ -57,7 +57,7 @@ }, { "cell_type": "markdown", - "id": "3569affd", + "id": "066131b8", "metadata": {}, "source": [ "The dataset is a subset of the SLC6A4 actives from ExcapeDB. They are hand selected to give test set performance despite the small size, and are provided as example data only and should not be used to build serious QSAR models.\n", @@ -68,13 +68,13 @@ { "cell_type": "code", "execution_count": 3, - "id": "594f45ba", + "id": "a3ec0a23", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:15.167046Z", - "iopub.status.busy": "2024-04-12T12:10:15.166800Z", - "iopub.status.idle": "2024-04-12T12:10:15.202826Z", - "shell.execute_reply": "2024-04-12T12:10:15.202180Z" + "iopub.execute_input": "2024-11-24T09:27:22.729951Z", + "iopub.status.busy": "2024-11-24T09:27:22.729732Z", + "iopub.status.idle": "2024-11-24T09:27:22.769704Z", + "shell.execute_reply": "2024-11-24T09:27:22.768854Z" }, "lines_to_next_cell": 0 }, @@ -94,7 +94,7 @@ }, { "cell_type": "markdown", - "id": "04af16b2", + "id": "eccaf4af", "metadata": {}, "source": [ "Then, let's import some tools from scikit-learn and two transformers from scikit-mol" @@ -103,13 +103,13 @@ { "cell_type": "code", "execution_count": 4, - "id": "ed19f736", + "id": "4eb8f0fa", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:15.205344Z", - "iopub.status.busy": "2024-04-12T12:10:15.205135Z", - "iopub.status.idle": "2024-04-12T12:10:15.593454Z", - "shell.execute_reply": "2024-04-12T12:10:15.592778Z" + "iopub.execute_input": "2024-11-24T09:27:22.772861Z", + "iopub.status.busy": "2024-11-24T09:27:22.772534Z", + "iopub.status.idle": "2024-11-24T09:27:23.182612Z", + "shell.execute_reply": "2024-11-24T09:27:23.181966Z" }, "lines_to_next_cell": 0 }, @@ -125,13 +125,13 @@ { "cell_type": "code", "execution_count": 5, - "id": "c4a255f4", + "id": "99edec0f", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:15.596462Z", - "iopub.status.busy": "2024-04-12T12:10:15.595952Z", - "iopub.status.idle": "2024-04-12T12:10:15.601122Z", - "shell.execute_reply": "2024-04-12T12:10:15.600608Z" + "iopub.execute_input": "2024-11-24T09:27:23.185612Z", + "iopub.status.busy": "2024-11-24T09:27:23.185269Z", + "iopub.status.idle": "2024-11-24T09:27:23.190844Z", + "shell.execute_reply": "2024-11-24T09:27:23.190290Z" } }, "outputs": [], @@ -141,7 +141,7 @@ }, { "cell_type": "markdown", - "id": "a088665f", + "id": "b8380817", "metadata": {}, "source": [ "After a split into train and test, we'll build the first pipeline" @@ -150,13 +150,13 @@ { "cell_type": "code", "execution_count": 6, - "id": "0ddbf668", + "id": "a27d6ff9", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:15.603558Z", - "iopub.status.busy": "2024-04-12T12:10:15.603329Z", - "iopub.status.idle": "2024-04-12T12:10:15.608527Z", - "shell.execute_reply": "2024-04-12T12:10:15.608014Z" + "iopub.execute_input": "2024-11-24T09:27:23.193426Z", + "iopub.status.busy": "2024-11-24T09:27:23.193188Z", + "iopub.status.idle": "2024-11-24T09:27:23.198881Z", + "shell.execute_reply": "2024-11-24T09:27:23.198225Z" } }, "outputs": [ @@ -176,7 +176,7 @@ }, { "cell_type": "markdown", - "id": "004b0d25", + "id": "6c12f9a8", "metadata": {}, "source": [ "We can do the fit by simply providing the list of RDKit molecule objects" @@ -185,13 +185,13 @@ { "cell_type": "code", "execution_count": 7, - "id": "231d0534", + "id": "634ca919", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:15.610826Z", - "iopub.status.busy": "2024-04-12T12:10:15.610623Z", - "iopub.status.idle": "2024-04-12T12:10:15.735973Z", - "shell.execute_reply": "2024-04-12T12:10:15.735308Z" + "iopub.execute_input": "2024-11-24T09:27:23.201230Z", + "iopub.status.busy": "2024-11-24T09:27:23.201013Z", + "iopub.status.idle": "2024-11-24T09:27:23.265644Z", + "shell.execute_reply": "2024-11-24T09:27:23.264698Z" }, "lines_to_next_cell": 0 }, @@ -213,7 +213,7 @@ }, { "cell_type": "markdown", - "id": "55915786", + "id": "8440cc5a", "metadata": {}, "source": [ "Nevermind the performance, or the exact value of the prediction, this is for demonstration purpures. We can easily predict on lists of molecules" @@ -222,13 +222,13 @@ { "cell_type": "code", "execution_count": 8, - "id": "5d1e9220", + "id": "f4431aab", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:15.738365Z", - "iopub.status.busy": "2024-04-12T12:10:15.738132Z", - "iopub.status.idle": "2024-04-12T12:10:15.744818Z", - "shell.execute_reply": "2024-04-12T12:10:15.744279Z" + "iopub.execute_input": "2024-11-24T09:27:23.269015Z", + "iopub.status.busy": "2024-11-24T09:27:23.268218Z", + "iopub.status.idle": "2024-11-24T09:27:23.280889Z", + "shell.execute_reply": "2024-11-24T09:27:23.279967Z" } }, "outputs": [ @@ -249,7 +249,7 @@ }, { "cell_type": "markdown", - "id": "07cf53ea", + "id": "a60e242b", "metadata": {}, "source": [ "We can also expand the already fitted pipeline, how about creating a pipeline that can predict directly from SMILES? With scikit-mol that is easy!" @@ -258,13 +258,13 @@ { "cell_type": "code", "execution_count": 9, - "id": "eb8ce486", + "id": "a908097d", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:15.747499Z", - "iopub.status.busy": "2024-04-12T12:10:15.746917Z", - "iopub.status.idle": "2024-04-12T12:10:15.754613Z", - "shell.execute_reply": "2024-04-12T12:10:15.754088Z" + "iopub.execute_input": "2024-11-24T09:27:23.284650Z", + "iopub.status.busy": "2024-11-24T09:27:23.283862Z", + "iopub.status.idle": "2024-11-24T09:27:23.298454Z", + "shell.execute_reply": "2024-11-24T09:27:23.297546Z" } }, "outputs": [ @@ -288,13 +288,13 @@ { "cell_type": "code", "execution_count": 10, - "id": "1444b605", + "id": "0124653c", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:15.757246Z", - "iopub.status.busy": "2024-04-12T12:10:15.756914Z", - "iopub.status.idle": "2024-04-12T12:10:15.761416Z", - "shell.execute_reply": "2024-04-12T12:10:15.760858Z" + "iopub.execute_input": "2024-11-24T09:27:23.302185Z", + "iopub.status.busy": "2024-11-24T09:27:23.301318Z", + "iopub.status.idle": "2024-11-24T09:27:23.307070Z", + "shell.execute_reply": "2024-11-24T09:27:23.306539Z" } }, "outputs": [ @@ -315,7 +315,7 @@ }, { "cell_type": "markdown", - "id": "90d7817b", + "id": "069e2d01", "metadata": {}, "source": [ "From here, the pipelines could be pickled, and later loaded for easy prediction on RDKit molecule objects or SMILES in other scripts. The transformation with the MorganTransformer will be the same as during fitting, so no need to remember if radius 2 or 3 was used for this or that model, as it is already in the pipeline itself. If we need to see the parameters for a particular pipeline of model, we can always get the non default settings via print or all settings with .get_params()." @@ -324,13 +324,13 @@ { "cell_type": "code", "execution_count": 11, - "id": "1eacda8f", + "id": "63c8ef60", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:15.765023Z", - "iopub.status.busy": "2024-04-12T12:10:15.764682Z", - "iopub.status.idle": "2024-04-12T12:10:15.772249Z", - "shell.execute_reply": "2024-04-12T12:10:15.771692Z" + "iopub.execute_input": "2024-11-24T09:27:23.309849Z", + "iopub.status.busy": "2024-11-24T09:27:23.309649Z", + "iopub.status.idle": "2024-11-24T09:27:23.317613Z", + "shell.execute_reply": "2024-11-24T09:27:23.316837Z" }, "lines_to_next_cell": 2 }, @@ -348,15 +348,17 @@ " 'pipe': Pipeline(steps=[('mol_transformer', MorganFingerprintTransformer()),\n", " ('Regressor', Ridge())]),\n", " 'smiles_transformer__parallel': False,\n", + " 'smiles_transformer__safe_inference_mode': False,\n", " 'pipe__memory': None,\n", " 'pipe__steps': [('mol_transformer', MorganFingerprintTransformer()),\n", " ('Regressor', Ridge())],\n", " 'pipe__verbose': False,\n", " 'pipe__mol_transformer': MorganFingerprintTransformer(),\n", " 'pipe__Regressor': Ridge(),\n", - " 'pipe__mol_transformer__nBits': 2048,\n", + " 'pipe__mol_transformer__fpSize': 2048,\n", " 'pipe__mol_transformer__parallel': False,\n", " 'pipe__mol_transformer__radius': 2,\n", + " 'pipe__mol_transformer__safe_inference_mode': False,\n", " 'pipe__mol_transformer__useBondTypes': True,\n", " 'pipe__mol_transformer__useChirality': False,\n", " 'pipe__mol_transformer__useCounts': False,\n", diff --git a/notebooks/04_standardizer.ipynb b/notebooks/04_standardizer.ipynb index 1cf8175..ea59112 100644 --- a/notebooks/04_standardizer.ipynb +++ b/notebooks/04_standardizer.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "be682e9c", + "id": "095e3de9", "metadata": {}, "source": [ "# Molecule standardization\n", @@ -12,13 +12,13 @@ { "cell_type": "code", "execution_count": 1, - "id": "2aa91923", + "id": "d40bdabe", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:17.122184Z", - "iopub.status.busy": "2024-04-12T12:10:17.121928Z", - "iopub.status.idle": "2024-04-12T12:10:17.878455Z", - "shell.execute_reply": "2024-04-12T12:10:17.877770Z" + "iopub.execute_input": "2024-11-24T09:27:25.092168Z", + "iopub.status.busy": "2024-11-24T09:27:25.091775Z", + "iopub.status.idle": "2024-11-24T09:27:25.972589Z", + "shell.execute_reply": "2024-11-24T09:27:25.971827Z" } }, "outputs": [], @@ -33,7 +33,7 @@ }, { "cell_type": "markdown", - "id": "0fed8d0b", + "id": "1f739296", "metadata": {}, "source": [ "For demonstration let's create some molecules with different protonation states. The two first molecules are Benzoic acid and Sodium benzoate." @@ -42,20 +42,20 @@ { "cell_type": "code", "execution_count": 2, - "id": "934c031b", + "id": "5a45dfd5", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:17.881422Z", - "iopub.status.busy": "2024-04-12T12:10:17.881092Z", - "iopub.status.idle": "2024-04-12T12:10:17.889228Z", - "shell.execute_reply": "2024-04-12T12:10:17.888702Z" + "iopub.execute_input": "2024-11-24T09:27:25.975743Z", + "iopub.status.busy": "2024-11-24T09:27:25.975328Z", + "iopub.status.idle": "2024-11-24T09:27:25.984915Z", + "shell.execute_reply": "2024-11-24T09:27:25.984323Z" } }, "outputs": [ { "data": { "text/plain": [ - "array([], dtype=object)" + "array([], dtype=object)" ] }, "metadata": {}, @@ -64,7 +64,7 @@ { "data": { "text/plain": [ - "array([], dtype=object)" + "array([], dtype=object)" ] }, "metadata": {}, @@ -84,7 +84,7 @@ }, { "cell_type": "markdown", - "id": "e68b0eff", + "id": "1974e56a", "metadata": {}, "source": [ "We can simply use the transformer directly and get a list of standardized molecules" @@ -93,13 +93,13 @@ { "cell_type": "code", "execution_count": 3, - "id": "c18bbd3e", + "id": "d13141c6", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:17.891559Z", - "iopub.status.busy": "2024-04-12T12:10:17.891342Z", - "iopub.status.idle": "2024-04-12T12:10:17.906792Z", - "shell.execute_reply": "2024-04-12T12:10:17.906295Z" + "iopub.execute_input": "2024-11-24T09:27:25.987910Z", + "iopub.status.busy": "2024-11-24T09:27:25.987688Z", + "iopub.status.idle": "2024-11-24T09:27:26.003398Z", + "shell.execute_reply": "2024-11-24T09:27:26.002776Z" } }, "outputs": [ @@ -129,7 +129,7 @@ }, { "cell_type": "markdown", - "id": "da3fc3e2", + "id": "d268d331", "metadata": {}, "source": [ "Some of the molecules were desalted and neutralized.\n", @@ -140,13 +140,13 @@ { "cell_type": "code", "execution_count": 4, - "id": "d03be7dc", + "id": "a376a759", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:17.909344Z", - "iopub.status.busy": "2024-04-12T12:10:17.909132Z", - "iopub.status.idle": "2024-04-12T12:10:17.939678Z", - "shell.execute_reply": "2024-04-12T12:10:17.939104Z" + "iopub.execute_input": "2024-11-24T09:27:26.006132Z", + "iopub.status.busy": "2024-11-24T09:27:26.005882Z", + "iopub.status.idle": "2024-11-24T09:27:26.034347Z", + "shell.execute_reply": "2024-11-24T09:27:26.033821Z" }, "lines_to_next_cell": 2 }, @@ -158,30 +158,6 @@ "Predictions with no standardization: [0.51983795 0.61543701 2.31738354 3.01206795 3.44085399 4.37516731]\n", "Predictions with standardization: [0.51983795 0.51983795 2.06562022 3.01206795 3.95446692 4.92816899]\n" ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n" - ] } ], "source": [ @@ -202,7 +178,7 @@ }, { "cell_type": "markdown", - "id": "9cfab56c", + "id": "f0d071fb", "metadata": {}, "source": [ "As we can see, the predictions with the standardizer and without are different. The two first molecules were benzoic acid and sodium benzoate, which with the standardized pipeline is predicted as the same, but differently with the nonstandardized pipeline. Wheter we want to make the prediction on the parent compound, or predict the exact form, will of course depend on the use-case, but now there is at least a way to handle it easily in pipelined predictors.\n", @@ -215,13 +191,13 @@ { "cell_type": "code", "execution_count": 5, - "id": "e5f8495f", + "id": "50f71bca", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:17.942493Z", - "iopub.status.busy": "2024-04-12T12:10:17.942248Z", - "iopub.status.idle": "2024-04-12T12:10:17.961792Z", - "shell.execute_reply": "2024-04-12T12:10:17.961206Z" + "iopub.execute_input": "2024-11-24T09:27:26.037572Z", + "iopub.status.busy": "2024-11-24T09:27:26.036950Z", + "iopub.status.idle": "2024-11-24T09:27:26.056194Z", + "shell.execute_reply": "2024-11-24T09:27:26.055013Z" } }, "outputs": [ @@ -232,30 +208,6 @@ "Predictions with no standardization: [0.07445775 0.96053374 2.05993278 3.00857908 3.96365443 4.93284221]\n", "Predictions with standardization: [0.07445775 0.07445775 2.32132164 3.00857908 2.68502208 4.30275549]\n" ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n", - "[19:07:06] DEPRECATION WARNING: please use MorganGenerator\n" - ] } ], "source": [ diff --git a/notebooks/05_smiles_sanitaztion.ipynb b/notebooks/05_smiles_sanitaztion.ipynb index 70eed7e..d59c830 100644 --- a/notebooks/05_smiles_sanitaztion.ipynb +++ b/notebooks/05_smiles_sanitaztion.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "b6fe4dbd", + "id": "9b787560", "metadata": {}, "source": [ "# SMILES sanitation\n", @@ -12,13 +12,13 @@ { "cell_type": "code", "execution_count": 1, - "id": "c46f479f", + "id": "612aa974", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:19.504461Z", - "iopub.status.busy": "2024-04-12T12:10:19.504268Z", - "iopub.status.idle": "2024-04-12T12:10:19.893131Z", - "shell.execute_reply": "2024-04-12T12:10:19.892459Z" + "iopub.execute_input": "2024-11-24T09:27:27.545695Z", + "iopub.status.busy": "2024-11-24T09:27:27.545293Z", + "iopub.status.idle": "2024-11-24T09:27:28.079174Z", + "shell.execute_reply": "2024-11-24T09:27:28.078490Z" } }, "outputs": [], @@ -33,7 +33,7 @@ }, { "cell_type": "markdown", - "id": "5db46e76", + "id": "0f957a69", "metadata": {}, "source": [ "Now, this example dataset contain all sanitizable SMILES, so for demonstration purposes, we will corrupt one of them" @@ -42,13 +42,13 @@ { "cell_type": "code", "execution_count": 2, - "id": "a7bc5ff6", + "id": "b09cfd6b", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:19.896100Z", - "iopub.status.busy": "2024-04-12T12:10:19.895854Z", - "iopub.status.idle": "2024-04-12T12:10:19.899441Z", - "shell.execute_reply": "2024-04-12T12:10:19.898958Z" + "iopub.execute_input": "2024-11-24T09:27:28.082222Z", + "iopub.status.busy": "2024-11-24T09:27:28.081921Z", + "iopub.status.idle": "2024-11-24T09:27:28.086003Z", + "shell.execute_reply": "2024-11-24T09:27:28.085450Z" } }, "outputs": [], @@ -59,13 +59,13 @@ { "cell_type": "code", "execution_count": 3, - "id": "a792f370", + "id": "e20fb5cc", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:19.901832Z", - "iopub.status.busy": "2024-04-12T12:10:19.901618Z", - "iopub.status.idle": "2024-04-12T12:10:19.939335Z", - "shell.execute_reply": "2024-04-12T12:10:19.938810Z" + "iopub.execute_input": "2024-11-24T09:27:28.088449Z", + "iopub.status.busy": "2024-11-24T09:27:28.088211Z", + "iopub.status.idle": "2024-11-24T09:27:28.130818Z", + "shell.execute_reply": "2024-11-24T09:27:28.130102Z" }, "lines_to_next_cell": 2 }, @@ -81,7 +81,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "[14:10:19] Explicit valence for atom # 1 N, 4, is greater than permitted\n" + "[10:27:28] Explicit valence for atom # 1 N, 4, is greater than permitted\n" ] } ], @@ -93,7 +93,7 @@ }, { "cell_type": "markdown", - "id": "54341ece", + "id": "f8dccd93", "metadata": {}, "source": [ "If we use these SMILES for the scikit-learn pipeline, we would face an error, so we need to check and clean the dataset first. The CheckSmilesSanitation can help us with that." @@ -102,13 +102,13 @@ { "cell_type": "code", "execution_count": 4, - "id": "849b643f", + "id": "3dbd50b3", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:19.942039Z", - "iopub.status.busy": "2024-04-12T12:10:19.941833Z", - "iopub.status.idle": "2024-04-12T12:10:19.981190Z", - "shell.execute_reply": "2024-04-12T12:10:19.980569Z" + "iopub.execute_input": "2024-11-24T09:27:28.133745Z", + "iopub.status.busy": "2024-11-24T09:27:28.133507Z", + "iopub.status.idle": "2024-11-24T09:27:28.508377Z", + "shell.execute_reply": "2024-11-24T09:27:28.507130Z" } }, "outputs": [ @@ -123,7 +123,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "[14:10:19] Explicit valence for atom # 1 N, 4, is greater than permitted\n" + "[10:27:28] Explicit valence for atom # 1 N, 4, is greater than permitted\n" ] } ], @@ -136,7 +136,7 @@ }, { "cell_type": "markdown", - "id": "5e410e4c", + "id": "c888d7da", "metadata": {}, "source": [ "Now the smiles_list_valid should be all valid and the y_values filtered as well. Errors are returned, but also accesible after the call to .sanitize() in the .errors property" @@ -145,13 +145,13 @@ { "cell_type": "code", "execution_count": 5, - "id": "2145530c", + "id": "5af5ea3d", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:19.983672Z", - "iopub.status.busy": "2024-04-12T12:10:19.983440Z", - "iopub.status.idle": "2024-04-12T12:10:19.995617Z", - "shell.execute_reply": "2024-04-12T12:10:19.995060Z" + "iopub.execute_input": "2024-11-24T09:27:28.511261Z", + "iopub.status.busy": "2024-11-24T09:27:28.510945Z", + "iopub.status.idle": "2024-11-24T09:27:28.522024Z", + "shell.execute_reply": "2024-11-24T09:27:28.521232Z" } }, "outputs": [ @@ -206,7 +206,7 @@ }, { "cell_type": "markdown", - "id": "c9906a45", + "id": "c2ce2677", "metadata": {}, "source": [ "The checker can also be used only on X" @@ -215,13 +215,13 @@ { "cell_type": "code", "execution_count": 6, - "id": "d5fd425e", + "id": "84db07cc", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:19.998113Z", - "iopub.status.busy": "2024-04-12T12:10:19.997903Z", - "iopub.status.idle": "2024-04-12T12:10:20.040005Z", - "shell.execute_reply": "2024-04-12T12:10:20.039381Z" + "iopub.execute_input": "2024-11-24T09:27:28.524982Z", + "iopub.status.busy": "2024-11-24T09:27:28.524717Z", + "iopub.status.idle": "2024-11-24T09:27:28.569119Z", + "shell.execute_reply": "2024-11-24T09:27:28.568473Z" } }, "outputs": [ @@ -236,7 +236,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "[14:10:19] Explicit valence for atom # 1 N, 4, is greater than permitted\n" + "[10:27:28] Explicit valence for atom # 1 N, 4, is greater than permitted\n" ] }, { diff --git a/notebooks/06_hyperparameter_tuning.ipynb b/notebooks/06_hyperparameter_tuning.ipynb index d15d9fe..9afcc21 100644 --- a/notebooks/06_hyperparameter_tuning.ipynb +++ b/notebooks/06_hyperparameter_tuning.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "9d600dd1", + "id": "f0b0cc54", "metadata": {}, "source": [ "# Full example: Hyperparameter tuning\n", @@ -13,13 +13,13 @@ { "cell_type": "code", "execution_count": 1, - "id": "7df4793c", + "id": "51aa3d62", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:21.479028Z", - "iopub.status.busy": "2024-04-12T12:10:21.478831Z", - "iopub.status.idle": "2024-04-12T12:10:22.543557Z", - "shell.execute_reply": "2024-04-12T12:10:22.542929Z" + "iopub.execute_input": "2024-11-24T09:27:30.230310Z", + "iopub.status.busy": "2024-11-24T09:27:30.230076Z", + "iopub.status.idle": "2024-11-24T09:27:31.452867Z", + "shell.execute_reply": "2024-11-24T09:27:31.452127Z" } }, "outputs": [], @@ -41,7 +41,7 @@ }, { "cell_type": "markdown", - "id": "8acee1c3", + "id": "e07990d0", "metadata": {}, "source": [ "We will need some data. There is a dataset with the SLC6A4 active compounds from ExcapeDB on Zenodo. The scikit-mol project uses a subset of this for testing, and the samples there has been specially selected to give good results in testing (it should therefore be used for any production modelling). If full_set is false, the fast subset will be used, and otherwise the full dataset will be downloaded if needed." @@ -50,13 +50,13 @@ { "cell_type": "code", "execution_count": 2, - "id": "45a8ebf1", + "id": "adbc1868", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:22.546506Z", - "iopub.status.busy": "2024-04-12T12:10:22.546207Z", - "iopub.status.idle": "2024-04-12T12:10:22.550011Z", - "shell.execute_reply": "2024-04-12T12:10:22.549526Z" + "iopub.execute_input": "2024-11-24T09:27:31.455770Z", + "iopub.status.busy": "2024-11-24T09:27:31.455436Z", + "iopub.status.idle": "2024-11-24T09:27:31.459245Z", + "shell.execute_reply": "2024-11-24T09:27:31.458654Z" } }, "outputs": [], @@ -67,15 +67,16 @@ " csv_file = \"SLC6A4_active_excape_export.csv\"\n", " if not os.path.exists(csv_file):\n", " import urllib.request\n", + "\n", " url = \"https://ndownloader.figshare.com/files/25747817\"\n", " urllib.request.urlretrieve(url, csv_file)\n", "else:\n", - " csv_file = '../tests/data/SLC6A4_active_excapedb_subset.csv'" + " csv_file = \"../tests/data/SLC6A4_active_excapedb_subset.csv\"" ] }, { "cell_type": "markdown", - "id": "f3c108d4", + "id": "d2ce3c7f", "metadata": {}, "source": [ "The CSV data is loaded into a Pandas dataframe and the PandasTools utility from RDKit is used to add a column with RDKit molecules" @@ -84,13 +85,13 @@ { "cell_type": "code", "execution_count": 3, - "id": "08c233a7", + "id": "9a283f12", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:22.552652Z", - "iopub.status.busy": "2024-04-12T12:10:22.552186Z", - "iopub.status.idle": "2024-04-12T12:10:22.591597Z", - "shell.execute_reply": "2024-04-12T12:10:22.591017Z" + "iopub.execute_input": "2024-11-24T09:27:31.461622Z", + "iopub.status.busy": "2024-11-24T09:27:31.461384Z", + "iopub.status.idle": "2024-11-24T09:27:31.500359Z", + "shell.execute_reply": "2024-11-24T09:27:31.499764Z" } }, "outputs": [ @@ -112,7 +113,7 @@ }, { "cell_type": "markdown", - "id": "e1828bee", + "id": "e245e989", "metadata": {}, "source": [ "We use the train_test_split to, well, split the dataframe's molecule columns and pXC50 column into lists for train and testing" @@ -121,25 +122,27 @@ { "cell_type": "code", "execution_count": 4, - "id": "5363d05a", + "id": "303b83de", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:22.594077Z", - "iopub.status.busy": "2024-04-12T12:10:22.593866Z", - "iopub.status.idle": "2024-04-12T12:10:22.598774Z", - "shell.execute_reply": "2024-04-12T12:10:22.598212Z" + "iopub.execute_input": "2024-11-24T09:27:31.502982Z", + "iopub.status.busy": "2024-11-24T09:27:31.502779Z", + "iopub.status.idle": "2024-11-24T09:27:31.507447Z", + "shell.execute_reply": "2024-11-24T09:27:31.506962Z" }, "lines_to_next_cell": 2 }, "outputs": [], "source": [ "\n", - "mol_list_train, mol_list_test, y_train, y_test = train_test_split(data.ROMol, data.pXC50, random_state=42)" + "mol_list_train, mol_list_test, y_train, y_test = train_test_split(\n", + " data.ROMol, data.pXC50, random_state=42\n", + ")" ] }, { "cell_type": "markdown", - "id": "bf9e8c8d", + "id": "56247c3b", "metadata": {}, "source": [ "We will standardize the molecules before modelling. This is best done before the hyperparameter optimizatiion of the featurization with the scikit-mol transformer and regression modelling, as the standardization is otherwise done for every loop in the hyperparameter optimization, which will make it take longer time." @@ -148,18 +151,18 @@ { "cell_type": "code", "execution_count": 5, - "id": "885daf12", + "id": "1383d0fc", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:22.601148Z", - "iopub.status.busy": "2024-04-12T12:10:22.600938Z", - "iopub.status.idle": "2024-04-12T12:10:22.967869Z", - "shell.execute_reply": "2024-04-12T12:10:22.967178Z" + "iopub.execute_input": "2024-11-24T09:27:31.509953Z", + "iopub.status.busy": "2024-11-24T09:27:31.509731Z", + "iopub.status.idle": "2024-11-24T09:27:31.830576Z", + "shell.execute_reply": "2024-11-24T09:27:31.829874Z" } }, "outputs": [], "source": [ - "# Probably the recommended way would be to prestandardize the data if there's no changes to the transformer, \n", + "# Probably the recommended way would be to prestandardize the data if there's no changes to the transformer,\n", "# and then add the standardizer in the inference pipeline.\n", "\n", "from scikit_mol.standardizer import Standardizer\n", @@ -170,7 +173,7 @@ }, { "cell_type": "markdown", - "id": "a81ae4c4", + "id": "0775d395", "metadata": {}, "source": [ "A simple pipeline with a MorganTransformer and a Ridge() regression for demonstration." @@ -179,14 +182,15 @@ { "cell_type": "code", "execution_count": 6, - "id": "8fd14250", + "id": "51c74711", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:22.970766Z", - "iopub.status.busy": "2024-04-12T12:10:22.970539Z", - "iopub.status.idle": "2024-04-12T12:10:22.973715Z", - "shell.execute_reply": "2024-04-12T12:10:22.973234Z" - } + "iopub.execute_input": "2024-11-24T09:27:31.833379Z", + "iopub.status.busy": "2024-11-24T09:27:31.833155Z", + "iopub.status.idle": "2024-11-24T09:27:31.836541Z", + "shell.execute_reply": "2024-11-24T09:27:31.835939Z" + }, + "lines_to_next_cell": 2 }, "outputs": [], "source": [ @@ -194,13 +198,12 @@ "moltransformer = MorganFingerprintTransformer()\n", "regressor = Ridge()\n", "\n", - "optimization_pipe = make_pipeline(moltransformer, regressor)\n", - "\n" + "optimization_pipe = make_pipeline(moltransformer, regressor)" ] }, { "cell_type": "markdown", - "id": "ad2752d0", + "id": "8221a682", "metadata": {}, "source": [ "For hyperparameter optimization we import the RandomizedSearchCV class from Scikit-Learn. It will try different random combinations of settings and use internal cross-validation to find the best model. In the end, it will fit the best found parameters on the full set. We also import loguniform, to get a better sampling of some of the parameters." @@ -209,26 +212,27 @@ { "cell_type": "code", "execution_count": 7, - "id": "fa082078", + "id": "4c6b833f", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:22.976061Z", - "iopub.status.busy": "2024-04-12T12:10:22.975846Z", - "iopub.status.idle": "2024-04-12T12:10:22.978721Z", - "shell.execute_reply": "2024-04-12T12:10:22.978155Z" + "iopub.execute_input": "2024-11-24T09:27:31.838854Z", + "iopub.status.busy": "2024-11-24T09:27:31.838668Z", + "iopub.status.idle": "2024-11-24T09:27:31.841636Z", + "shell.execute_reply": "2024-11-24T09:27:31.841130Z" }, "title": "Now hyperparameter tuning" }, "outputs": [], "source": [ "from sklearn.model_selection import RandomizedSearchCV\n", - "#from sklearn.utils.fixes import loguniform\n", + "\n", + "# from sklearn.utils.fixes import loguniform\n", "from scipy.stats import loguniform" ] }, { "cell_type": "markdown", - "id": "fa2a316a", + "id": "6b9d4576", "metadata": {}, "source": [ "With the pipelines, getting the names of the parameters to tune is a bit more tricky, as they are concatenations of the name of the step and the parameter with double underscores in between. We can get the available parameters from the pipeline with the get_params() method, and select the parameters we want to change from there." @@ -237,13 +241,13 @@ { "cell_type": "code", "execution_count": 8, - "id": "046e24d3", + "id": "0af1003b", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:22.981002Z", - "iopub.status.busy": "2024-04-12T12:10:22.980797Z", - "iopub.status.idle": "2024-04-12T12:10:22.986820Z", - "shell.execute_reply": "2024-04-12T12:10:22.986344Z" + "iopub.execute_input": "2024-11-24T09:27:31.843922Z", + "iopub.status.busy": "2024-11-24T09:27:31.843728Z", + "iopub.status.idle": "2024-11-24T09:27:31.849777Z", + "shell.execute_reply": "2024-11-24T09:27:31.849273Z" }, "title": "Which keys do we have?" }, @@ -251,7 +255,7 @@ { "data": { "text/plain": [ - "dict_keys(['memory', 'steps', 'verbose', 'morganfingerprinttransformer', 'ridge', 'morganfingerprinttransformer__nBits', 'morganfingerprinttransformer__parallel', 'morganfingerprinttransformer__radius', 'morganfingerprinttransformer__useBondTypes', 'morganfingerprinttransformer__useChirality', 'morganfingerprinttransformer__useCounts', 'morganfingerprinttransformer__useFeatures', 'ridge__alpha', 'ridge__copy_X', 'ridge__fit_intercept', 'ridge__max_iter', 'ridge__positive', 'ridge__random_state', 'ridge__solver', 'ridge__tol'])" + "dict_keys(['memory', 'steps', 'verbose', 'morganfingerprinttransformer', 'ridge', 'morganfingerprinttransformer__fpSize', 'morganfingerprinttransformer__parallel', 'morganfingerprinttransformer__radius', 'morganfingerprinttransformer__safe_inference_mode', 'morganfingerprinttransformer__useBondTypes', 'morganfingerprinttransformer__useChirality', 'morganfingerprinttransformer__useCounts', 'morganfingerprinttransformer__useFeatures', 'ridge__alpha', 'ridge__copy_X', 'ridge__fit_intercept', 'ridge__max_iter', 'ridge__positive', 'ridge__random_state', 'ridge__solver', 'ridge__tol'])" ] }, "execution_count": 8, @@ -266,7 +270,7 @@ }, { "cell_type": "markdown", - "id": "cd7c2297", + "id": "cb0db6a5", "metadata": {}, "source": [ "We will tune the regularization strength of the Ridge regressor, and try out different parameters for the Morgan fingerprint, namely the number of bits, the radius of the fingerprint, wheter to use counts or bits and features." @@ -275,30 +279,33 @@ { "cell_type": "code", "execution_count": 9, - "id": "cf2c45d7", + "id": "c2d541b3", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:22.989460Z", - "iopub.status.busy": "2024-04-12T12:10:22.988970Z", - "iopub.status.idle": "2024-04-12T12:10:22.993117Z", - "shell.execute_reply": "2024-04-12T12:10:22.992622Z" - }, - "lines_to_next_cell": 1 + "iopub.execute_input": "2024-11-24T09:27:31.852166Z", + "iopub.status.busy": "2024-11-24T09:27:31.851946Z", + "iopub.status.idle": "2024-11-24T09:27:31.856126Z", + "shell.execute_reply": "2024-11-24T09:27:31.855622Z" + } }, "outputs": [], "source": [ "\n", - "param_dist = {'ridge__alpha': loguniform(1e-2, 1e3),\n", - " \"morganfingerprinttransformer__nBits\": [256,512,1024,2048,4096],\n", - " 'morganfingerprinttransformer__radius':[1,2,3,4],\n", - " 'morganfingerprinttransformer__useCounts': [True,False],\n", - " 'morganfingerprinttransformer__useFeatures':[True,False]}" + "param_dist = {\n", + " \"ridge__alpha\": loguniform(1e-2, 1e3),\n", + " \"morganfingerprinttransformer__fpSize\": [256, 512, 1024, 2048, 4096],\n", + " \"morganfingerprinttransformer__radius\": [1, 2, 3, 4],\n", + " \"morganfingerprinttransformer__useCounts\": [True, False],\n", + " \"morganfingerprinttransformer__useFeatures\": [True, False],\n", + "}" ] }, { "cell_type": "markdown", - "id": "d61fc18c", - "metadata": {}, + "id": "2157d154", + "metadata": { + "lines_to_next_cell": 2 + }, "source": [ "The report function was taken from [this example](https://scikit-learn.org/stable/auto_examples/model_selection/plot_randomized_search.html#sphx-glr-auto-examples-model-selection-plot-randomized-search-py) from the scikit learn documentation." ] @@ -306,13 +313,13 @@ { "cell_type": "code", "execution_count": 10, - "id": "fbb2cacd", + "id": "f2c91783", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:22.995477Z", - "iopub.status.busy": "2024-04-12T12:10:22.995281Z", - "iopub.status.idle": "2024-04-12T12:10:22.999317Z", - "shell.execute_reply": "2024-04-12T12:10:22.998769Z" + "iopub.execute_input": "2024-11-24T09:27:31.858429Z", + "iopub.status.busy": "2024-11-24T09:27:31.858216Z", + "iopub.status.idle": "2024-11-24T09:27:31.862461Z", + "shell.execute_reply": "2024-11-24T09:27:31.861795Z" }, "title": "From https://scikit-learn.org/stable/auto_examples/model_selection/plot_randomized_search.html#sphx-glr-auto-examples-model-selection-plot-randomized-search-py" }, @@ -336,7 +343,7 @@ }, { "cell_type": "markdown", - "id": "ad49376f", + "id": "469691f4", "metadata": {}, "source": [ "We will do 25 tries of random parameter sets, and see what comes out as the best one. If you are using the small example dataset, this should take some second, but may take some minutes with the full set." @@ -345,13 +352,13 @@ { "cell_type": "code", "execution_count": 11, - "id": "bc66efa3", + "id": "79a70a0f", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:23.001598Z", - "iopub.status.busy": "2024-04-12T12:10:23.001400Z", - "iopub.status.idle": "2024-04-12T12:10:27.149245Z", - "shell.execute_reply": "2024-04-12T12:10:27.148640Z" + "iopub.execute_input": "2024-11-24T09:27:31.864936Z", + "iopub.status.busy": "2024-11-24T09:27:31.864708Z", + "iopub.status.idle": "2024-11-24T09:27:36.221386Z", + "shell.execute_reply": "2024-11-24T09:27:36.220369Z" } }, "outputs": [ @@ -359,7 +366,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Runtime: 4.14 for 25 iterations)\n" + "Runtime: 4.35 for 25 iterations)\n" ] } ], @@ -372,19 +379,19 @@ "random_search.fit(mol_list_std_train, y_train.values)\n", "t1 = time()\n", "\n", - "print(f'Runtime: {t1-t0:0.2F} for {n_iter_search} iterations)')" + "print(f\"Runtime: {t1-t0:0.2F} for {n_iter_search} iterations)\")" ] }, { "cell_type": "code", "execution_count": 12, - "id": "b2b3d623", + "id": "b6160cb3", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:27.153307Z", - "iopub.status.busy": "2024-04-12T12:10:27.152284Z", - "iopub.status.idle": "2024-04-12T12:10:27.157929Z", - "shell.execute_reply": "2024-04-12T12:10:27.157394Z" + "iopub.execute_input": "2024-11-24T09:27:36.224876Z", + "iopub.status.busy": "2024-11-24T09:27:36.224667Z", + "iopub.status.idle": "2024-11-24T09:27:36.232647Z", + "shell.execute_reply": "2024-11-24T09:27:36.231571Z" }, "lines_to_next_cell": 0 }, @@ -394,16 +401,16 @@ "output_type": "stream", "text": [ "Model with rank: 1\n", - "Mean validation score: 0.539 (std: 0.090)\n", - "Parameters: {'morganfingerprinttransformer__nBits': 2048, 'morganfingerprinttransformer__radius': 1, 'morganfingerprinttransformer__useCounts': False, 'morganfingerprinttransformer__useFeatures': False, 'ridge__alpha': 10.016632822744322}\n", + "Mean validation score: 0.563 (std: 0.115)\n", + "Parameters: {'morganfingerprinttransformer__fpSize': 1024, 'morganfingerprinttransformer__radius': 2, 'morganfingerprinttransformer__useCounts': False, 'morganfingerprinttransformer__useFeatures': False, 'ridge__alpha': 6.855244257973563}\n", "\n", "Model with rank: 2\n", - "Mean validation score: 0.534 (std: 0.145)\n", - "Parameters: {'morganfingerprinttransformer__nBits': 2048, 'morganfingerprinttransformer__radius': 3, 'morganfingerprinttransformer__useCounts': False, 'morganfingerprinttransformer__useFeatures': False, 'ridge__alpha': 0.7814453905088184}\n", + "Mean validation score: 0.527 (std: 0.086)\n", + "Parameters: {'morganfingerprinttransformer__fpSize': 512, 'morganfingerprinttransformer__radius': 2, 'morganfingerprinttransformer__useCounts': False, 'morganfingerprinttransformer__useFeatures': False, 'ridge__alpha': 13.611425709525077}\n", "\n", "Model with rank: 3\n", - "Mean validation score: 0.526 (std: 0.090)\n", - "Parameters: {'morganfingerprinttransformer__nBits': 4096, 'morganfingerprinttransformer__radius': 1, 'morganfingerprinttransformer__useCounts': False, 'morganfingerprinttransformer__useFeatures': False, 'ridge__alpha': 11.295262712617353}\n", + "Mean validation score: 0.466 (std: 0.149)\n", + "Parameters: {'morganfingerprinttransformer__fpSize': 2048, 'morganfingerprinttransformer__radius': 4, 'morganfingerprinttransformer__useCounts': False, 'morganfingerprinttransformer__useFeatures': True, 'ridge__alpha': 1.383163758398022}\n", "\n" ] } @@ -414,7 +421,7 @@ }, { "cell_type": "markdown", - "id": "219e3e32", + "id": "9a2ea219", "metadata": {}, "source": [ "It can be interesting to see what combinations of hyperparameters gave good results for the cross-validation. Usually the number of bits are in the high end and radius is 2 to 4. But this can vary a bit, as we do a small number of tries for this demo. More extended search with more iterations could maybe find even better and more consistent. solutions" @@ -422,7 +429,7 @@ }, { "cell_type": "markdown", - "id": "630772af", + "id": "6cf91582", "metadata": {}, "source": [ "Let's see if standardization had any influence on this dataset. We build an inference pipeline that includes the standardization object and the best estimator, and run the best estimator directly on the list of test molecules" @@ -431,13 +438,13 @@ { "cell_type": "code", "execution_count": 13, - "id": "cb369a0e", + "id": "4daaf106", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:27.161728Z", - "iopub.status.busy": "2024-04-12T12:10:27.160746Z", - "iopub.status.idle": "2024-04-12T12:10:27.316434Z", - "shell.execute_reply": "2024-04-12T12:10:27.315830Z" + "iopub.execute_input": "2024-11-24T09:27:36.236805Z", + "iopub.status.busy": "2024-11-24T09:27:36.235794Z", + "iopub.status.idle": "2024-11-24T09:27:36.394539Z", + "shell.execute_reply": "2024-11-24T09:27:36.393590Z" } }, "outputs": [ @@ -445,27 +452,29 @@ "name": "stdout", "output_type": "stream", "text": [ - "No Standardization 0.5379\n", - "With Standardization 0.5379\n" + "No Standardization 0.6389\n", + "With Standardization 0.6389\n" ] } ], "source": [ "inference_pipe = make_pipeline(standardizer, random_search.best_estimator_)\n", "\n", - "print(f'No Standardization {random_search.best_estimator_.score(mol_list_test, y_test):0.4F}')\n", - "print(f'With Standardization {inference_pipe.score(mol_list_test, y_test):0.4F}')" + "print(\n", + " f\"No Standardization {random_search.best_estimator_.score(mol_list_test, y_test):0.4F}\"\n", + ")\n", + "print(f\"With Standardization {inference_pipe.score(mol_list_test, y_test):0.4F}\")" ] }, { "cell_type": "markdown", - "id": "e00bae88", + "id": "2d31c059", "metadata": { "lines_to_next_cell": 0, "title": "Building an inference pipeline, it appears our test-data was pretty standard" }, "source": [ - "We see that the dataset already appeared to be in forms that are similar to the ones coming from the standardization. \n", + "We see that the dataset already appeared to be in forms that are similar to the ones coming from the standardization.\n", "\n", "Interestingly the test-set performance often seem to be better than the CV performance during the hyperparameter search. This may be due to the model being refit at the end of the search to the whole training dataset, as the refit parameter on the randomized_search object by default is true. The final model is thus fitted on more data than the individual models during training.\n", "\n", @@ -475,13 +484,13 @@ { "cell_type": "code", "execution_count": 14, - "id": "f6426b23", + "id": "92105568", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:27.320951Z", - "iopub.status.busy": "2024-04-12T12:10:27.319924Z", - "iopub.status.idle": "2024-04-12T12:10:27.337918Z", - "shell.execute_reply": "2024-04-12T12:10:27.337344Z" + "iopub.execute_input": "2024-11-24T09:27:36.397490Z", + "iopub.status.busy": "2024-11-24T09:27:36.397082Z", + "iopub.status.idle": "2024-11-24T09:27:36.411965Z", + "shell.execute_reply": "2024-11-24T09:27:36.411400Z" } }, "outputs": [ @@ -489,23 +498,31 @@ "name": "stdout", "output_type": "stream", "text": [ - "Predictions with no standardization: [5.95334818 5.99768591 5.99768591 6.31509408 6.09785566]\n", - "Predictions with standardization: [5.95334818 5.95334818 5.95334818 5.95334818 5.95334818]\n" + "Predictions with no standardization: [5.89126045 5.97721234 5.97721234 6.03427056 6.03951076]\n", + "Predictions with standardization: [5.89126045 5.89126045 5.89126045 5.89126045 5.89126045]\n" ] } ], "source": [ "# Intergrating the Standardizer and challenge it with some different forms and salts of benzoic acid\n", - "smiles_list = ['c1ccccc1C(=O)[OH]', 'c1ccccc1C(=O)[O-]', 'c1ccccc1C(=O)[O-].[Na+]', 'c1ccccc1C(=O)[O][Na]', 'c1ccccc1C(=O)[O-].C[N+](C)C']\n", + "smiles_list = [\n", + " \"c1ccccc1C(=O)[OH]\",\n", + " \"c1ccccc1C(=O)[O-]\",\n", + " \"c1ccccc1C(=O)[O-].[Na+]\",\n", + " \"c1ccccc1C(=O)[O][Na]\",\n", + " \"c1ccccc1C(=O)[O-].C[N+](C)C\",\n", + "]\n", "mols_list = [Chem.MolFromSmiles(smiles) for smiles in smiles_list]\n", "\n", - "print(f'Predictions with no standardization: {random_search.best_estimator_.predict(mols_list)}')\n", - "print(f'Predictions with standardization: {inference_pipe.predict(mols_list)}')" + "print(\n", + " f\"Predictions with no standardization: {random_search.best_estimator_.predict(mols_list)}\"\n", + ")\n", + "print(f\"Predictions with standardization: {inference_pipe.predict(mols_list)}\")" ] }, { "cell_type": "markdown", - "id": "47345289", + "id": "9d196197", "metadata": {}, "source": [ "Without standardization we get variation in the predictions, but with the standardization object in place, we get the same results. If you want a model that gives different predictions for the different forms, either the standardization need to be removed or the settings changed.\n", @@ -515,7 +532,7 @@ }, { "cell_type": "markdown", - "id": "8e0a8f49", + "id": "824ebc99", "metadata": {}, "source": [] } diff --git a/notebooks/06_hyperparameter_tuning.py b/notebooks/06_hyperparameter_tuning.py index 0747bd2..ba59814 100644 --- a/notebooks/06_hyperparameter_tuning.py +++ b/notebooks/06_hyperparameter_tuning.py @@ -44,10 +44,11 @@ csv_file = "SLC6A4_active_excape_export.csv" if not os.path.exists(csv_file): import urllib.request + url = "https://ndownloader.figshare.com/files/25747817" urllib.request.urlretrieve(url, csv_file) else: - csv_file = '../tests/data/SLC6A4_active_excapedb_subset.csv' + csv_file = "../tests/data/SLC6A4_active_excapedb_subset.csv" # %% [markdown] # The CSV data is loaded into a Pandas dataframe and the PandasTools utility from RDKit is used to add a column with RDKit molecules @@ -64,14 +65,16 @@ # %% -mol_list_train, mol_list_test, y_train, y_test = train_test_split(data.ROMol, data.pXC50, random_state=42) +mol_list_train, mol_list_test, y_train, y_test = train_test_split( + data.ROMol, data.pXC50, random_state=42 +) # %% [markdown] # We will standardize the molecules before modelling. This is best done before the hyperparameter optimizatiion of the featurization with the scikit-mol transformer and regression modelling, as the standardization is otherwise done for every loop in the hyperparameter optimization, which will make it take longer time. # %% -# Probably the recommended way would be to prestandardize the data if there's no changes to the transformer, +# Probably the recommended way would be to prestandardize the data if there's no changes to the transformer, # and then add the standardizer in the inference pipeline. from scikit_mol.standardizer import Standardizer @@ -90,13 +93,13 @@ optimization_pipe = make_pipeline(moltransformer, regressor) - # %% [markdown] # For hyperparameter optimization we import the RandomizedSearchCV class from Scikit-Learn. It will try different random combinations of settings and use internal cross-validation to find the best model. In the end, it will fit the best found parameters on the full set. We also import loguniform, to get a better sampling of some of the parameters. # %% Now hyperparameter tuning from sklearn.model_selection import RandomizedSearchCV -#from sklearn.utils.fixes import loguniform + +# from sklearn.utils.fixes import loguniform from scipy.stats import loguniform # %% [markdown] @@ -111,15 +114,18 @@ # %% -param_dist = {'ridge__alpha': loguniform(1e-2, 1e3), - "morganfingerprinttransformer__nBits": [256,512,1024,2048,4096], - 'morganfingerprinttransformer__radius':[1,2,3,4], - 'morganfingerprinttransformer__useCounts': [True,False], - 'morganfingerprinttransformer__useFeatures':[True,False]} +param_dist = { + "ridge__alpha": loguniform(1e-2, 1e3), + "morganfingerprinttransformer__fpSize": [256, 512, 1024, 2048, 4096], + "morganfingerprinttransformer__radius": [1, 2, 3, 4], + "morganfingerprinttransformer__useCounts": [True, False], + "morganfingerprinttransformer__useFeatures": [True, False], +} # %% [markdown] # The report function was taken from [this example](https://scikit-learn.org/stable/auto_examples/model_selection/plot_randomized_search.html#sphx-glr-auto-examples-model-selection-plot-randomized-search-py) from the scikit learn documentation. + # %% From https://scikit-learn.org/stable/auto_examples/model_selection/plot_randomized_search.html#sphx-glr-auto-examples-model-selection-plot-randomized-search-py # Utility function to report best scores def report(results, n_top=3): @@ -149,7 +155,7 @@ def report(results, n_top=3): random_search.fit(mol_list_std_train, y_train.values) t1 = time() -print(f'Runtime: {t1-t0:0.2F} for {n_iter_search} iterations)') +print(f"Runtime: {t1-t0:0.2F} for {n_iter_search} iterations)") # %% report(random_search.cv_results_) @@ -162,22 +168,32 @@ def report(results, n_top=3): # %% inference_pipe = make_pipeline(standardizer, random_search.best_estimator_) -print(f'No Standardization {random_search.best_estimator_.score(mol_list_test, y_test):0.4F}') -print(f'With Standardization {inference_pipe.score(mol_list_test, y_test):0.4F}') +print( + f"No Standardization {random_search.best_estimator_.score(mol_list_test, y_test):0.4F}" +) +print(f"With Standardization {inference_pipe.score(mol_list_test, y_test):0.4F}") # %% Building an inference pipeline, it appears our test-data was pretty standard [markdown] -# We see that the dataset already appeared to be in forms that are similar to the ones coming from the standardization. +# We see that the dataset already appeared to be in forms that are similar to the ones coming from the standardization. # # Interestingly the test-set performance often seem to be better than the CV performance during the hyperparameter search. This may be due to the model being refit at the end of the search to the whole training dataset, as the refit parameter on the randomized_search object by default is true. The final model is thus fitted on more data than the individual models during training. # # To demonstrate the effect of standartization we can see the difference if we challenge the predictor with different forms of benzoic acid and benzoates. # %% # Intergrating the Standardizer and challenge it with some different forms and salts of benzoic acid -smiles_list = ['c1ccccc1C(=O)[OH]', 'c1ccccc1C(=O)[O-]', 'c1ccccc1C(=O)[O-].[Na+]', 'c1ccccc1C(=O)[O][Na]', 'c1ccccc1C(=O)[O-].C[N+](C)C'] +smiles_list = [ + "c1ccccc1C(=O)[OH]", + "c1ccccc1C(=O)[O-]", + "c1ccccc1C(=O)[O-].[Na+]", + "c1ccccc1C(=O)[O][Na]", + "c1ccccc1C(=O)[O-].C[N+](C)C", +] mols_list = [Chem.MolFromSmiles(smiles) for smiles in smiles_list] -print(f'Predictions with no standardization: {random_search.best_estimator_.predict(mols_list)}') -print(f'Predictions with standardization: {inference_pipe.predict(mols_list)}') +print( + f"Predictions with no standardization: {random_search.best_estimator_.predict(mols_list)}" +) +print(f"Predictions with standardization: {inference_pipe.predict(mols_list)}") # %% [markdown] # Without standardization we get variation in the predictions, but with the standardization object in place, we get the same results. If you want a model that gives different predictions for the different forms, either the standardization need to be removed or the settings changed. diff --git a/notebooks/07_parallel_transforms.ipynb b/notebooks/07_parallel_transforms.ipynb index 36c4ac0..9c111f8 100644 --- a/notebooks/07_parallel_transforms.ipynb +++ b/notebooks/07_parallel_transforms.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "3c3e2734", + "id": "87ed8373", "metadata": {}, "source": [ "# Parallel calculations of transforms\n", @@ -15,13 +15,13 @@ { "cell_type": "code", "execution_count": 1, - "id": "d34a6f7e", + "id": "dac6956a", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:28.855965Z", - "iopub.status.busy": "2024-04-12T12:10:28.855774Z", - "iopub.status.idle": "2024-04-12T12:10:29.593405Z", - "shell.execute_reply": "2024-04-12T12:10:29.592709Z" + "iopub.execute_input": "2024-11-24T09:27:38.302600Z", + "iopub.status.busy": "2024-11-24T09:27:38.302116Z", + "iopub.status.idle": "2024-11-24T09:27:39.171522Z", + "shell.execute_reply": "2024-11-24T09:27:39.170882Z" } }, "outputs": [], @@ -38,7 +38,7 @@ }, { "cell_type": "markdown", - "id": "f73bfd41", + "id": "7c2a81f2", "metadata": {}, "source": [ "## Obtaining the Data\n", @@ -51,13 +51,13 @@ { "cell_type": "code", "execution_count": 2, - "id": "f59b0883", + "id": "f64c418f", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:29.596321Z", - "iopub.status.busy": "2024-04-12T12:10:29.596022Z", - "iopub.status.idle": "2024-04-12T12:10:29.600548Z", - "shell.execute_reply": "2024-04-12T12:10:29.599990Z" + "iopub.execute_input": "2024-11-24T09:27:39.174368Z", + "iopub.status.busy": "2024-11-24T09:27:39.174075Z", + "iopub.status.idle": "2024-11-24T09:27:39.177863Z", + "shell.execute_reply": "2024-11-24T09:27:39.177305Z" } }, "outputs": [], @@ -77,13 +77,13 @@ { "cell_type": "code", "execution_count": 3, - "id": "9cb3cb5c", + "id": "0eabd800", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:29.602922Z", - "iopub.status.busy": "2024-04-12T12:10:29.602713Z", - "iopub.status.idle": "2024-04-12T12:10:29.643748Z", - "shell.execute_reply": "2024-04-12T12:10:29.643141Z" + "iopub.execute_input": "2024-11-24T09:27:39.180191Z", + "iopub.status.busy": "2024-11-24T09:27:39.179937Z", + "iopub.status.idle": "2024-11-24T09:27:39.221096Z", + "shell.execute_reply": "2024-11-24T09:27:39.220386Z" } }, "outputs": [ @@ -105,7 +105,7 @@ }, { "cell_type": "markdown", - "id": "cbdda331", + "id": "4144946e", "metadata": {}, "source": [ "## Evaluating the Impact of Parallelism on Transformations\n", @@ -116,13 +116,13 @@ { "cell_type": "code", "execution_count": 4, - "id": "45c042f0", + "id": "a7f66af7", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:29.646541Z", - "iopub.status.busy": "2024-04-12T12:10:29.646035Z", - "iopub.status.idle": "2024-04-12T12:10:29.651144Z", - "shell.execute_reply": "2024-04-12T12:10:29.650588Z" + "iopub.execute_input": "2024-11-24T09:27:39.223702Z", + "iopub.status.busy": "2024-11-24T09:27:39.223459Z", + "iopub.status.idle": "2024-11-24T09:27:39.228461Z", + "shell.execute_reply": "2024-11-24T09:27:39.227977Z" }, "title": "A demonstration of the speedup that can be had for the descriptor transformer" }, @@ -134,21 +134,687 @@ { "cell_type": "code", "execution_count": 5, - "id": "8f158499", + "id": "a03bc824", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:29.653455Z", - "iopub.status.busy": "2024-04-12T12:10:29.653236Z", - "iopub.status.idle": "2024-04-12T12:10:31.579596Z", - "shell.execute_reply": "2024-04-12T12:10:31.578985Z" + "iopub.execute_input": "2024-11-24T09:27:39.230911Z", + "iopub.status.busy": "2024-11-24T09:27:39.230692Z", + "iopub.status.idle": "2024-11-24T09:27:41.368180Z", + "shell.execute_reply": "2024-11-24T09:27:41.367438Z" } }, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:40] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, { "name": "stdout", "output_type": "stream", "text": [ - "Calculation time on dataset of size 200 with parallel=False:\t1.92 seconds\n" + "Calculation time on dataset of size 200 with parallel=False:\t2.13 seconds\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" ] } ], @@ -163,7 +829,7 @@ }, { "cell_type": "markdown", - "id": "08b2cb6e", + "id": "d304d675", "metadata": {}, "source": [ "\n", @@ -173,13 +839,13 @@ { "cell_type": "code", "execution_count": 6, - "id": "f1b48596", + "id": "c80388e6", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:31.582218Z", - "iopub.status.busy": "2024-04-12T12:10:31.581970Z", - "iopub.status.idle": "2024-04-12T12:10:32.110173Z", - "shell.execute_reply": "2024-04-12T12:10:32.109459Z" + "iopub.execute_input": "2024-11-24T09:27:41.370886Z", + "iopub.status.busy": "2024-11-24T09:27:41.370638Z", + "iopub.status.idle": "2024-11-24T09:27:42.384085Z", + "shell.execute_reply": "2024-11-24T09:27:42.383188Z" } }, "outputs": [ @@ -187,15 +853,4215 @@ "name": "stderr", "output_type": "stream", "text": [ - "/home/esben/python_envs/vscode/lib/python3.10/site-packages/numpy/core/fromnumeric.py:59: FutureWarning: 'Series.swapaxes' is deprecated and will be removed in a future version. Please use 'Series.transpose' instead.\n", - " return bound(*args, **kwds)\n" + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/esben/python_envs/vscode/lib/python3.10/site-packages/numpy/core/fromnumeric.py:59: FutureWarning: 'Series.swapaxes' is deprecated and will be removed in a future version. Please use 'Series.transpose' instead.\n", + " return bound(*args, **kwds)\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:41] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:27:42] DEPRECATION WARNING: please use MorganGenerator\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "Calculation time on dataset of size 200 with parallel=True:\t0.52 seconds\n" + "Calculation time on dataset of size 200 with parallel=True:\t1.01 seconds\n" ] } ], @@ -207,7 +5073,7 @@ }, { "cell_type": "markdown", - "id": "267de7b7", + "id": "731bd13a", "metadata": {}, "source": [ "We've seen that parallelism can help speed up our transformations, with the degree of speedup depending on the number of CPU cores available. However, it's worth noting that there may be some overhead associated with the process of splitting the dataset, pickling objects and functions, and passing them to the parallel child processes. As a result, it may not always be worthwhile to use parallelism, particularly for smaller datasets or certain types of fingerprints.\n", @@ -220,13 +5086,13 @@ { "cell_type": "code", "execution_count": 7, - "id": "f8b61e6c", + "id": "ef6d2b0c", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:32.113041Z", - "iopub.status.busy": "2024-04-12T12:10:32.112800Z", - "iopub.status.idle": "2024-04-12T12:10:32.220711Z", - "shell.execute_reply": "2024-04-12T12:10:32.219973Z" + "iopub.execute_input": "2024-11-24T09:27:42.387160Z", + "iopub.status.busy": "2024-11-24T09:27:42.386886Z", + "iopub.status.idle": "2024-11-24T09:27:42.484867Z", + "shell.execute_reply": "2024-11-24T09:27:42.484222Z" }, "lines_to_next_cell": 2, "title": "Some of the benchmarking plots" @@ -256,7 +5122,7 @@ }, { "cell_type": "markdown", - "id": "9c29a58f", + "id": "2aac85b1", "metadata": {}, "source": [ "Interestingly, we observed that parallelism actually took longer to calculate the fingerprints in some cases, which is a perfect illustration of the overhead issue associated with parallelism. Generally, the faster the fingerprint calculation in itself, the larger the dataset needs to be for parallelism to be worthwhile. For example, the Descriptor transformer, which is one of the slowest, can benefit even for smaller datasets, while for faster fingerprint types like Morgan, Atompairs, and Topological Torsion fingerprints, the dataset needs to be larger.\n", diff --git a/notebooks/08_external_library_skopt.ipynb b/notebooks/08_external_library_skopt.ipynb index de50fee..8d8121f 100644 --- a/notebooks/08_external_library_skopt.ipynb +++ b/notebooks/08_external_library_skopt.ipynb @@ -3,8 +3,14 @@ { "cell_type": "code", "execution_count": 1, - "id": "7111cd27", + "id": "c0f4155f", "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:27:44.212745Z", + "iopub.status.busy": "2024-11-24T09:27:44.212299Z", + "iopub.status.idle": "2024-11-24T09:27:47.165987Z", + "shell.execute_reply": "2024-11-24T09:27:47.162995Z" + }, "title": "Needs scikit-optimize" }, "outputs": [ @@ -12,15 +18,21 @@ "name": "stdout", "output_type": "stream", "text": [ - "Requirement already satisfied: scikit-optimize in /home/esben/python_envs/vscode/lib/python3.10/site-packages (0.10.1)\n", - "Requirement already satisfied: packaging>=21.3 in /home/esben/python_envs/vscode/lib/python3.10/site-packages (from scikit-optimize) (23.2)\n", - "Requirement already satisfied: pyaml>=16.9 in /home/esben/python_envs/vscode/lib/python3.10/site-packages (from scikit-optimize) (23.12.0)\n", - "Requirement already satisfied: joblib>=0.11 in /home/esben/python_envs/vscode/lib/python3.10/site-packages (from scikit-optimize) (1.3.2)\n", - "Requirement already satisfied: scikit-learn>=1.0.0 in /home/esben/python_envs/vscode/lib/python3.10/site-packages (from scikit-optimize) (1.3.1)\n", - "Requirement already satisfied: scipy>=1.1.0 in /home/esben/python_envs/vscode/lib/python3.10/site-packages (from scikit-optimize) (1.11.3)\n", - "Requirement already satisfied: numpy>=1.20.3 in /home/esben/python_envs/vscode/lib/python3.10/site-packages (from scikit-optimize) (1.26.0)\n", - "Requirement already satisfied: PyYAML in /home/esben/python_envs/vscode/lib/python3.10/site-packages (from pyaml>=16.9->scikit-optimize) (6.0.1)\n", - "Requirement already satisfied: threadpoolctl>=2.0.0 in /home/esben/python_envs/vscode/lib/python3.10/site-packages (from scikit-learn>=1.0.0->scikit-optimize) (3.2.0)\n" + "Requirement already satisfied: scikit-optimize in /home/esben/python_envs/vscode/lib/python3.10/site-packages (0.10.2)\r\n", + "Requirement already satisfied: scikit-learn>=1.0.0 in /home/esben/python_envs/vscode/lib/python3.10/site-packages (from scikit-optimize) (1.5.2)\r\n", + "Requirement already satisfied: joblib>=0.11 in /home/esben/python_envs/vscode/lib/python3.10/site-packages (from scikit-optimize) (1.3.2)\r\n", + "Requirement already satisfied: scipy>=1.1.0 in /home/esben/python_envs/vscode/lib/python3.10/site-packages (from scikit-optimize) (1.11.3)\r\n", + "Requirement already satisfied: packaging>=21.3 in /home/esben/python_envs/vscode/lib/python3.10/site-packages (from scikit-optimize) (23.2)\r\n", + "Requirement already satisfied: pyaml>=16.9 in /home/esben/python_envs/vscode/lib/python3.10/site-packages (from scikit-optimize) (23.12.0)\r\n", + "Requirement already satisfied: numpy>=1.20.3 in /home/esben/python_envs/vscode/lib/python3.10/site-packages (from scikit-optimize) (1.26.4)\r\n", + "Requirement already satisfied: PyYAML in /home/esben/python_envs/vscode/lib/python3.10/site-packages (from pyaml>=16.9->scikit-optimize) (6.0.1)\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: threadpoolctl>=3.1.0 in /home/esben/python_envs/vscode/lib/python3.10/site-packages (from scikit-learn>=1.0.0->scikit-optimize) (3.2.0)\r\n" ] } ], @@ -31,9 +43,14 @@ { "cell_type": "code", "execution_count": 2, - "id": "5648edb8", + "id": "49f80040", "metadata": { - "lines_to_next_cell": 0 + "execution": { + "iopub.execute_input": "2024-11-24T09:27:47.174431Z", + "iopub.status.busy": "2024-11-24T09:27:47.173616Z", + "iopub.status.idle": "2024-11-24T09:27:47.507299Z", + "shell.execute_reply": "2024-11-24T09:27:47.506634Z" + } }, "outputs": [], "source": [ @@ -45,8 +62,15 @@ { "cell_type": "code", "execution_count": 3, - "id": "6825d2cd", - "metadata": {}, + "id": "f1268213", + "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:27:47.510217Z", + "iopub.status.busy": "2024-11-24T09:27:47.509924Z", + "iopub.status.idle": "2024-11-24T09:27:48.065273Z", + "shell.execute_reply": "2024-11-24T09:27:48.064596Z" + } + }, "outputs": [], "source": [ "from sklearn.linear_model import Ridge\n", @@ -61,9 +85,14 @@ { "cell_type": "code", "execution_count": 4, - "id": "12f97eb7", + "id": "7239cf27", "metadata": { - "lines_to_next_cell": 0 + "execution": { + "iopub.execute_input": "2024-11-24T09:27:48.068114Z", + "iopub.status.busy": "2024-11-24T09:27:48.067809Z", + "iopub.status.idle": "2024-11-24T09:27:48.129879Z", + "shell.execute_reply": "2024-11-24T09:27:48.129159Z" + } }, "outputs": [], "source": [ @@ -76,8 +105,15 @@ { "cell_type": "code", "execution_count": 5, - "id": "3e9f36e9", - "metadata": {}, + "id": "aabbba9d", + "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:27:48.132744Z", + "iopub.status.busy": "2024-11-24T09:27:48.132424Z", + "iopub.status.idle": "2024-11-24T09:27:48.173318Z", + "shell.execute_reply": "2024-11-24T09:27:48.172690Z" + } + }, "outputs": [], "source": [ "full_set = False\n", @@ -86,32 +122,443 @@ " csv_file = \"SLC6A4_active_excape_export.csv\"\n", " if not os.path.exists(csv_file):\n", " import urllib.request\n", + "\n", " url = \"https://ndownloader.figshare.com/files/25747817\"\n", " urllib.request.urlretrieve(url, csv_file)\n", "else:\n", - " csv_file = '../tests/data/SLC6A4_active_excapedb_subset.csv'\n", + " csv_file = \"../tests/data/SLC6A4_active_excapedb_subset.csv\"\n", "\n", "data = pd.read_csv(csv_file)\n", "trf = SmilesToMolTransformer()\n", - "data['ROMol'] = trf.transform(data.SMILES.values).flatten()" + "data[\"ROMol\"] = trf.transform(data.SMILES.values).flatten()" ] }, { "cell_type": "code", "execution_count": 6, - "id": "67d54492", + "id": "488a3e82", "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:27:48.176242Z", + "iopub.status.busy": "2024-11-24T09:27:48.175854Z", + "iopub.status.idle": "2024-11-24T09:27:48.188154Z", + "shell.execute_reply": "2024-11-24T09:27:48.187463Z" + }, "lines_to_next_cell": 0 }, "outputs": [ { "data": { "text/html": [ - "
Pipeline(steps=[('morganfingerprinttransformer',\n",
+       "
Pipeline(steps=[('morganfingerprinttransformer',\n",
        "                 MorganFingerprintTransformer()),\n",
-       "                ('ridge', Ridge())])
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
MorganFingerprintTransformer()
" ], "text/plain": [ "Pipeline(steps=[('morganfingerprinttransformer',\n", @@ -132,14 +579,21 @@ { "cell_type": "code", "execution_count": 7, - "id": "e3ce7fc0", - "metadata": {}, + "id": "44811b8e", + "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:27:48.190932Z", + "iopub.status.busy": "2024-11-24T09:27:48.190654Z", + "iopub.status.idle": "2024-11-24T09:27:48.195099Z", + "shell.execute_reply": "2024-11-24T09:27:48.194411Z" + } + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "{'memory': None, 'steps': [('morganfingerprinttransformer', MorganFingerprintTransformer()), ('ridge', Ridge())], 'verbose': False, 'morganfingerprinttransformer': MorganFingerprintTransformer(), 'ridge': Ridge(), 'morganfingerprinttransformer__nBits': 2048, 'morganfingerprinttransformer__parallel': False, 'morganfingerprinttransformer__radius': 2, 'morganfingerprinttransformer__useBondTypes': True, 'morganfingerprinttransformer__useChirality': False, 'morganfingerprinttransformer__useCounts': False, 'morganfingerprinttransformer__useFeatures': False, 'ridge__alpha': 1.0, 'ridge__copy_X': True, 'ridge__fit_intercept': True, 'ridge__max_iter': None, 'ridge__positive': False, 'ridge__random_state': None, 'ridge__solver': 'auto', 'ridge__tol': 0.0001}\n" + "{'memory': None, 'steps': [('morganfingerprinttransformer', MorganFingerprintTransformer()), ('ridge', Ridge())], 'verbose': False, 'morganfingerprinttransformer': MorganFingerprintTransformer(), 'ridge': Ridge(), 'morganfingerprinttransformer__fpSize': 2048, 'morganfingerprinttransformer__parallel': False, 'morganfingerprinttransformer__radius': 2, 'morganfingerprinttransformer__safe_inference_mode': False, 'morganfingerprinttransformer__useBondTypes': True, 'morganfingerprinttransformer__useChirality': False, 'morganfingerprinttransformer__useCounts': False, 'morganfingerprinttransformer__useFeatures': False, 'ridge__alpha': 1.0, 'ridge__copy_X': True, 'ridge__fit_intercept': True, 'ridge__max_iter': None, 'ridge__positive': False, 'ridge__random_state': None, 'ridge__solver': 'auto', 'ridge__tol': 0.0001}\n" ] } ], @@ -150,23 +604,28 @@ { "cell_type": "code", "execution_count": 8, - "id": "0a155dd3", + "id": "49eb7dbe", "metadata": { - "lines_to_next_cell": 0 + "execution": { + "iopub.execute_input": "2024-11-24T09:27:48.197795Z", + "iopub.status.busy": "2024-11-24T09:27:48.197479Z", + "iopub.status.idle": "2024-11-24T09:27:48.205564Z", + "shell.execute_reply": "2024-11-24T09:27:48.205022Z" + } }, "outputs": [], "source": [ "max_bits = 4096\n", "\n", "morgan_space = [\n", - " Categorical([True, False], name='morganfingerprinttransformer__useCounts'),\n", - " Categorical([True, False], name='morganfingerprinttransformer__useFeatures'),\n", - " Integer(512,max_bits, name='morganfingerprinttransformer__nBits'),\n", - " Integer(1,3, name='morganfingerprinttransformer__radius')\n", + " Categorical([True, False], name=\"morganfingerprinttransformer__useCounts\"),\n", + " Categorical([True, False], name=\"morganfingerprinttransformer__useFeatures\"),\n", + " Integer(512, max_bits, name=\"morganfingerprinttransformer__fpSize\"),\n", + " Integer(1, 3, name=\"morganfingerprinttransformer__radius\"),\n", "]\n", "\n", "\n", - "regressor_space = [Real(1e-2, 1e3, \"log-uniform\", name='ridge__alpha')]\n", + "regressor_space = [Real(1e-2, 1e3, \"log-uniform\", name=\"ridge__alpha\")]\n", "\n", "search_space = morgan_space + regressor_space" ] @@ -174,9 +633,14 @@ { "cell_type": "code", "execution_count": 9, - "id": "abb750a3", + "id": "3818beb2", "metadata": { - "lines_to_next_cell": 0 + "execution": { + "iopub.execute_input": "2024-11-24T09:27:48.207944Z", + "iopub.status.busy": "2024-11-24T09:27:48.207727Z", + "iopub.status.idle": "2024-11-24T09:27:48.211453Z", + "shell.execute_reply": "2024-11-24T09:27:48.210957Z" + } }, "outputs": [], "source": [ @@ -186,15 +650,29 @@ " print(f\"{key}:{value} - {type(value)}\")\n", " pipe.set_params(**params)\n", "\n", - " return -np.mean(cross_val_score(pipe, data.ROMol, data.pXC50, cv=2, n_jobs=-1,\n", - " scoring=\"neg_mean_absolute_error\"))" + " return -np.mean(\n", + " cross_val_score(\n", + " pipe,\n", + " data.ROMol,\n", + " data.pXC50,\n", + " cv=2,\n", + " n_jobs=-1,\n", + " scoring=\"neg_mean_absolute_error\",\n", + " )\n", + " )" ] }, { "cell_type": "code", "execution_count": 10, - "id": "8b6a546c", + "id": "aa6b3af8", "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:27:48.213752Z", + "iopub.status.busy": "2024-11-24T09:27:48.213531Z", + "iopub.status.idle": "2024-11-24T09:27:50.948132Z", + "shell.execute_reply": "2024-11-24T09:27:50.947483Z" + }, "lines_to_next_cell": 0, "title": "THIS takes forever on my machine with a GradientBoostingRegressor" }, @@ -205,7 +683,7 @@ "text": [ "morganfingerprinttransformer__useCounts:False - \n", "morganfingerprinttransformer__useFeatures:False - \n", - "morganfingerprinttransformer__nBits:3587 - \n", + "morganfingerprinttransformer__fpSize:3587 - \n", "morganfingerprinttransformer__radius:3 - \n", "ridge__alpha:13.116515715358098 - \n" ] @@ -216,47 +694,65 @@ "text": [ "morganfingerprinttransformer__useCounts:True - \n", "morganfingerprinttransformer__useFeatures:True - \n", - "morganfingerprinttransformer__nBits:715 - \n", + "morganfingerprinttransformer__fpSize:715 - \n", "morganfingerprinttransformer__radius:2 - \n", - "ridge__alpha:2.445263057083992 - \n", + "ridge__alpha:2.445263057083992 - \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ "morganfingerprinttransformer__useCounts:False - \n", "morganfingerprinttransformer__useFeatures:True - \n", - "morganfingerprinttransformer__nBits:1920 - \n", + "morganfingerprinttransformer__fpSize:1920 - \n", "morganfingerprinttransformer__radius:3 - \n", "ridge__alpha:0.48638570461894715 - \n", "morganfingerprinttransformer__useCounts:False - \n", "morganfingerprinttransformer__useFeatures:True - \n", - "morganfingerprinttransformer__nBits:3942 - \n", + "morganfingerprinttransformer__fpSize:3942 - \n", "morganfingerprinttransformer__radius:1 - \n", "ridge__alpha:224.09712855921126 - \n", "morganfingerprinttransformer__useCounts:True - \n", "morganfingerprinttransformer__useFeatures:False - \n", - "morganfingerprinttransformer__nBits:2377 - \n", + "morganfingerprinttransformer__fpSize:2377 - \n", "morganfingerprinttransformer__radius:2 - \n", - "ridge__alpha:40.10174523739503 - \n", + "ridge__alpha:40.10174523739503 - \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ "morganfingerprinttransformer__useCounts:False - \n", "morganfingerprinttransformer__useFeatures:False - \n", - "morganfingerprinttransformer__nBits:3231 - \n", + "morganfingerprinttransformer__fpSize:3231 - \n", "morganfingerprinttransformer__radius:1 - \n", "ridge__alpha:2.333469328026273 - \n", "morganfingerprinttransformer__useCounts:True - \n", "morganfingerprinttransformer__useFeatures:False - \n", - "morganfingerprinttransformer__nBits:1288 - \n", + "morganfingerprinttransformer__fpSize:1288 - \n", "morganfingerprinttransformer__radius:1 - \n", "ridge__alpha:0.41754668393896904 - \n", "morganfingerprinttransformer__useCounts:True - \n", "morganfingerprinttransformer__useFeatures:True - \n", - "morganfingerprinttransformer__nBits:1897 - \n", + "morganfingerprinttransformer__fpSize:1897 - \n", "morganfingerprinttransformer__radius:3 - \n", "ridge__alpha:1.777255838269662 - \n", "morganfingerprinttransformer__useCounts:False - \n", "morganfingerprinttransformer__useFeatures:False - \n", - "morganfingerprinttransformer__nBits:868 - \n", + "morganfingerprinttransformer__fpSize:868 - \n", "morganfingerprinttransformer__radius:3 - \n", - "ridge__alpha:18.43742127649598 - \n", + "ridge__alpha:18.43742127649598 - \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ "morganfingerprinttransformer__useCounts:True - \n", "morganfingerprinttransformer__useFeatures:True - \n", - "morganfingerprinttransformer__nBits:3202 - \n", + "morganfingerprinttransformer__fpSize:3202 - \n", "morganfingerprinttransformer__radius:2 - \n", "ridge__alpha:0.4219258607446576 - \n" ] @@ -281,8 +777,14 @@ { "cell_type": "code", "execution_count": 11, - "id": "243f5309", + "id": "42d8fc82", "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:27:50.951138Z", + "iopub.status.busy": "2024-11-24T09:27:50.950922Z", + "iopub.status.idle": "2024-11-24T09:27:50.956593Z", + "shell.execute_reply": "2024-11-24T09:27:50.956046Z" + }, "lines_to_next_cell": 0 }, "outputs": [ @@ -291,20 +793,27 @@ "output_type": "stream", "text": [ "Best parameters:\n", - "{'morganfingerprinttransformer__useCounts': False, 'morganfingerprinttransformer__useFeatures': False, 'morganfingerprinttransformer__nBits': 3231, 'morganfingerprinttransformer__radius': 1, 'ridge__alpha': 2.333469328026273}\n" + "{'morganfingerprinttransformer__useCounts': False, 'morganfingerprinttransformer__useFeatures': False, 'morganfingerprinttransformer__fpSize': 3231, 'morganfingerprinttransformer__radius': 1, 'ridge__alpha': 2.333469328026273}\n" ] } ], "source": [ "print(\"\"\"Best parameters:\"\"\")\n", - "print({param.name:value for param,value in zip(pipe_gp.space, pipe_gp.x) })" + "print({param.name: value for param, value in zip(pipe_gp.space, pipe_gp.x)})" ] }, { "cell_type": "code", "execution_count": 12, - "id": "b95b09d1", - "metadata": {}, + "id": "c5e9fda9", + "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:27:50.959607Z", + "iopub.status.busy": "2024-11-24T09:27:50.959088Z", + "iopub.status.idle": "2024-11-24T09:27:51.588690Z", + "shell.execute_reply": "2024-11-24T09:27:51.587982Z" + } + }, "outputs": [ { "data": { @@ -329,13 +838,14 @@ ], "source": [ "from skopt.plots import plot_convergence\n", + "\n", "plot_convergence(pipe_gp)" ] }, { "cell_type": "code", "execution_count": null, - "id": "8371d672", + "id": "aebdc43d", "metadata": {}, "outputs": [], "source": [] @@ -344,8 +854,7 @@ "metadata": { "jupytext": { "cell_metadata_filter": "title,-all", - "formats": "ipynb,py:percent", - "main_language": "python" + "formats": "ipynb,py:percent" }, "kernelspec": { "display_name": "vscode", diff --git a/notebooks/08_external_library_skopt.py b/notebooks/08_external_library_skopt.py index 4254251..090983e 100644 --- a/notebooks/08_external_library_skopt.py +++ b/notebooks/08_external_library_skopt.py @@ -21,6 +21,7 @@ import os import numpy as np import pandas as pd + # %% from sklearn.linear_model import Ridge from sklearn.model_selection import cross_val_score @@ -35,6 +36,7 @@ from skopt.utils import use_named_args from skopt import gp_minimize + # %% full_set = False @@ -42,14 +44,15 @@ csv_file = "SLC6A4_active_excape_export.csv" if not os.path.exists(csv_file): import urllib.request + url = "https://ndownloader.figshare.com/files/25747817" urllib.request.urlretrieve(url, csv_file) else: - csv_file = '../tests/data/SLC6A4_active_excapedb_subset.csv' + csv_file = "../tests/data/SLC6A4_active_excapedb_subset.csv" data = pd.read_csv(csv_file) trf = SmilesToMolTransformer() -data['ROMol'] = trf.transform(data.SMILES.values).flatten() +data["ROMol"] = trf.transform(data.SMILES.values).flatten() # %% pipe = make_pipeline(MorganFingerprintTransformer(), Ridge()) @@ -61,16 +64,18 @@ max_bits = 4096 morgan_space = [ - Categorical([True, False], name='morganfingerprinttransformer__useCounts'), - Categorical([True, False], name='morganfingerprinttransformer__useFeatures'), - Integer(512,max_bits, name='morganfingerprinttransformer__nBits'), - Integer(1,3, name='morganfingerprinttransformer__radius') + Categorical([True, False], name="morganfingerprinttransformer__useCounts"), + Categorical([True, False], name="morganfingerprinttransformer__useFeatures"), + Integer(512, max_bits, name="morganfingerprinttransformer__fpSize"), + Integer(1, 3, name="morganfingerprinttransformer__radius"), ] -regressor_space = [Real(1e-2, 1e3, "log-uniform", name='ridge__alpha')] +regressor_space = [Real(1e-2, 1e3, "log-uniform", name="ridge__alpha")] search_space = morgan_space + regressor_space + + # %% @use_named_args(search_space) def objective(**params): @@ -78,17 +83,28 @@ def objective(**params): print(f"{key}:{value} - {type(value)}") pipe.set_params(**params) - return -np.mean(cross_val_score(pipe, data.ROMol, data.pXC50, cv=2, n_jobs=-1, - scoring="neg_mean_absolute_error")) + return -np.mean( + cross_val_score( + pipe, + data.ROMol, + data.pXC50, + cv=2, + n_jobs=-1, + scoring="neg_mean_absolute_error", + ) + ) + + # %% THIS takes forever on my machine with a GradientBoostingRegressor pipe_gp = gp_minimize(objective, search_space, n_calls=10, random_state=0) "Best score=%.4f" % pipe_gp.fun # %% print("""Best parameters:""") -print({param.name:value for param,value in zip(pipe_gp.space, pipe_gp.x) }) +print({param.name: value for param, value in zip(pipe_gp.space, pipe_gp.x)}) # %% from skopt.plots import plot_convergence + plot_convergence(pipe_gp) # %% diff --git a/notebooks/09_Combinatorial_Method_Usage_with_FingerPrint_Transformers.ipynb b/notebooks/09_Combinatorial_Method_Usage_with_FingerPrint_Transformers.ipynb index 8e4e2fd..18bc9ec 100644 --- a/notebooks/09_Combinatorial_Method_Usage_with_FingerPrint_Transformers.ipynb +++ b/notebooks/09_Combinatorial_Method_Usage_with_FingerPrint_Transformers.ipynb @@ -2,6 +2,7 @@ "cells": [ { "cell_type": "markdown", + "id": "0e70fca3", "metadata": {}, "source": [ "# Example: Using Multiple Different Fingerprint Transformer\n", @@ -14,7 +15,7 @@ "* Training Phase\n", "* Analysis\n", "\n", - "Authors: @VincentAlexanderScholz, @RiesBen \n", + "Authors: @VincentAlexanderScholz, @RiesBen\n", "\n", "## Imports:\n", "First we will import all the stuff that we will need for our work.\n" @@ -23,12 +24,13 @@ { "cell_type": "code", "execution_count": 1, + "id": "b705b5c9", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:33.739171Z", - "iopub.status.busy": "2024-04-12T12:10:33.738827Z", - "iopub.status.idle": "2024-04-12T12:10:34.837344Z", - "shell.execute_reply": "2024-04-12T12:10:34.836672Z" + "iopub.execute_input": "2024-11-24T09:27:55.508365Z", + "iopub.status.busy": "2024-11-24T09:27:55.507967Z", + "iopub.status.idle": "2024-11-24T09:27:56.807362Z", + "shell.execute_reply": "2024-11-24T09:27:56.806654Z" }, "lines_to_next_cell": 2 }, @@ -52,6 +54,7 @@ }, { "cell_type": "markdown", + "id": "2a4eb825", "metadata": {}, "source": [ "## Get Data:\n", @@ -64,12 +67,13 @@ { "cell_type": "code", "execution_count": 2, + "id": "34b2618a", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:10:34.840322Z", - "iopub.status.busy": "2024-04-12T12:10:34.839978Z", - "iopub.status.idle": "2024-04-12T12:10:34.881015Z", - "shell.execute_reply": "2024-04-12T12:10:34.880411Z" + "iopub.execute_input": "2024-11-24T09:27:56.810246Z", + "iopub.status.busy": "2024-11-24T09:27:56.809941Z", + "iopub.status.idle": "2024-11-24T09:27:56.851202Z", + "shell.execute_reply": "2024-11-24T09:27:56.850568Z" } }, "outputs": [ @@ -89,12 +93,13 @@ " csv_file = \"SLC6A4_active_excape_export.csv\"\n", " if not os.path.exists(csv_file):\n", " import urllib.request\n", + "\n", " url = \"https://ndownloader.figshare.com/files/25747817\"\n", " urllib.request.urlretrieve(url, csv_file)\n", "else:\n", - " csv_file = '../tests/data/SLC6A4_active_excapedb_subset.csv'\n", + " csv_file = \"../tests/data/SLC6A4_active_excapedb_subset.csv\"\n", "\n", - "#Parse Database\n", + "# Parse Database\n", "data = pd.read_csv(csv_file)\n", "\n", "PandasTools.AddMoleculeColumnToFrame(data, smilesCol=\"SMILES\")\n", @@ -103,12 +108,13 @@ }, { "cell_type": "markdown", + "id": "b8dba759", "metadata": {}, "source": [ "## Build Pipeline:\n", "In this stage we will build the Pipeline consisting of the featurization part (finger print transformers) and the model part (Ridge Regression).\n", "\n", - "Note that the featurization in this section is an hyperparameter, living in `param_grid`, and the `\"fp_transformer\"` string is just a placeholder, being replaced during pipeline execution. \n", + "Note that the featurization in this section is an hyperparameter, living in `param_grid`, and the `\"fp_transformer\"` string is just a placeholder, being replaced during pipeline execution.\n", "\n", "This way we can define multiple different scenarios in `param_grid`, that allow us to rapidly explore different combinations of settings and methodologies." ] @@ -116,16 +122,13 @@ { "cell_type": "code", "execution_count": 3, + "id": "e06042cc", "metadata": { - "ExecuteTime": { - "end_time": "2023-09-22T11:29:15.949644Z", - "start_time": "2023-09-22T11:29:15.461010Z" - }, "execution": { - "iopub.execute_input": "2024-04-12T12:10:34.883521Z", - "iopub.status.busy": "2024-04-12T12:10:34.883306Z", - "iopub.status.idle": "2024-04-12T12:10:34.893319Z", - "shell.execute_reply": "2024-04-12T12:10:34.892759Z" + "iopub.execute_input": "2024-11-24T09:27:56.854051Z", + "iopub.status.busy": "2024-11-24T09:27:56.853508Z", + "iopub.status.idle": "2024-11-24T09:27:56.863947Z", + "shell.execute_reply": "2024-11-24T09:27:56.863371Z" } }, "outputs": [ @@ -134,7 +137,7 @@ "text/plain": [ "[{'fp_transformer': [MorganFingerprintTransformer(),\n", " AvalonFingerprintTransformer()],\n", - " 'fp_transformer__nBits': [256, 512, 1024, 2048, 4096],\n", + " 'fp_transformer__fpSize': [256, 512, 1024, 2048, 4096],\n", " 'regressor__alpha': array([0.1 , 0.325, 0.55 , 0.775, 1. ])},\n", " {'fp_transformer': [RDKitFingerprintTransformer(),\n", " AtomPairFingerprintTransformer(),\n", @@ -150,24 +153,35 @@ "source": [ "\n", "regressor = Ridge()\n", - "optimization_pipe = Pipeline([(\"fp_transformer\", \"fp_transformer\"), # this is a placeholder for different transformers\n", - " (\"regressor\", regressor)])\n", - "\n", - "param_grid = [ # Here pass different Options and Approaches\n", + "optimization_pipe = Pipeline(\n", + " [\n", + " (\n", + " \"fp_transformer\",\n", + " \"fp_transformer\",\n", + " ), # this is a placeholder for different transformers\n", + " (\"regressor\", regressor),\n", + " ]\n", + ")\n", + "\n", + "param_grid = [ # Here pass different Options and Approaches\n", " {\n", - " \"fp_transformer\": [fingerprints.MorganFingerprintTransformer(),\n", - " fingerprints.AvalonFingerprintTransformer()],\n", - " \"fp_transformer__nBits\": [2**x for x in range(8,13)],\n", + " \"fp_transformer\": [\n", + " fingerprints.MorganFingerprintTransformer(),\n", + " fingerprints.AvalonFingerprintTransformer(),\n", + " ],\n", + " \"fp_transformer__fpSize\": [2**x for x in range(8, 13)],\n", " },\n", " {\n", - " \"fp_transformer\": [fingerprints.RDKitFingerprintTransformer(),\n", - " fingerprints.AtomPairFingerprintTransformer(),\n", - " fingerprints.MACCSKeysFingerprintTransformer()], \n", + " \"fp_transformer\": [\n", + " fingerprints.RDKitFingerprintTransformer(),\n", + " fingerprints.AtomPairFingerprintTransformer(),\n", + " fingerprints.MACCSKeysFingerprintTransformer(),\n", + " ],\n", " },\n", "]\n", "\n", "global_options = {\n", - " \"regressor__alpha\": np.linspace(0.1,1,5),\n", + " \"regressor__alpha\": np.linspace(0.1, 1, 5),\n", "}\n", "\n", "[params.update(global_options) for params in param_grid]\n", @@ -177,6 +191,7 @@ }, { "cell_type": "markdown", + "id": "521aa24a", "metadata": {}, "source": [ "## Train Model\n", @@ -186,16 +201,13 @@ { "cell_type": "code", "execution_count": 4, + "id": "f1cf66df", "metadata": { - "ExecuteTime": { - "end_time": "2023-09-22T11:29:15.960939Z", - "start_time": "2023-09-22T11:29:15.461078Z" - }, "execution": { - "iopub.execute_input": "2024-04-12T12:10:34.895684Z", - "iopub.status.busy": "2024-04-12T12:10:34.895457Z", - "iopub.status.idle": "2024-04-12T12:11:08.386413Z", - "shell.execute_reply": "2024-04-12T12:11:08.385791Z" + "iopub.execute_input": "2024-11-24T09:27:56.866817Z", + "iopub.status.busy": "2024-11-24T09:27:56.866251Z", + "iopub.status.idle": "2024-11-24T09:28:28.265183Z", + "shell.execute_reply": "2024-11-24T09:28:28.264595Z" } }, "outputs": [ @@ -203,28 +215,30 @@ "name": "stdout", "output_type": "stream", "text": [ - "Runtime: 33.48\n" + "Runtime: 31.39\n" ] } ], "source": [ "# Split Data\n", - "mol_list_train, mol_list_test, y_train, y_test = train_test_split(data.ROMol, data.pXC50, random_state=0)\n", + "mol_list_train, mol_list_test, y_train, y_test = train_test_split(\n", + " data.ROMol, data.pXC50, random_state=0\n", + ")\n", "\n", "# Define Search Process\n", - "grid = GridSearchCV(optimization_pipe, n_jobs=1,\n", - " param_grid=param_grid)\n", + "grid = GridSearchCV(optimization_pipe, n_jobs=1, param_grid=param_grid)\n", "\n", "# Train\n", "t0 = time()\n", "grid.fit(mol_list_train, y_train.values)\n", "t1 = time()\n", "\n", - "print(f'Runtime: {t1-t0:0.2F}')" + "print(f\"Runtime: {t1-t0:0.2F}\")" ] }, { "cell_type": "markdown", + "id": "55aa1549", "metadata": {}, "source": [ "## Analysis\n", @@ -235,12 +249,13 @@ { "cell_type": "code", "execution_count": 5, + "id": "f80006f8", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:08.390298Z", - "iopub.status.busy": "2024-04-12T12:11:08.389259Z", - "iopub.status.idle": "2024-04-12T12:11:08.443953Z", - "shell.execute_reply": "2024-04-12T12:11:08.443334Z" + "iopub.execute_input": "2024-11-24T09:28:28.268630Z", + "iopub.status.busy": "2024-11-24T09:28:28.268131Z", + "iopub.status.idle": "2024-11-24T09:28:28.320208Z", + "shell.execute_reply": "2024-11-24T09:28:28.319598Z" } }, "outputs": [ @@ -270,7 +285,7 @@ " mean_score_time\n", " std_score_time\n", " param_fp_transformer\n", - " param_fp_transformer__nBits\n", + " param_fp_transformer__fpSize\n", " param_regressor__alpha\n", " params\n", " split0_test_score\n", @@ -286,13 +301,13 @@ " \n", " \n", " 0\n", - " 0.025447\n", - " 0.002689\n", - " 0.003600\n", - " 0.000743\n", + " 0.011822\n", + " 0.001013\n", + " 0.003596\n", + " 0.001311\n", " MorganFingerprintTransformer()\n", - " 256\n", - " 0.1\n", + " 256.0\n", + " 0.100\n", " {'fp_transformer': MorganFingerprintTransforme...\n", " 0.017975\n", " 0.394682\n", @@ -305,12 +320,12 @@ " \n", " \n", " 1\n", - " 0.025515\n", - " 0.001279\n", - " 0.003084\n", - " 0.000064\n", + " 0.010119\n", + " 0.000152\n", + " 0.002832\n", + " 0.000070\n", " MorganFingerprintTransformer()\n", - " 256\n", + " 256.0\n", " 0.325\n", " {'fp_transformer': MorganFingerprintTransforme...\n", " 0.078758\n", @@ -324,13 +339,13 @@ " \n", " \n", " 2\n", - " 0.026243\n", - " 0.000330\n", - " 0.003101\n", - " 0.000081\n", + " 0.010302\n", + " 0.000429\n", + " 0.003310\n", + " 0.000967\n", " MorganFingerprintTransformer()\n", - " 256\n", - " 0.55\n", + " 256.0\n", + " 0.550\n", " {'fp_transformer': MorganFingerprintTransforme...\n", " 0.128221\n", " 0.490253\n", @@ -343,12 +358,12 @@ " \n", " \n", " 3\n", - " 0.026571\n", - " 0.001018\n", - " 0.003208\n", - " 0.000214\n", + " 0.010192\n", + " 0.000159\n", + " 0.002859\n", + " 0.000089\n", " MorganFingerprintTransformer()\n", - " 256\n", + " 256.0\n", " 0.775\n", " {'fp_transformer': MorganFingerprintTransforme...\n", " 0.169585\n", @@ -362,13 +377,13 @@ " \n", " \n", " 4\n", - " 0.027070\n", - " 0.001007\n", - " 0.003137\n", - " 0.000176\n", + " 0.010103\n", + " 0.000126\n", + " 0.002868\n", + " 0.000119\n", " MorganFingerprintTransformer()\n", - " 256\n", - " 1.0\n", + " 256.0\n", + " 1.000\n", " {'fp_transformer': MorganFingerprintTransforme...\n", " 0.204831\n", " 0.546774\n", @@ -400,13 +415,13 @@ " \n", " \n", " 60\n", - " 0.113114\n", - " 0.018944\n", - " 0.029888\n", - " 0.008465\n", + " 0.100754\n", + " 0.006501\n", + " 0.025367\n", + " 0.001743\n", " MACCSKeysFingerprintTransformer()\n", " NaN\n", - " 0.1\n", + " 0.100\n", " {'fp_transformer': MACCSKeysFingerprintTransfo...\n", " -1.649022\n", " -1.943461\n", @@ -419,10 +434,10 @@ " \n", " \n", " 61\n", - " 0.102846\n", - " 0.001870\n", - " 0.025450\n", - " 0.001682\n", + " 0.118554\n", + " 0.022440\n", + " 0.036584\n", + " 0.023911\n", " MACCSKeysFingerprintTransformer()\n", " NaN\n", " 0.325\n", @@ -438,13 +453,13 @@ " \n", " \n", " 62\n", - " 0.103216\n", - " 0.001285\n", - " 0.025450\n", - " 0.001661\n", + " 0.097552\n", + " 0.001638\n", + " 0.025571\n", + " 0.001753\n", " MACCSKeysFingerprintTransformer()\n", " NaN\n", - " 0.55\n", + " 0.550\n", " {'fp_transformer': MACCSKeysFingerprintTransfo...\n", " -0.657588\n", " -0.505782\n", @@ -457,10 +472,10 @@ " \n", " \n", " 63\n", - " 0.103230\n", - " 0.002304\n", - " 0.025570\n", - " 0.001561\n", + " 0.098300\n", + " 0.001744\n", + " 0.025552\n", + " 0.001695\n", " MACCSKeysFingerprintTransformer()\n", " NaN\n", " 0.775\n", @@ -476,13 +491,13 @@ " \n", " \n", " 64\n", - " 0.104568\n", - " 0.002589\n", - " 0.025515\n", - " 0.001571\n", + " 0.098103\n", + " 0.001473\n", + " 0.025320\n", + " 0.001673\n", " MACCSKeysFingerprintTransformer()\n", " NaN\n", - " 1.0\n", + " 1.000\n", " {'fp_transformer': MACCSKeysFingerprintTransfo...\n", " -0.339715\n", " -0.266652\n", @@ -500,43 +515,43 @@ ], "text/plain": [ " mean_fit_time std_fit_time mean_score_time std_score_time \\\n", - "0 0.025447 0.002689 0.003600 0.000743 \n", - "1 0.025515 0.001279 0.003084 0.000064 \n", - "2 0.026243 0.000330 0.003101 0.000081 \n", - "3 0.026571 0.001018 0.003208 0.000214 \n", - "4 0.027070 0.001007 0.003137 0.000176 \n", + "0 0.011822 0.001013 0.003596 0.001311 \n", + "1 0.010119 0.000152 0.002832 0.000070 \n", + "2 0.010302 0.000429 0.003310 0.000967 \n", + "3 0.010192 0.000159 0.002859 0.000089 \n", + "4 0.010103 0.000126 0.002868 0.000119 \n", ".. ... ... ... ... \n", - "60 0.113114 0.018944 0.029888 0.008465 \n", - "61 0.102846 0.001870 0.025450 0.001682 \n", - "62 0.103216 0.001285 0.025450 0.001661 \n", - "63 0.103230 0.002304 0.025570 0.001561 \n", - "64 0.104568 0.002589 0.025515 0.001571 \n", + "60 0.100754 0.006501 0.025367 0.001743 \n", + "61 0.118554 0.022440 0.036584 0.023911 \n", + "62 0.097552 0.001638 0.025571 0.001753 \n", + "63 0.098300 0.001744 0.025552 0.001695 \n", + "64 0.098103 0.001473 0.025320 0.001673 \n", "\n", - " param_fp_transformer param_fp_transformer__nBits \\\n", - "0 MorganFingerprintTransformer() 256 \n", - "1 MorganFingerprintTransformer() 256 \n", - "2 MorganFingerprintTransformer() 256 \n", - "3 MorganFingerprintTransformer() 256 \n", - "4 MorganFingerprintTransformer() 256 \n", - ".. ... ... \n", - "60 MACCSKeysFingerprintTransformer() NaN \n", - "61 MACCSKeysFingerprintTransformer() NaN \n", - "62 MACCSKeysFingerprintTransformer() NaN \n", - "63 MACCSKeysFingerprintTransformer() NaN \n", - "64 MACCSKeysFingerprintTransformer() NaN \n", + " param_fp_transformer param_fp_transformer__fpSize \\\n", + "0 MorganFingerprintTransformer() 256.0 \n", + "1 MorganFingerprintTransformer() 256.0 \n", + "2 MorganFingerprintTransformer() 256.0 \n", + "3 MorganFingerprintTransformer() 256.0 \n", + "4 MorganFingerprintTransformer() 256.0 \n", + ".. ... ... \n", + "60 MACCSKeysFingerprintTransformer() NaN \n", + "61 MACCSKeysFingerprintTransformer() NaN \n", + "62 MACCSKeysFingerprintTransformer() NaN \n", + "63 MACCSKeysFingerprintTransformer() NaN \n", + "64 MACCSKeysFingerprintTransformer() NaN \n", "\n", - " param_regressor__alpha params \\\n", - "0 0.1 {'fp_transformer': MorganFingerprintTransforme... \n", - "1 0.325 {'fp_transformer': MorganFingerprintTransforme... \n", - "2 0.55 {'fp_transformer': MorganFingerprintTransforme... \n", - "3 0.775 {'fp_transformer': MorganFingerprintTransforme... \n", - "4 1.0 {'fp_transformer': MorganFingerprintTransforme... \n", - ".. ... ... \n", - "60 0.1 {'fp_transformer': MACCSKeysFingerprintTransfo... \n", - "61 0.325 {'fp_transformer': MACCSKeysFingerprintTransfo... \n", - "62 0.55 {'fp_transformer': MACCSKeysFingerprintTransfo... \n", - "63 0.775 {'fp_transformer': MACCSKeysFingerprintTransfo... \n", - "64 1.0 {'fp_transformer': MACCSKeysFingerprintTransfo... \n", + " param_regressor__alpha params \\\n", + "0 0.100 {'fp_transformer': MorganFingerprintTransforme... \n", + "1 0.325 {'fp_transformer': MorganFingerprintTransforme... \n", + "2 0.550 {'fp_transformer': MorganFingerprintTransforme... \n", + "3 0.775 {'fp_transformer': MorganFingerprintTransforme... \n", + "4 1.000 {'fp_transformer': MorganFingerprintTransforme... \n", + ".. ... ... \n", + "60 0.100 {'fp_transformer': MACCSKeysFingerprintTransfo... \n", + "61 0.325 {'fp_transformer': MACCSKeysFingerprintTransfo... \n", + "62 0.550 {'fp_transformer': MACCSKeysFingerprintTransfo... \n", + "63 0.775 {'fp_transformer': MACCSKeysFingerprintTransfo... \n", + "64 1.000 {'fp_transformer': MACCSKeysFingerprintTransfo... \n", "\n", " split0_test_score split1_test_score split2_test_score \\\n", "0 0.017975 0.394682 0.524598 \n", @@ -593,12 +608,13 @@ { "cell_type": "code", "execution_count": 6, + "id": "a6041579", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:08.447990Z", - "iopub.status.busy": "2024-04-12T12:11:08.446959Z", - "iopub.status.idle": "2024-04-12T12:11:08.691729Z", - "shell.execute_reply": "2024-04-12T12:11:08.691123Z" + "iopub.execute_input": "2024-11-24T09:28:28.324000Z", + "iopub.status.busy": "2024-11-24T09:28:28.323259Z", + "iopub.status.idle": "2024-11-24T09:28:28.574471Z", + "shell.execute_reply": "2024-11-24T09:28:28.573892Z" }, "lines_to_next_cell": 2 }, @@ -618,17 +634,20 @@ "# Best Fingerprint Method / Performance\n", "res_dict = {}\n", "for i, row in df_training_stats.iterrows():\n", - " fp_name = row['param_fp_transformer'] \n", - " if(fp_name in res_dict and row['mean_test_score'] > res_dict[fp_name][\"mean_test_score\"]):\n", + " fp_name = row[\"param_fp_transformer\"]\n", + " if (\n", + " fp_name in res_dict\n", + " and row[\"mean_test_score\"] > res_dict[fp_name][\"mean_test_score\"]\n", + " ):\n", " res_dict[fp_name] = row.to_dict()\n", - " elif(not fp_name in res_dict):\n", + " elif not fp_name in res_dict:\n", " res_dict[fp_name] = row.to_dict()\n", - " \n", + "\n", "df = pd.DataFrame(list(res_dict.values()))\n", - "df =df.sort_values(by=\"mean_test_score\")\n", + "df = df.sort_values(by=\"mean_test_score\")\n", "\n", - "#plot test score vs. approach\n", - "plt.figure(figsize=[14,5])\n", + "# plot test score vs. approach\n", + "plt.figure(figsize=[14, 5])\n", "plt.bar(range(len(df)), df.mean_test_score, yerr=df.std_test_score)\n", "plt.xticks(range(len(df)), df.param_fp_transformer, rotation=90, fontsize=14)\n", "plt.ylabel(\"mean score\", fontsize=14)\n", @@ -639,19 +658,20 @@ { "cell_type": "code", "execution_count": 7, + "id": "3ee14366", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:08.694324Z", - "iopub.status.busy": "2024-04-12T12:11:08.694077Z", - "iopub.status.idle": "2024-04-12T12:11:09.027663Z", - "shell.execute_reply": "2024-04-12T12:11:09.026932Z" + "iopub.execute_input": "2024-11-24T09:28:28.576983Z", + "iopub.status.busy": "2024-11-24T09:28:28.576761Z", + "iopub.status.idle": "2024-11-24T09:28:28.913143Z", + "shell.execute_reply": "2024-11-24T09:28:28.912512Z" }, "lines_to_next_cell": 2 }, "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAABIkAAAJGCAYAAADf3NUDAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAADQ9UlEQVR4nOzdd3gU5d7G8Xs3IQkBEgKBAKGEJsUChK4gRRAQEawcUYEoqCiCoEhROoKgIhYU5VCPBUSaooIYAUEQpamoCCgJNaEnEEoged4/eDOyZNM2ye4Gvp/r2gsy88zOb2fnmZm9d3bGZowxAgAAAAAAwDXN7ukCAAAAAAAA4HmERAAAAAAAACAkAgAAAAAAACERAAAAAAAAREgEAAAAAAAAERIBAAAAAABAhEQAAAAAAAAQIREAAAAAAABESAQAAAAAAAAREgF5ymazyWazafXq1Z4u5aq2evVqa1mjYFi7dq06duyoUqVKycfHRzabTV26dPF0WYDHtGzZUjabTaNGjfJ0KVc99s3eZe/evYqKilLFihXl5+cnm82m4sWLe7osXOU8sR2IiYmx5hsTE+O2+QK5RUgEZGDUqFHWhj2rB64eq1ev1qhRozR79myXps/uOuPs4eo8vd2PP/6o1q1b66uvvtKxY8dUokQJhYWFKSQkxNOlXZUuX6dq1aqVZfuff/7ZYZqePXvmf5FXmcuD66weBBVXj5iYGI0aNSrDoC8tCHTlcbX2w4SEBN1yyy2aPXu29u3bp8DAQIWFhSksLMzTpcFLXR60XPnw8/NTmTJl1LZtW73//vu6cOFCjp//5MmTVj8+efJk3r8AoADy9XQBQEGQ3YOXGjVqSJICAwPzs5xrXmBgoLWs89rq1as1evRotWjRwqWD9IzWldOnTyspKSnTNoULF87x/AqCKVOm6OLFi7rlllv0+eefq0SJEp4u6ZqxY8cObdiwQU2bNs2wzcyZM91Y0dUvJCREfn5+GY5PG1exYkXVqFFDoaGh7irtmpVf++aYmBiNHj1akpwGRWmB+JWSk5N14sQJSRmvL8HBwXlaq7f45JNPtH//foWEhGj9+vWqWbOmp0tCARIUFORwrJSYmKj4+HjFx8fr22+/1QcffKCVK1c6Pc7IaDtw8uRJqx/37NkzT89qK1SokDXfQoUK5dnzAvmNkAjIhri4uGy127FjRz5XAklq1KiR1y7rjNaVUaNGWQch2V2frha//fabJOk///kPAZEbRUREKCYmRrNmzcowJDp37pzmzZsnm82mihUrKjY21s1VXn0WLVqkli1bZtlu7ty5+V8MJHlu37xo0SKnw1evXq1WrVpZbbKzvlwt0vYHrVu3JiBCjr355pvpvsA7cOCAXnvtNU2ZMkVbtmzR0KFD9f7776eb1hPbgfDwcK89XgUyw8/NAAD56syZM5KkokWLeriSa0v37t1ls9k0f/586z240qJFi3Ty5Em1aNFCERER7i0QwDWH/QHyWnh4uN544w3ddtttkqQlS5Z4tiDgKkBIBOShjK45ceWF6+Lj49W/f39VrlxZAQEBCgsL03/+858sv22IjY3VY489pvLly8vf31/ly5dXVFSUdu/ena2L4yUnJ+vdd99Vq1atFBoaav2Wu3Pnzvr666+z9boOHz6sgQMH6rrrrlNgYKDDNZl69uxpXUvBGKNp06apUaNGCgoKUlBQkJo1a6aPP/44w/lcfiHXCxcu6PXXX1eDBg1UvHhxh+Wa2YWrZ8+eLZvNZn3g3bx5sx544AGVLVtW/v7+qlKligYOHGid6p8mbfmlne2zZs0at14zKLvL+MyZM/rkk0/UvXt31a1bV6VKlZK/v7/KlSunLl26ZPo+urpsLrdx40Y99NBD1rpbpEgRVapUSS1atNDYsWO1f//+dK8pbX2MiopyWJ5Xrqd///23+vTpo+rVq6tw4cIKCgpSZGSkxowZo8TERKf1XLkubN26VQ899JDKly+vQoUKWd/QX/na165dq06dOql06dIqUqSI6tWrpxkzZjg895dffqm2bduqVKlSCgwMVMOGDTV//vwMl02aH374QQ8//LAqVaqkgIAABQcHq1GjRpo4caJOnz7tdJor+85///tfNWvWTCVLlnR53atcubJatGihxMRELVy40GmbtJ+aRUVFZes5t27dqu7du1uvLSQkRDfffLOmTJmi8+fPO53mymW/atUqdenSRWXLlpWPj0+6b4W///57derUSaGhoSpcuLBq1KihF198UadPn073XJfzdN/IqcwuXB0REWG978nJyXr11VdVp04dFSlSRMHBwWrdurWWL1+e6fMnJSVp5MiRqlWrlgoXLqzSpUvrjjvuUHR0dLp5ZOTLL7/Uvffeq/DwcPn7+yskJES33nqr3nvvPSUnJ2f5ujLbjl+5zFeuXKkOHTqoVKlSKly4sK6//nqNGzdO586dczqftOsGpvXxhQsX6vbbb1fp0qVlt9sdlmt+7JsjIiKss4Eun0deXFMou8swNTVV0dHR6tevn5o0aaLy5cvLz89PJUuWVIsWLTRt2rQMr9GSF8cl+/fv14ABA3T99derSJEiVn+rX7++BgwYoJ9//jnda0pb3+bMmZPp/jUhIUFjxoxRZGSk9ROj6tWrq0+fPvrnn38yrCk7+9IrX3tsbKx69+6tihUrKiAgQFWrVtVLL71k/URckrZv366HH35YFSpUUEBAgKpXr65x48ZleQ2cmJgYPfvss7r++utVtGhRBQYGqmbNmurfv7/27t3rdJqcbjMzc/nyiIuLU9++fa33uEyZMnrooYeydaZLfm4L8krdunUlKcP9rLPtQMuWLVW5cmXr78qVKzusl1ee5bdjxw49/vjj1joVEBCgChUqqEmTJho2bFi6ZZnZsXlur0/myrEGkG0GgFMjR440kkxOukla+1WrVjkM37NnjzVu2bJlpnTp0kaSCQwMNP7+/ta4oKAgs23bNqfPvX79elOsWDGrbeHChU3RokWt6T799FNr3J49e9JNHxMTY66//nqrjc1mM8HBwdbfksyTTz6Z6euaPn26CQsLM5JMQECAVU+aHj16GEmmR48epmvXrkaSsdvtJiQkxNhsNut5oqKiTGpqarr5tGjRwkgygwcPNjfffLORZHx9fa3p05brqlWrMnxvZs2aZSSZSpUqmY8++sgUKlTISDLBwcHGbrdb011//fXm1KlT1nR79+41YWFhpkiRIkaSKVSokAkLC3N4zJs3z+nyyY6s1qfsLuO013f5exgYGOjwPj733HNO5+Hqskkze/Zsh/fR39/fBAUFOcx71qxZVvu05Zb23EFBQQ7Lc+/evVbb+fPnO/SFYsWKOfxdoUIF88cff6Sr6fJ14bPPPrNeU1BQkAkICDAtWrRI99qnT59u7Ha70z4wZMgQY4wxI0aMsNbfK9u89957TpdvSkqK6devn0PbokWLGh8fH+vvGjVqmJiYmHTTpvWd7t27m3vvvdeh79jtdoflmpXL34s5c+YYSaZVq1bp2sXExBibzWaKFStmkpKSrP7Xo0cPp887efJkh/c/ODjYWt6SzE033WQOHjyYbrrLl/2UKVOs50ib/vL5vfXW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NjZWPj4+WrZsmTp06JDuG05nZwbkJT8/P91zzz16//339dtvv+nIkSOaNm2aSpQooX379qlHjx45er7L14HMfg6RNs7X19flb+ryU1o/89ZTu8uWLav27dvr7NmzGj58uKTs/dRM+vc9Onr0qM6fP59hu7T3yJV+ffkBsSvbOW/oG94ibVlmthzPnz+f4Zml7l6Xjx49mulPNthfOHfhwgUtWrRIkvTOO+8oKirKYX8vyeHsufzSrFkzTZw4UevWrdPJkye1dOlS3XjjjTp79qweffTRbJ1Jk+by453s7A8k71wvvHF/kNlx2eXjLl+e3vg6slKpUiVJcvjZXF6y2+1q166d3nzzTW3atEnHjx/XRx99pIoVK+rEiRPq1q1bjn+CNmzYMH322Wfy8fHR/PnzrZ9GO1MQ3xMUTIREgJfz8/PT9ddfL0mZfiOQ0biIiAjrVOIvvvgir8tzatOmTdb1ja60e/du6wCvQYMGbqknJ9JO7fbGMw327dsn6dKHwIxOHU+7NoC7lCxZUk888YQmTpwo6dK1ZXJyYevIyEhrmaddL8eZtNdVp06dDC++7klp11z49ttvde7cOQ9X41zaBayTk5MVGhqqu+66K1vTpfXTixcvas2aNRm2S3uPMrp+R2bq1atnnfniynbOG/uGp6RdwySz9+qHH37QxYsXnY5LW5eXLVuW98U5cfHiRa1du9bpOGOM9Tq8eX8huX+fceTIEWtbU69ePadt1q1b59btUUBAgO666y4rvDp37pzWrVuX7en9/Px00003Scre/sBut+fZNXvyUlofiouLy/BaWu62atWqLMeVKFHC+qmZ5P5tQV5IO77M6LqCzuSmHxcrVkzdunWzLvIdHx+fozOqZ86cqVdeeUWS9NZbbzlcMN2ZgnCsgasDIRFQANx3332SLt154u+//043/tixY5o2bVqG06ddHHHGjBnaunVrpvPKiwtznj17Vq+99prTcePGjZN06WAk7eKT3iTtgtuXX9fEWwQHB0v69257V9q/f7/eeuutfJl3ZmeQSHK4M05OrqFQvHhx66Do1Vdfdfr7+V9++UULFy6UJD344IPZfm53evTRR+Xr66ujR4+muxvJlZKTkzMMUfNTp06dNGjQID333HOaMmVKtsO2m266yfpmc9y4cU4vVv7VV19p48aNklx7j0qUKGHdIef11193+k3s999/n2GY4Mm+4W3S9hcxMTFOf3JhjNH48eMznP7xxx+XJG3fvl3vvfdepvNKSkrKkwu3vvzyy0pNTU03fM6cOVYA2LVr11zPJ69dfoMGd+8zgoKCrGD1l19+STf+4sWLevHFF/Nl3hcvXnT6fqVxdX8gSf/5z38kSZ999pm2b9+ebvzp06c1adIkSdIdd9xh9X1v0qpVK+sC+AMGDMiyj7jjgugLFizQX3/9lW740aNH9f7770tK38c8sS3IjdWrV1t3HstJqJydfpzVa3Nlnf/uu++sO8v169dPTz31VJbTFIRjDVwdCImAAqBv374KCwvTuXPn1L59e61Zs8b6tmPTpk1q27Ztht8KS5dub3vjjTfq3LlzatWqld555x2Hsz1Onjypr7/+Wt27d8/VLabTBAcHa+zYsZowYYJOnTol6dKBSP/+/TVnzhxJ0vDhwxUQEJDreeW1tFvu/v7771q/fr2Hq3HUrFkzFSlSRMYYPfDAA9q5c6ekSz8pWLFihVq2bOnydUiyMm/ePN1yyy16//339c8//1jD0+addlv5pk2bKiQkJEfPPW7cOBUqVEi7d+9Wu3btrG/hUlNT9dVXX+mOO+7QxYsXVbVq1Ty/PXxeqVq1qvUzrkmTJql79+4OH3AuXryobdu2acyYMapWrVqmt6POL4UKFdKkSZP02muvOb01embSzhRbu3at7rvvPutU/gsXLuijjz6ygqGbb77ZuvVuTo0ePVo2m03bt2/XXXfdpV27dkm6tOwWLVqke++9N8N1y5N9w9s0b97cCuB79+6t2bNnWyHv/v379dBDD2nt2rUZXmS+RYsW1k8Rn376aQ0YMMChz58/f14//vijXnjhBVWqVCnDCwdnV2BgoNatW6du3bpZZwGcO3dOH3zwgfr06SNJ6ty5c4Z3ofKk6667zrob4X//+1+3nk1UtGhR66yCgQMH6rvvvrOCm+3bt+uOO+7Qpk2bcnRGRXbt379f1atX17hx47R161aH449ff/1VDz/8sKRLZ3NkdrdCZ/r06aPKlSvrwoUL6tChg77++mvrdf32229q166d9uzZI39/f+tLJ2/j6+uradOmydfXV+vWrdOtt96q6Ohohwtc//PPP5o2bZoaNmyod999N99rCggIUPv27fXtt99a6+nPP/+sNm3a6OjRoypWrJi1H0/j7m2Bq86fP6+lS5da+zVfX1/169cv29MXL17cOgN11qxZTo+n169fr5tuuklvvPGG/vzzT2udNMZo/fr11raqfPny1tlwmdm1a5fuvfdeXbhwQXfccYcmT56crVoLwrEGrhIGgFMjR440kkxOukla+1WrVjkM37NnjzVuz549GU5fqVIlI8nMmjUr3bi1a9eaokWLWs8TGBho/V28eHGzYMECa9yhQ4fSTX/gwAHTpEkTq43NZjPFixc3QUFB1jBJplq1atl+XVfq0aOHkWR69OhhunbtaiQZHx8fExISYmw2m/U83bt3NykpKemmb9GihZFkRo4cmel8Vq1aleF7M2vWLCPJVKpUKcPpM3s/Lly4YGrUqGGNDwkJMZUqVTKVKlUyCxYsyLSuzGS1PmV3Gb/33nsO71fRokVNQECAkWRCQ0PN559/nuFry82ySZs27eHv729Klixp7Ha7NaxcuXLmzz//TPecma3XaebNm2f8/Pys5woKCrJelyRToUIF88cff6SbLrN1IaevPe09atGiRYZtLl/Hr5SammqGDx/usK4XLlzYlCxZ0vj4+Dgsv3Xr1mX7eXMqbR6ZLW9n0vpfRjVMnjzZ4bUVL17c4T278cYbzYEDB9JNl51ln+aNN95wWE7Fixc3/v7+RpK54YYbrPE1atRIN62n+oYxjuthVn04TWbbu+z0mczWmUOHDpmaNWtaNRUqVMgUL17cSDJ2u9188MEHpmLFikaS+eSTT9JNf/78edOrV690yzMkJMShz0sy+/fvz/brutzly/ydd96x1q2QkBBTqFAh6/nr1Kljjh49mm767PTXNPm5b37ssccc9ssVK1Y0lSpVMs8991yGz5fV+pLdZbhp0yZTpEgRh+1ysWLFjCTj6+tr5s6dm2HtuXntl0+btp8vUaKEw/bAz8/P6T4zO9u63377zYSHh1vPFRAQ4HCs4u/vn+H+ODv9MDuvPTv7lqy2G4sXL7bej7R+WLJkSWublvYYN25cjp43J9LmMXPmTFOmTBlrPb38eNLf398sW7bM6fTu2BZk5fL3KygoyISFhVmPUqVKGV9fX4c+OG/evEyXhbN1Y+zYsQ7Lo0KFCqZSpUqma9euxhjH9eHy9/LyeQcFBZnvv/8+w9ozOqYKCQlxeE1XPvr16+fwnLk51gCyizOJgAKiWbNm+vXXXxUVFaVy5crp4sWLKl68uB599FFt2bJFVatWtdoWL1483fTlypXTunXr9Mknn+iuu+5S2bJldebMGSUnJysiIkKdOnXSlClT9P333+dJvZ988oneffdd1atXTxcvXlSRIkXUtGlTzZ07V3PmzMmz27rmNV9fX0VHR6tXr16qXLmykpKSFBsbq9jYWK84bffJJ5/Ul19+qZYtW6po0aK6ePGiwsPD9cwzz+iXX37RjTfemC/zveuuuzR37lxFRUWpTp06Cg4OVkJCgooVK6ZGjRpp7Nix+v3331WzZk2Xnr9r1676/fff9cQTT6hq1ao6f/68fH19VbduXY0ePVrbt29XrVq18vhV5S2bzaYxY8bo119/1VNPPaVatWrJx8dHCQkJCgkJ0c0336xBgwZp/fr11hkABcmAAQO0adMmPfzww6pQoYLOnDmjwoULq0mTJnrjjTf0888/Z3rb9ex49tlntXr1at1xxx0KCQnRuXPnFBERoZdeekk//vij9Q24s22cp/qGNypTpox+/vlnDR8+XDVq1JDdbpevr6/uuOMOfffdd+rdu7cSEhIkOV+Wfn5+mj59utavX6+ePXuqatWqSklJ0enTp1W6dGm1bNlSI0aM0K+//prj25w78/TTT2vFihVq37697Ha77Ha7atasqTFjxmjDhg0qWbJkrueRX6ZOnapRo0ZZ69fevXsVGxub7xeMlqT69evrp59+0gMPPKDQ0FClpqaqWLFieuCBB7R+/Xo98sgj+TLf8PBwff755xowYICaNGmismXL6vTp0/L19VXt2rX19NNPa/v27dZPH3Pqhhtu0O+//65Ro0apbt268vX11fnz51W1alU9+eST+v33311+bnfq0qWLdu/erZEjR6pRo0YqWrSoTp48KX9/f9WpU0e9evXS4sWLNWjQoHyvpXLlytq6dauefvpplSpVSsnJySpdurQefPBBbd26VR07dnQ6nbu3BVlJTEy0flYcHx+vo0ePKjAwUPXr19cLL7yg33//3aWfpg4bNkxvvvmmGjRooEKFCmn//v2KjY21bnjQsGFDffrpp+rTp4/q16+v0NBQJSYmKiAgQHXr1tULL7ygP//806Wz8U+cOOHwmq58pG2r01ztxxrwDjaTdsQFoECbPn26Hn/8cVWpUsXpdYvcoWfPnpozZ4569OiR4a1QAcBVDz30kD7++GM9+uij1oVCkXO7du3S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8olLIVGfPn20evVq+fj4SJJatmypefPmqVKlStq+fbvCwsL01ltvqXfv3nlaLAAAAAAAAPKHrysTBQUFqXHjxg7D7r//ft1///15UhQAAAAAAADcy6UziQAAAAAAAHB1yVVItHjxYj3wwAO66aabVK1aNWv4jh07NGnSJB04cCDXBQIAAAAAACD/ufRzs9TUVD344IP67LPPJEmFCxfW2bNnrfEhISF68cUXlZKSoqFDh+ZNpQAAAAAAAMg3Lp1J9MYbb2jBggV64okndOLECT3//PMO48PCwtS8eXN9+eWXeVIkAAAAAAAA8pdLIdHs2bPVsGFDvfvuuwoKCpLNZkvXplq1atqzZ0+uCwQAAAAAAED+cykk2r17t5o3b55pm5IlS+rYsWMuFQUAAAAAAAD3cikkKly4sBISEjJtExsbq+LFi7vy9AAAAAAAAHAzl0KievXqacWKFTp37pzT8cePH9fy5cvVpEmTXBUHAAAAAAAA93ApJOrXr5/279+ve++9V/v373cY9/fff+vuu+9WQkKC+vXrlydFAgAAAAAAIH/5ujJR586dNXjwYE2cOFGVKlVSkSJFJEmlS5fWsWPHZIzR8OHD1bp16zwtFgAAAAAAAPnDpTOJJGnChAlasWKF7rzzTgUGBsrHx0epqalq3769vv76a40ePTov6wQAAAAAAEA+culMojRt27ZV27Zt86oWAAAAAAAAeIjLZxIBAAAAAADg6pGrM4lSUlK0f/9+HTx4UBcuXHDa5tZbb83NLAAAAAAAAOAGLoVEqampGj9+vN58800dP34807YpKSkuFTZ16lS9+uqriouLU506dfT222+rUaNGTtsuWrRI48eP1+7du3XhwgVVr15dzz33nB555BGX5g3Afex+Aao0eJmnywAAAACAa55LIdHQoUP16quvqnTp0oqKilLZsmXl65urk5IczJ8/XwMHDtS0adPUuHFjTZkyRe3atdNff/2l0qVLp2tfokQJvfjii6pZs6b8/Py0bNkyRUVFqXTp0mrXrl2e1QUAAAAAAHC1cinZmTNnjmrUqKGff/5ZRYsWzeuaNHnyZPXu3VtRUVGSpGnTpunLL7/UzJkzNWTIkHTtW7Zs6fB3//79NWfOHK1bt85pSHT+/HmdP3/e+jsxMTFvXwAAAAAAAEAB49KFq0+fPq2OHTvmS0CUnJyszZs3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+Bs2bJhh3fmlbdu2at++vbp3765SpUq5dd55yVMfNLOLvpEz9I284+1946+//lKtWrVks9mUkpLilnm+/vrrevHFF3XhwgVJUkBAgF588UUNHTo03Xo2evRojRkzxm21jRkzRi1btnQ4/f7MmTPq0aOHFi1aJOnfi6iXKFFCs2fPVseOHd1Sm+R43Yt69eqpV69e6tatm4KCgtxWQ17xxLqXE57suwUxRL2SN4WABLwArhkGuMKOHTuMzWYzdrvdrfP99NNPTcmSJY3dbjd2u92UL1/efPTRR07bjho1yq31zZkzx/zyyy8Ow1JTU83zzz9v/Pz8rJrtdrupWbOm2bRpk9tqM8ZY75efn5+59957zddff21SU1PdWkNe8NS6l130jfToG+7h7X0jISHBzJ4928yePdst81uxYoWx2WymePHi5oknnjB9+/Y1ZcqUMXa73XTs2NGcO3fOob27+4XNZjOjR492GPbII48Ym81matasaV5++WXz/vvvm6ioKOPj42MKFy5s/vrrL7fW16xZM3PjjTda61WRIkVMjx49zJo1a9xWR144c+aMWb16tVm9erWnS3HKU333tddeM/7+/tb2NzAw0Lz88stOt3/u7h854e7lN3r06HR9ICkpydx3333WskyrJzQ01CxbtswtdaVJm7fdbjf169c37733nklISHBrDXnp0KFDJioqyjz66KNun+/ChQvN0qVLzfHjxzNst3r16nTbck/ZunWreeedd8zEiRPN/PnzTWJiottrqFatmunbt6/ZunWr2+ed1/bu3WtatWplWrdu7elSvBIhEdI5evSoGTlypBk1apTb5rlx40bj4+Nj/Pz8TLt27cydd95pAgICjN1uN08++WS69t5wwD9w4EBjs9lM6dKlTe/evc3QoUNNq1atjM1mMyVLljQHDhxwa3033HCDCQ0NtQ4gKlasaEaOHGliYmLcVkduufuDZk7RN9Kjb7iHt/cNd+vQoYMpUqSI2blzpzUsMTHRPPjgg8Zms5m2bduas2fPWuM83S/+/vtvY7fbTdOmTc2ZM2cc2i5cuNDYbDbzxBNPeKS+jRs3mt69e5ugoCCrj9SoUcNMmjTJxMfHu62mq5Un+q63h6g54e4QkIDXvTwRonpzgEpI6T7e/uWbpxESwSvce++9plChQmbdunXWsNjYWHPrrbcau91uevTo4bDx9vQB/4EDB0yhQoVM7dq1TVxcnEPbKVOmGJvNZp577jm315ecnGzmz59v2rZta3x8fIzNZjM+Pj7m9ttvN59++qlJTk52W03IG/SNvKmPvnF1CQ0NNd27d3c6bsiQIcZms5nbbrvNCoo83S9mzJhh7Ha7+e6775y2b968ualWrZq7ynP6QTgpKcnMmjXLNGvWzOEMvLvvvtt8+eWXBfIMvGuVt4eo3oyA1704C9URIaX7ePtZqJ5GSASvUKZMGXP//fenG37hwgXTrVs3Y7PZzMMPP2wdpHp6o/2///3P2O128/nnnzttHxkZaWrXru2u8pzuVGJjY83IkSNNxYoVHb51GDBggNm+fbvbakPu0Ddyh76Rd1JTU82ePXvMtm3bzLZt28yePXtMSkqKR2rx9/c3w4YNy3D8Sy+9ZGw2m2ndurU5c+aMx/vF+PHjjd1uNydPnnTavn///qZw4cLuKs9pv7jcX3/9ZQYNGmTKlClj9ZEKFSq4rT7kjreHqN6MgPfq5u0BKiElvIXd09dEguekpqYqISFBCQkJSk1N9Wgtx48fV/Xq1dMN9/X11Ycffqju3bvro48+0sMPP+zxWiVp//79kqSmTZs6Hd+kSRPFxsa6s6R0KlasqFGjRikmJkbLly/Xvffeq1OnTmnKlCm66aabdPPNN3u0Pm9G33AdfePqM3/+fLVp00aBgYGqWrWqIiMjFRkZqapVq6pIkSJq27atPv30U7fWFB4ergMHDmQ4fuzYsXrxxRe1atUq3XHHHTp9+rQbq0svODhY0qULRjvj4+OT4ThPuO666zRp0iTt379fixYt0h133KFDhw55uqwMDRo0SFWrVvXY/I0xiomJ0S+//KJffvlFMTExHt0enzp1KsNbYk+YMEEvvviivvvuO3Xs2FFnz551c3UFS3x8vCQpMjLS6fjIyMhMt0XuEBgYqJ49e2rt2rXasWOHnnvuOZUoUUJLlixRp06dVKlSJY/W501+/vln3XvvvQ7HVcWKFdPHH3+swYMH69tvv9Wdd96pc+fOebDKf61evVqS9PLLL6tw4cIO4+655x41a9bMYxd0b9SokT744AMdOnRIM2fO1M0336ydO3dqyJAhqlChgu655x599dVXMtwjq0Dy9XQBcK+NGzdq+vTpWrNmjcNBjM1mU+XKldWyZUs99thjatKkiVvrKlOmjI4cOeJ0nM1m06xZs2SM0f/+9z+lpqaqWrVqbq3vSmkb6iJFijgdX6RIEa/4wC5dWn633367br/9dh0/flxz587VjBkztHHjRk+X5tTEiRO1YsUKfffdd26dL30jb9A38o+7+8bFixd1//336/PPP5cxRjVq1FD16tWtO2AlJiZq165dio6O1nfffadPPvlECxYskK9v/h9a3HDDDVkeGI8dO1bSpYPr9evX53tNV1qyZIliYmIkSQcPHpQk/f33307vSLR//36Fhoa6sbrs8fHxUZcuXdSlSxevDomOHj1qLWt3mj9/vqZPn64ffvhBycnJDuP8/PzUrFkz9e7dWw888IBb68pOiCpd6ht33HGHGjRo4K7SXDJo0CAtWrRIf//9t9vnXVAD3gkTJuiLL77QjBkztHz5co/WZIxRbGysEhISJF1aphUrVvTIcssqQPX19dXLL7+sjh07atmyZW6uLr3shJQffPCBO0tKJy2k7Nmzp3bu3Kn//ve/+t///qclS5Zo6dKlCg8P1969ez1aI3KOkOga0r9/f73zzjsyxqhIkSKqVauWw8H+nj17NGPGDM2cOVPPPPOMpkyZ4rbaatasaaXlzthsNs2ePVuS9L///c/ttxyV5FDfzp07JUkxMTGqVatWurb79+9XyZIl3VVatpUoUULPPvusnn32Wf3888+eLsepHTt2aM2aNW6dJ30jd+gb7uHuvjFp0iQtXbpU//nPf/TKK6+oYsWKTtvt3btXQ4YM0fz58/Xqq69q6NCh+V5bx44d9cUXX+jLL7/M9NbxY8eOlc1m07hx46xbvrvLtm3btG3bNodhS5YscRoSbdiwQTfeeKN7CnNR2bJlPV2C1/DmAFUqGCFqTrg7BCTgzRveGKIWtACVkDJ/eTKA9naERNeIadOm6e2331bz5s01duxYNWvWLN1GJTU1VWvXrtXw4cP19ttvq1atWnriiSfcUl+HDh00cOBArV27Vs2bN3faJu3DsM1m09y5c91+wL969ep0H9aXLVvm9IPwpk2bVKNGDTdV5pqGDRt6ugSvQN/IPfrG1Wnu3Llq2rSpPv7440zbVaxYUR9//LH27NmjOXPmuCUkuu+++6xQNytjxoxRlSpV3Pozxz179jgdHhgYmG7Ytm3bVLVqVd177735XZZl1apVioiIcNv8curRRx/NUft169blUyXOeXOAKhWMENWbEfDmjjeHqAUhQCWkdB9PnYVaEBASXSOmTZtmbRgz2gjb7Xa1aNFC0dHRioyM1Hvvvee2D8IPPPCA4uPjdezYsUzbpf28JiIiwq0H/KtWrXI6vFSpUumGbdmyRRcuXFC7du3yuyzLrFmznO48vMGYMWNy1P7KA7P8Rt/IHfqG67y9b8TGxuqee+7JdvuWLVu67Sy7EiVK5KgP9uzZM/+KcSIn1wCpW7duhv0ov7Ro0cKt88uptNA7J9eycGfI4c0BquT9Iao3h4AEvLnnzSFqQQhQCSnhDWyGq0ldEwIDA9W/f39NmDAhW+2HDBmit956S2fOnMnnynC1s9vtLh3sp6Sk5GNV/6JvwFO8vW+UK1dOzZo1y/ZFqe+//3798MMP1jefgKuKFy+u8PBwzZw5M1vtx44dq6+//tptfaNw4cIaMGCAxo8fn632Q4cO1ZQpU7hI9P/z9m0fcqdmzZoqWbKkfvjhh2y1b9q0qU6cOKEdO3bkc2WXbgayYMEC1ahRQy1btsyy/ezZsxUbG6uRI0fme22SMgxrAwMD0335tm3bNg0YMECPPPJIjoNXV61Zs0YRERFeezH0nC6HtWvX6p9//mHb4gRnEl0jihQpkqPT/Q4dOpStb6CArAQGBio8PDzbZ0289957Wrt2bT5X9S/6BjzF2/tGhw4dNGfOHE2fPl29e/fOtO3777+vxYsXKyoqyk3VXZKYmKjY2FhVqVLFoV+uWLFCq1evVqFChdShQ4cM77Z3rXr55ZfVrl07j19vIyORkZH6+eef1ahRo2x9i+/szMX8FBISot27d2e7/e7duxUSEpKPFRUsQUFBLoWAKBg4C9V1nIWaO95+FmpBQkh0jWjVqpXmz5+vbt266fbbb8+07fLlyzV//nx17tzZTdU5OnXqVLqL7/7xxx9au3atChUqpDZt2mR46uq16qOPPtJtt92mMmXKeLqUdOrWravff/9dXbt2zVb75cuXu/WDMH3j6kbfcN3LL7+slStX6sknn9SkSZPUtm1bVa9e3bqQZkJCgnbt2qWVK1fqn3/+Ufny5TVu3Di31TdhwgSNHj1aFy5cUGBgoN5++2317NlTzz77rN5++23rIPHll1/WoEGD9Morr7ittpyIi4vTsGHDZLPZNGPGDLfMc/jw4RoxYoRuuukmPfbYY3r44YdVvHhxt8w7OyIjI7VmzRrt2LHD6bXNPK0gBKiS94ao3h4CejNvD3glQlR4DgF0HjK4JuzcudMEBwcbu91u2rRpYyZOnGgWLVpkoqOjTXR0tFm0aJGZOHGiue2224zdbjchISFm586dbq3xww8/NGXKlDF2u91ERESY5cuXG2OMef31142vr6+x2+3Gbrcbf39/M3XqVLfWlhNHjx41o0ePNmPGjHHbPG02mylUqJDp0qWL+eKLL0xKSorb5p2VZ555xtjtdrN79+5ste/Zs6ex2+35XNW/6BvuQ99w5O19wxhj4uLiTPfu3U1AQICx2WzGZrNZ61va3/7+/qZHjx7m0KFDbqsrOjra2Gw2ExYWZu655x5Trlw54+fnZz766CNjt9vN008/bZYuXWreffddU6FCBWO3283KlSvdVl9O7Nixw1qu7mKz2UzRokWt+RYuXNg89NBDZtWqVW6rITPff/+96dmzp9m8eXO22q9bt87Mnj07n6v616FDh6z1qlq1aqZPnz5m8uTJZsaMGWbGjBlm8uTJpk+fPqZatWrGbrebihUrmri4OLfVZ4wx48ePN/7+/sZut5uiRYuaWbNmGWOM6d+/v0P/tdvtZvDgwW6t7bnnnjN2u9388ccf2WrviW1fdhw6dMhERUWZRx991G3zTHvP6tata95++21z4sQJt807ux599FHj4+NjPvjggyzbTps2zfj4+JhevXq5obJ/JSQkmF9//dWcPn3aYfjy5cvNkCFDzPDhw8369evdWlNBMG7cOPPzzz97uowMtWrVyhQtWtSkpqZmq723blu8ASHRNeT33383t956a7oD/SsP+Fu0aGF+//13t9a2adMm60A1MjLSFClSxBQtWtSsXLnS+Pj4mI4dO5o333zTvPDCCyY4ONj4+PiYn376ya01ZpenDvjT3kO73W7Cw8PNiy++aP7++2+31ZCRL774wrRs2dKsW7cuW+2XLFliRo0alc9VOaJvuAd9w1FB6BtpTp06Zb755hszdepUM378eDN+/HgzdepU880335jExES313PnnXea4sWLW8HU0aNHTalSpUxQUJB54YUXHNrGxMQYf39/c//997u9zuxISEgws2fPdmvIYbPZzOjRo83mzZtNnz59TPHixa0+UrVqVTN+/Hhz8OBBt9VTEHlrgGqM94eo3h4CZhcBr3PeHqJ6c4CaE4SU6V0t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c0+227ds2dKrz7BDweLtIao3I+C9unl7gEpICW/hfT9oBLzQzp071bFjx2wl9YUKFVLHjh21c+dON1QGeBZ9A0gvJCREu3fvznb73bt3KyQkJB8rApAdsbGxatGiRbbbt2zZMt3Pl+C9rrvuOt17771ZBkTSvwFqTgL/3Lo8pMwoIJL+DSkbNWrk1p9zzZo1S3fddZfb5gfPISQCsqFIkSI5uq34oUOHVKRIkXysCPAO9A14u7i4OD366KN67LHH3DbPDh06aNGiRZo+fXqWbd9//30tXrxYHTt2dENlOeeJ5Qd4CgEvPImQEt6Cn5uhwDl27JimTp0qm82m4cOHu2WerVq10vz589WtWzfdfvvtmbZdvny55s+fr86dO7ultpzyxPKDe9A3coe+kfciIiJ06623erSGhIQEzZ49WzabTTNmzHDLPF9++WWtXLlSTz75pCZNmqS2bduqevXqCg4OtmratWuXVq5cqX/++Ufly5fXuHHj3FJbTnli+eUFb1j3CoK4uDgNGzaswL2/+aVDhw6aM2eOpk+frt69e2faNi3g9dbbZfPeFjyElPAWNmOM8XQRKBimTJmiN9980+3XPLnSX3/9pVq1aslmsyklJcUt89y1a5caNmyoU6dOqXXr1hke8H/zzTdatWqVgoODtXHjxgwvhOdJnlh+ueUt615GvKU++kbu0DdyJjExUWfPnlWpUqW88na8aRITE7V48WJJl66n4C7x8fF64YUX9Omnn+r8+fOSJJvNJunSbY2lS3epSbv2RJkyZdxWW054avllpqCse5mZM2eOZs+e7fHrARXE7Z6Uf8svLi5OjRo10oEDB1SlSpVsBbw//fSTR+6AlZWC+t5K0ujRozVmzBiP1u2JkO2xxx7TnDlz9N5772UrpHz66acVFRWVrbNW3a2ghpTesO55A0IiFDjHjh3T22+/LZvNppEjR7ptvn/88Yf69OmjtWvXSvr3YD9NWle69dZb9e6776p27dpuqy0nPLX8kP/oG7lD33B04MABxcbGqkmTJg4fxN9//329/vrr+vvvvyVd+snhPffco0mTJql06dKeKtdrnT59Whs2bNCuXbuUkJAgSQoODlb16tXVpEkTFStWzMMVep+rYd07c+aMChUqlK1rn3iSN4aAkmeXHwGv53lDiOqJkI2Q0vO8Yd3zBoRE14ikpCQlJCSoXLlyDsNXrFih119/XZs2bdLZs2cVERGhrl27avDgwSpcuLCHqvVuu3bt0urVq50e8Ldo0SLbdxS5VhSkde/48ePy9fW1bjXqzN69exUTE8PPGJygb7jOG9e9bt26acOGDQ5nKb3wwgt6/fXXZbPZVKVKFRUvXly7d+/WyZMnVblyZW3cuFGhoaFuqe9q9+uvv2rbtm3q3r27p0txu4Kw7v3xxx+aPHmyjhw5ojZt2ujpp5+W3W7XsmXL9Nxzz2n37t2y2+26+eabNXnyZNWvX99ttRUEBWH5EfDmn88//1wRERG66aabPF1KhjgLNXe8NaQsCOueVzC4JkRFRZkyZco4DHvjjTeM3W43NpvNBAQEmFKlShmbzWbsdrtp2LChSUpK8lC1V6fY2FizZs0aT5fhdgVh3Vu7dq254YYbjN1uN3a73TRp0sR8//33TtuOGjXK2O12t9Z3tbtW+4Yx3r3uVa5c2fTo0cP6e/fu3cbHx8fUrl3bbN++3Rp+4cIFM2bMGGOz2Uy/fv3cVt/lUlNTzZ49e8y2bdvMtm3bzJ49e0xKSopHaskr7ny/vW35efu6988//5jg4GBjs9msfdczzzxj1q9fbwoVKmQCAwNNZGSkqVChgrHZbKZo0aJmx44dbqvP213ty++XX34xc+bM8XQZXs1ms5nHH3/c02V4tVOnTplvvvnGTJ061YwfP96MHz/eTJ061XzzzTcmMTHR0+UVWKx72UNIdI247rrrTLdu3ay/Dxw4YPz9/U14eLj5+uuvTWpqqjHGmCNHjphevXoZm81mXnrpJU+Va4wxJiUlxZw8edKcPHmywB/sG+P+D3jesvy8fd3bsWOHCQwMNDabzdSoUcPccMMNxmazGV9fX/PKK6+ka+8NIZG3vLd55VrtG96+7gUEBJihQ4daf0+bNs3Y7Xazbt06p+1vu+02U6lSJTdVd8m8efPMbbfdZgICAqygLe0REBBg2rRpY+bPn+/WmvKKO95vb11+3r7uPfHEE8Zut5s33njj/9q787goq/0P4J/nGRiQNcQF4arAFbdAEa+Ky2VxxfQqUlpaApZrhjvghoD9UrFcKm1REcW6LWSlleVSqECJdU20kgQRxCUzDVlFgu/vDy5zHRkQlXnmDHzfr9e8Xs15jjPfvucwPPPlec6hrKwsWr9+PanVavLx8aE+ffrQb7/9pun75ptvkiRJWkUvpYlWBDS2/N2v5lzgJSJKT0+/50OSJAoMDNRqY42jORcpee41Hi4SNRMWFha0ePFizfPt27eTLMu0b98+nf379etHbm5uSoWncezYMXruueeoU6dOZGJiojlZValU1KlTJ5o6dSp99913isfVGJQ4aRAxf6LPveDgYJIkSeuLUHp6OnXt2pVkWa5VsDJUkUjEsW0szfVnQ/S5Z29vTy+88ILm+Zo1a0iW5Tqv9Fu0aBGZmZkpEltFRQUFBgZqrkjs2rUr/etf/6Knn36ann76afrXv/5FXbt21VylEBgYSBUVFYrE1lj0Od6i50/kuUdE1KVLFxo5cqRW24gRI0iWZUpLS6vVf8iQIdS+fXulwtMQtQhoLPl7UM25wEtEms+N+30YgohFtofVnIuUxjT3RGdi6NvdmDLUarXmvlag+n5XAHWubTFo0CBs2rRJkdhqzJ07F5s2bQIRwdLSEt26ddOsz1FYWIjz588jPj4e27dvR1hYGDZu3KhofKITNX+iz73k5GQ89thjmDBhgqatb9++SE9PR2BgIFatWoXKykqsWrVKsZjuJurYGgtR8yf63OvVqxf2798PIoIkSZod6TIzM+Hl5VWrf2ZmJuzt7RWJbe3atdizZ49mTYYOHTro7HfhwgUsXrwYH3zwAV5++WUsWbJEkfhEJ3r+RJ57AJCfn49x48ZptXl6euLgwYPw9PSs1d/Ly0uzsL8S/vrrL4wfPx579+4FEaFLly5wc3PT+tzLysrC119/jW+++QbvvfcekpKSYGKizNcC0fMnMtHHtoalpSUCAwOhUqlqHSMiJCYmws3NDQMGDFA0rhoffPABtm7dirS0NNy+fVvrmFqtxqBBgzBt2jSt38/sf0TOn+hzz2gYqjrFlDVo0CDy9PTUPH/nnXdIluU67/F+8sknqXXr1kqFp7mc2MfHh44cOaKzCl1ZWUmHDx+mf/7znyTLMr311luKxdcY9FnZFzl/os89tVqtdaXTncrKymjYsGEkyzJFRkYSkfJXc4g8to2luf5siD73Pv74Y5IkicLCwqiyspLKy8upS5cu5O3trXU7CBHRtm3bSJZlevbZZxWJrUuXLjRgwIAG9/f29qYuXbroMaLGp8/xFj1/Is89IqJ27drR888/r9U2a9YskmWZLl26VKv/tGnTyMrKSqnw6KWXXiJJkmjixImUl5dXZ7+8vDyaOHEiybJMq1atUiw+0fP3sPT5syv62BJVX/lnbm5O/fv3pzNnzujsI0kSTZs2TdG4iMS/irIxNOerUEWee8aGi0TNRHx8PEmSRC+//DIRVS+G5ujoSKNGjaKysjKtvgcPHiRTU1MaP368YvH17NmTPDw8GvRBcvv2bXJ3d6eePXvqP7BGpM8PbZHzJ/rcc3R0rHWyeqdbt25pvqyHh4cr/kVd5LFtLM31Z0P0uUdENH36dJIkidzc3GjRokUUERFBJiYmZGlpSb6+vjR27Fjq3LkzybJMDg4OdPHiRUXiunvNmntZvHgxmZub6zGixqfP8TaG/Ik694iI/Pz8yMnJiYqKioiIqLCwkBwdHcnGxobWrl2r1ffmzZvUtm1b6t27t2LxiV4EFD1/D6s5F3hrnD59mry8vKhFixYUFxenWX+yhqG+qBtDke1hNfcipahzz9hwkaiZqKqqotGjR5Msy+Tn50ebNm2iF198kUxMTMjJyYlCQkJo7ty5mi8kVlZW9MsvvygWX4sWLer8i7oukZGR1KJFCz1G1Pj0+aEtcv5En3s+Pj7Uo0ePevvceVWHo6Ojol/URR7bxtJcfzZEn3s1Nm7cSC1bttT8ZbBmR6I7HyNGjKBz584pFlO7du3uq5j8xBNPULt27fQYUePT58+FseRPxLlHRLR7926SJIlcXV3pmWeeIRcXF1KpVPThhx+SWq2mRYsW0eeff04JCQnk4eFBsixTXFycYvGJXgQUPX8Pq7kXeGtUVFRQdHQ0mZqaUr9+/bTO7Qz1Rd1YimwPg4uUYs49Y8NFomakvLyc5s2bR6amppqFuu7cfrTmv7t37674Su+tWrW6r50rgoODqVWrVvoLSA/0+aEtev5EnnsvvfQSybJMJ0+erLdfzZf1mpiVIvrYNobm+rMh+ty7O4Y9e/bQihUraObMmTR9+nQKDw+nbdu2Kf4FnYjo2WefJZVKRVu2bLln37feeotUKhVNnTpVgcgajz5/Lowpf6LNvRoLFiwglUpFkiSRmZkZbdy4kYiIYmNjtRZPlSSJfH196fbt24rFZgxFQJHz97C4wKvtP//5Dz366KNkbm5OL730Ev31118G+6JuTEW2B8VFyv8Rae4ZGy4SNUOXLl2ijRs3UnBwMAUEBNDw4cNp/PjxtHz5cvrmm28Msir9+PHjydzcnPbv33/Pvl9++SWZmZnRhAkTFIis8ejzQ9tY8ifi3MvKyqKnnnqqQduF3rp1i0JCQsjPz0+ByKoZy9g+jOb6syH63BPZlStXqH379iTLMnXq1IlmzZpF69evp/j4eIqPj6f169fTrFmzqFOnTiTLMnXo0KHWWjai0+fPRXPInxJ+++03OnbsGF2/fl2r/eDBg7Rw4UIKCwuj999/X/HfbcZSBBQ1fw+LC7y1lZeXU0REBKlUKvLy8iJZlg3yRd0Yi2z3i4uU2kSZe8ZGIiIy9OLZjGVlZaFPnz4oKirC4MGDMWzYMLi5ucHW1hYAcPPmTWRlZeHAgQNITk6Gra0t0tPTNTueGIPY2FisXLkSlZWVjf7azSF/zVVzGFv+2WAP4urVq4iIiMCHH36o2UFRkiQA1TuYANW7rNTs4OXg4GCwWB/Ezp07sWPHDiQnJ+vl9Zt6/pqz3377DX379sWlS5fg6upa5+fewYMHkZOTg7/97W84fvw42rZta+DImwZ9/k4z9rH97rvvEBISguzsbEydOhVbtmxR9P2fe+457Ny5E2+++SamTZtWb9+3334bs2fPxpQpU7B161aFInx4+px/xpw/Q889Y8NFIiaMX375BbNmzdJsc1pzslqjZqr6+PjgjTfeQPfu3RWP8WFs3LgRr776Ks6fP6+X12/q+WvOmvrY8s+G+HJzc5GcnIyzZ8+ioKAAsiyjTZs2+Mc//oFhw4ZBrVYbLLbi4mJ89913yMrKws2bNwEAtra2cHNzg7e3N6ytrQ0WW10KCwtRVlaG1q1bQ5Zlg8Yiev5Ennsi4yKg4XCBt36VlZUoLi6GmZkZzM3NFX1vYy+yNQQXKetmyLlnbLhIxABUnySWlpaiVatWBj9hzcrKwuHDh3WesPr6+qJz584GjU90xpY/keZeQ9y4cQPFxcXo0KGD4u9tbGMrGmPPnyHm3vnz5zF79mzs37+/1jEigiRJsLe3R3R0NGbPnq1YXI3h1KlTOHnyJIKDgxv9tS9duoS8vDx4e3trfa69/fbbWLduHc6dOwcAsLS0RFBQENauXYs2bdo0ehz6pM/8AcY/91q2bImQkBBs2LDBoHGIXgSsiyj506W0tBSmpqYwNTU1aBzGOraGZuxFtnvhIiVrFErf38YMIy8vj27evFmr/bPPPqOePXtqFgi0tramqVOn0o0bNwwQ5cPJy8ujI0eO6OW1i4uL6dKlS7Xav/rqKxo2bBjZ2dmRubk5de3alaKjo6m0tFQvceiTvvLX1OZeaGgoqVQqQ4dxX/T5s3Gn69ev6xxrQ8TSmESJWem5l5+fTw4ODiRJEvXq1YuCgoKoV69eJEkSeXp60iuvvEIhISFkb29PsizTzJkzFYutMehz3YaJEyeSs7OzVlt4eDjJskwqlYrc3NyoT58+ZGdnp9nl6dq1a3qJRV/0mb+mMPeMfXHUjIyMBq2Xpi+GzN/PP/9Mzz33HI0ZM4Zee+01zZpIn332GXXu3JlkWSYTExPy8fGhH374wSAxPgxDj60oioqK6MCBA7R582ZatWoVrVq1ijZv3kwHDhygwsJCQ4dXpz179lBGRoahwzDa/LGG4SJRMyHLMq1cuVKrLTExkVQqFcmyTG5ubtS/f3+ysbHRnITdunXLQNE+GH2esE6ZMoUcHBy02jZs2KDZecPc3Jxat26t2ZGjT58+VFJSopdY9EVf+Wtqcy80NNRgO0w9KH3+bBARpaSkkLu7u6bg5+3tTUePHjVILPogSsxKz70pU6aQLMv00UcfabXv3r2bVCoVbd++nYiqTxTHjx9PsizTJ598olh8D0uf4+ri4qK1q152djapVCrq3r07/fTTT5r2iooKWrlyJUmSRHPmzNFLLPqi79+5Is+9bt263fMhSRLZ2dlpnnfv3l2x+BqDPsdX5Pzl5OSQra2t1g6sYWFh9O2335KpqSlZWFiQl5cXtW/fniRJIisrK8rMzFQktsaixO+033//nV544QXy8PCgXr160eLFi2stUH5nPMb0xzdDF9kkSaLp06cb7P0flr7z15TnnpK4SNRMSJJEsbGxmufFxcVkZ2dH9vb29PXXX2vaS0pKaOLEiSTLMq1bt84QoT4wff7S69y5M02aNEnz/NKlS2RmZkZOTk705ZdfUlVVFRERXbt2jaZOnUqSJNHy5cv1Eou+6Ct/TW3ucZFIW2ZmJllYWJAkSdSlSxdyd3cnSZLIxMSE1qxZo2gs+iJKzErPPUdHRxo3bpzOY0FBQeTu7q55Xl5eTh07dqShQ4cqFd5DU3Kb4LfeeotkWabU1FSd/YcMGUIdO3bUSyz6os/8iT73aooHNYUEXQ9dx42JPsdX5PzNmDGDZFmmDRs2UFZWFq1fv57UajX5+PhQnz59tHb5e/PNN0mSJK2CsDHQ9++0goICzc6Id45fu3btdF6VK8rv2IbSZ7zp6en3fEiSRIGBgVptxkSf+Wvqc09J4i8AwvTi0KFDKCgowMqVKzF48GBNu4WFBbZv3w4nJyckJSUZMEKxXLx4UWsdkP3796OiogJbt25FQECA5l7cVq1aYevWrejbty8++OADQ4UrNNHmnqur6309du/erVhsxmDVqlUoKyvD+++/j8zMTJw+fRrHjh1Dp06dsHTpUkRFRRk6RGGJPvf++OOPOnd569SpE7KzszXP1Wo1Ro0ahRMnTigVntAsLS1RVFSkeV5QUAAA6NWrl87+vXr1wm+//aZEaEZB9LnXo0cPWFpaYvPmzaiqqtL5ICJMnTpVq41VEzl/hw8fxogRIzBv3jx06tQJ8+fPh7+/P1JTU7Fx40atBXhnzpyJwYMH45tvvlEkNmOxevVqnDt3DjNnzsTly5dx7do1rFmzBoWFhQgICMCXX35p6BCF5e3tjf79+9f7kCQJe/fu1Wpj1XjuNR4TQwfADCMrKwuSJGH06NG1jpmbm2Po0KH4+OOPDRCZmNRqtWZxNqB60TagejckXQYNGoRNmzYpEpuxEW3u5ebmQpblBi9AWVFRoeeIjEtycjIee+wxTJgwQdPWt29fpKenIzAwEKtWrUJlZSVWrVplwCjFJPrcc3BwwKlTp3QeO3XqlGY3kxo2NjYoLS1VIjTh9erVC/v379cssFxT8MjMzISXl1et/pmZmbC3t1c6TGGJPve+//57xMTEYM6cOfjoo48QHx8PZ2dnxd7f2Imcv/z8fIwbN06rzdPTEwcPHoSnp2et/l5eXpqdM1m1PXv2wMvLC5s3b9a0RUREYPjw4Rg1ahSCgoKQlJSk8zyQVf+RITAwECqVqtYxIkJiYiLc3NwwYMAAA0QnNp57jYevJGqmav4iU9eK823btkVZWZmSIQnN3d1da5eA9u3bA6i+wkiXixcvwsbGRpHYjI1oc8/R0RGPPvooysrKGvR45plnFIvNGFy9ehUeHh612m1sbLBv3z4MGTIEcXFxWLx4sQGiE5vocy8gIAAHDhzQOtkCgDfeeAMHDhyAv7+/Vnt+fr4w29wa2vPPP4/s7GzMnTsXVVVVGD16NNzc3DB79mzNHxlqxMfHY9++fQgICDBQtOIRfe6ZmpripZdeQlpaGi5fvgwPDw/+w9B9EDl/tra2KCws1GqreV5zReCdCgoKoFarlQjNaOTm5sLPz69Wu6enJ1JSUtCmTRs88cQT2Lt3r/LBCW716tWoqKhAdnY2IiMjkZCQoPXYsWMHAMDX11ernVXjudd4uEjUjOTm5uLo0aM4evSo5qqYK1eu6Oz722+/wc7OTsnwhDZlyhRkZGTglVdeAQCMHTsWDg4OWLhwIW7duqXV99ChQ/j44491fkg1VyLPvd69e+PMmTNaV4rVp+bWQlatVatWtU6oa5ibm+Ozzz7DkCFD8PLLLyMiIkLh6MQm+txbsWIFWrVqhTlz5sDR0RH9+/eHo6MjwsLCYGVlhdjYWE3fyspKHDx4EN7e3orGKKpx48Zh2rRp2LRpE7p27Yply5Zh7Nix+OGHH/D3v/8dfn5+CAwMRJcuXTB9+nS0adMGK1euNHTYwjCWude3b1+cPHkS06ZNw7x58+Dr64tz584pHoexEjF/Xbp0wZ49e1BcXAwAKCoqwp49e2BlZYV3331Xq29hYSH27t2LLl26GCJUYVlaWmq2Qr+bq6srDh8+jLZt22LChAnYs2ePwtGJLTIyEt9//z3Ky8vh5eWFtWvX1plLVhvPvcbDRaJmZOfOnfD394e/vz+io6MBVN97rcuZM2eEufRXBFOmTMGoUaMQGRkJf39/7Ny5E7NmzcL+/fvRqVMnhIaGYt68eRg+fDhGjBgBMzMzrZPY5k7kuderVy/89ddfyMjIaFB/ql7wX89RGY9OnTohNTW1zuNmZmbYu3cvhgwZgnXr1mHLli0KRic20eeek5MTvvvuO4wcORJ//PEH0tPTce3aNfj5+SElJQWdO3fW9K2oqMDHH3+Ml19+WbH4RPf2229jw4YNuH79OtatW4dXXnkFlZWVKC0txdGjR7F3715kZWVh2LBhSEtLg5OTk6FDFoYxzT0zMzOsX78e33zzDS5evIgePXpg/fr1BonFGImWv7CwMFy+fBk9e/bE5MmT0bNnT1y9ehXbtm3D8uXLER4eji+++AI7duzAoEGDcO3aNa3brRng7OyMH3/8sc7jLi4uSE5O1nxZP3DggILRic/d3R3p6emIiIjA8uXL0b9/f5w5c8bQYRkFnnuNh9ckaiZqvpjf7ZFHHqnVlpWVhe+//x6zZ8/Wc1TGQ5Ik7N69G5GRkdi8eTOOHj0KoPpL2+XLl7Fr1y7Nl7du3bohISEB3bp1M2TIwhB97gUHB8PFxQVt2rRpUP9169ZxAfAOI0aMQFRUFDIyMtCzZ0+dfczNzbF3716MGTMGhw4d4qux/ssY5p6rqys+//xzlJeX4/r167Czs0OLFi1q9TM3N8fAgQMVjc0YzJ07FzNmzMCBAwfwn//8B7///juqqqpga2uLLl26wN/fH66uroYOU0jGNvd8fHxw+vRpLFy4EIsWLTJ0OEZHlPwFBQVh/vz5ePXVV3H+/Hmo1WqsW7cO48ePx5kzZxATE6MpYhERfHx8MH/+fIPFKyJfX1+8/vrruHr1ap23gbq6uiI5ORn+/v747rvv+LzgLiYmJoiJicGYMWMQHBwMLy8vREVFITIy0tChCY3nXuPhIlEzUdcXdV3atWuHnJwctGzZUo8RGR+1Wo0NGzYgPDwcSUlJOHHiRK0T/sGDB8PX1xeyzBfp1RB97tXsHNVQ9vb2vMDsHSZMmIDTp0/XWyQC/nfr2YwZM5CXl6dghOIyprlnZmYGR0dHg7y3vjg7O9e5+UBjMjc3x5gxYzBmzBi9v5eSlMqfMc09CwsLvPnmm3jyySeRkZEBd3d3Q4dkVETJ37p16xAREYHc3Fy4ublpzklWrFiBAQMG4KuvvsLt27cxcOBAjB8/ns/57hIUFIR///vfSExMRHh4eJ39am7/8ff3R35+voIRGg8vLy+cOHECUVFRWLFiBXbv3s1FjXrw3Gs8XCRitVhZWcHKysrQYdw3W1tbrW3q9cXR0RFz587V+/soTan81cdY557o9Dm2nTp1wnvvvdegvmZmZppFF42JCD8bIrh06RKysrJw8+ZNANV5cXNzE/I2qcLCQpSVlaF169Z1foELCQlBSEiIwpEZB9HyZ0xzDwD8/PyMfl1CpYqAuoiQv7Zt2+q8EmHo0KEYOnSoASJqPPoe24EDB9a57uTdXFxckJubq7dYmgK1Wo24uDgEBgYiJCSElzyoB8+9xiMRz7RmpaKiAqdPn4aJiQk8PDzqrEafOnUKJ0+eRHBwsMIRsqbK2OZeSUkJtm7dirS0NJSUlMDZ2RmTJk3CoEGDDBoXa/pEmnu3b9/Ghg0bsG3bNuTk5Ojs4+LigunTp2Pu3LkwMzNTJK5Lly4hLy8P3t7eWkWMt99+G+vWrdMsfmtpaYmgoCCsXbu2wbf1Nbbc3FwkJyfj7NmzKCgogCzLaNOmDf7xj39g2LBhBtkZyRjyJ+rc08XYilgAUFpaClNTU5iamho6FKPMn8hEGtumaOfOndixY4fWrsdKqaysRHFxMczMzGBubq74+zcGQ+aP3QdizcaHH35I9vb2JMsyybJMf/vb3+jdd9/V2TcmJoZkWVYstuLiYrp06VKt9q+++oqGDRtGdnZ2ZG5uTl27dqXo6GgqLS1VLLaGKCoqoqtXr1JlZaVB3l/0/Ik89/z9/Wnnzp1abefOnSMXFxeSZZkkSdI8ZFmm5cuXKxbb3a5fv043b96st09eXh4dOXJEoYju3/Xr1ykvL89g7y1S/kSfe8XFxdSvXz+SJImsra0pICCAwsLCaNmyZbRs2TIKCwujgIAAsra2JlmWydvbm4qLixWJbeLEieTs7KzVFh4eTrIsk0qlIjc3N+rTpw/Z2dmRJEnk6upK165dUyS2Gjk5OTRy5EjN596dj5oxbd26NW3atEnRuIjEz5/Ic69GeXk5rVmzhjp16qRzjGVZpr///e8UFxdHt27dUjQ2IqKff/6ZnnvuORozZgy99tprmvOTzz77jDp37kyyLJOJiQn5+PjQDz/8oHh8ouevPnZ2djRv3jyDvb/oY3u3ixcvUnJyMn366af06aefUnJyMl28eNHQYdVpz549lJGRYegwjJZI+TO2uScSLhI1E+np6aRSqUitVtOIESNo9OjRZG5uTrIs08yZM2v1V/qL+pQpU8jBwUGrbcOGDZqTaXNzc2rdurXmxLpPnz5UUlKiWHx5eXk6v1x+9tln1LNnT80JjbW1NU2dOpVu3LihWGxEYudP9LknSRLFxsZqtfXt25ckSaLg4GBKS0ujX3/9lXbu3EkODg4kyzIdOnRIsfiIiFJSUsjd3V0zz7y9veno0aM6+yqdv/sVGhpKKpVK0fcUNX+iz73w8HCSJIkWL15c7+dFSUkJRUZGkiRJFBERoUhsLi4uFBISonmenZ1NKpWKunfvTj/99JOmvaKiglauXEmSJNGcOXMUiY2IKD8/nxwcHEiSJOrVqxcFBQVRr169SJIk8vT0pFdeeYVCQkI0xXNdn4X6JHr+RJ57ROIXsXJycsjW1laryBwWFkbffvstmZqakoWFBXl5eVH79u1JkiSysrKizMxMxeITPX/3IkkSTZs2zSDvLfrY1jDmIqAkSTR9+nRDh2G0DJ0/Y557IuEiUTPx+OOPk6mpKaWmpmra8vLyyMfHh2RZppCQEKqqqtIcU/qLZufOnWnSpEma55cuXSIzMzNycnKiL7/8UhPbtWvXaOrUqSRJkqJ/VZdlmVauXKnVlpiYSCqVimRZJjc3N+rfvz/Z2NhovgQo+cEjcv5En3t3f1FPT08nSZK0vkDVOHPmDKnVagoKClIsvszMTLKwsCBJkqhLly7k7u5OkiSRiYkJrVmzplZ/YygSKRmfyPkTfe45OztTQEBAg/sPHz681tUp+mJubk5LlizRPH/rrbdIlmWtz5k7DRkyhDp27KhIbETVhXtZlumjjz7Sat+9ezepVCravn07EVVfhTp+/HiSZZk++eQTxeITPX8izz0i8YtYM2bMIFmWacOGDZSVlUXr168ntVpNPj4+1KdPH/rtt980fd988806P3f0ReT8devW7Z4PSZLIzs5O87x79+6KxEYk/tgSiV0ETE9Pv+dDkiQKDAzUalPS77//Ti+88AJ5eHhQr169aPHixXT9+nWdfWNiYhT9w5vo+RN57hkbLhI1Ew4ODjR+/Pha7RUVFTRp0iSSJImeeeYZzZd1pb9oWlhY0OLFizXPt2/fTrIs0759+3T279evH7m5uSkVXq0vc8XFxWRnZ0f29vb09ddfa9pLSkpo4sSJJMsyrVu3TrH4RM6f6HPv7rHdtGkTybJc56WygYGB5OjoqFR4FBwcTJIk0QcffKBpS09Pp65du+q8BYmLRNpEzp/oc8/MzEyrkHAvS5YsITMzMz1G9D/29vb0wgsvaJ6vWbOGZFmu8wvnokWLFIuNiMjR0ZHGjRun81hQUBC5u7trnpeXl1PHjh1p6NChSoUnfP5EnntE4hexunTpQiNHjtRqGzFiBMmyTGlpabX6DxkyhNq3b69UeELnr+bqnDtv9737oeu4UkQfWyKxi4A143e/D6UUFBRoroC5c361a9dO563whjhnFjl/Is89Y8O7mzUTN27cgJubW612ExMTvPPOOzA1NUViYiKqqqqwa9cuxeNTq9UoLy/XPL969SoA1Ln7wqBBg7Bp0yZFYtPl0KFDKCgowKZNmzB48GBNu4WFBbZv347U1FQkJSVhwYIFisQjcv5En3t3KywsBAB07txZ5/HOnTtj3759isWTnJyMxx57DBMmTNC09e3bF+np6QgMDMSqVatQWVmJVatWKRbTne5nC3cA+OOPP/QUiW6i5+9Oos09BwcHnDx5ssH9T5w4AQcHB/0FdIdevXph//79ICJIkqT5jMnMzISXl1et/pmZmbC3t1ckNqB6nuv63AOqdwS8cxzVajVGjRqF999/X6nwhM+fyHMPAK5cuYKJEyc2uH/v3r1x5MgRPUakLT8/H+PGjdNq8/T0xMGDB+Hp6Vmrv5eXF1JSUhSKTuz89ejRAzk5OYiLi8OsWbN09pFlGVOnTsWWLVsUielOoo8tACQlJWHEiBFYvXp1vf0sLCywZs0a/Pjjj/jwww8RFxenSHyWlpYIDAyESqWqdYyIkJiYCDc3NwwYMECReO60evVqnDt3DrNmzUJUVBRMTU0RHx+PlStXIiAgALt378bIkSMVj+tOIudP9LlnTHTva8qaHAcHB1y7dk3nMUmSkJCQgMmTJ+O9997D008/jb/++kvR+Nzd3bVWuW/fvj0A4OLFizr7X7x4ETY2NorEpktWVhYkScLo0aNrHTM3N8fQoUNx5swZxeIROX+iz72aOGo4OjoCAIqLi3X2LSkpgYWFhSJxAdUFPw8Pj1rtNjY22LdvH4YMGYK4uDgsXrxYsZjulJubiwsXLuDKlSsNepSWlioan+j5E3nuBQUFYf/+/Vi2bBnKysrq7FdWVoalS5fi4MGDePzxxxWJ7fnnn0d2djbmzp2LqqoqjB49Gm5ubpg9e7amSF4jPj4e+/btQ0BAgCKxAdWfe6dOndJ57NSpU7C1tdVqs7GxUfRnQ/T8iTz3APGLWLa2tpqic42a5wUFBbX6FxQUKLrLnsj5+/777xEWFoY5c+ZgyJAhwm2RLfrYAtVFwF69ejW4f+/evRu8bfnDWr16NSoqKpCdnY3IyEgkJCRoPXbs2AEA8PX11WpXyp49e+Dl5YXNmzfDwcEB9vb2iIiIQGpqKuzs7BAUFITPP/9csXjuJnr+RJ57RsewFzIxpQwfPvyetxdVVVVpbs2wsbFR9PLA+Ph4kiSJXn75ZSKqXqfB0dGRRo0aRWVlZVp9Dx48SKampjpvYdKXu28LiYuLI1mWqby8XGf/xYsXk1qtVio8ofMn+tyrWVvAxcWFXFxcyNHRkWRZpuTkZJ39R48eTV26dFEsPkdHR3r++efrPH7r1i0aNmwYybJM4eHhil967OTkRD169Ghw/5CQEEXjEzl/os+9wsJC8vT01Pxcjhw5kubMmUNRUVEUFRVFc+bMoZEjR2qtxVZYWKhYfNOnTydJksjNzY0WLVpEERERZGJiQpaWluTr60tjx47V7PTj4OCg6I4m06dPJ1mWa+1ctnnzZpJlmZ566imt9qefflrRNX+IxM6f6HNv/vz5JMsyLV26tN7dQktLS2nJkiUkyzItWLBAsfj8/PzIycmJioqKiKg6n46OjmRjY0Nr167V6nvz5k1q27Yt9e7dW7H4RM8f0f9uS7aysqLXX39d65ghF64WfWyJiDp27Fjrlrj6jBgxQtHPv9OnT5OXlxe1aNGC4uLitNbFJDLs+Jqbm9PChQt1Hjt37hx16NCBzMzMaM+ePURkmCUGRM6f6HPPmHCRqJnYsGEDSZJU544+NaqqqigkJERzz6lSqqqqaPTo0STLMvn5+dGmTZvoxRdfJBMTE3JycqKQkBCaO3eu5suclZUV/fLLL4rFJ0kSTZkyhY4cOUJHjhyhlStXkizLlJubq7N/aGgotW3bVrH4RM6f6HOvY8eO5OzsXOtx90LlRNUnrDY2NrW+4OmTj4/PPYswZWVlmrGtKTQoZcyYMWRqatrghdqVXpNI5PyJPveIqu/bX7FiBTk5OdW5PoeTkxNFR0cruuNkjY0bN1LLli3rXUdkxIgRdO7cOUXjunjxIrVp04ZkWaZ27dqRt7c3tWvXjmRZJhsbG/r11181ff/66y9q06YNPfnkk4rGSCRu/ojEnnuiF7F2795NkiSRq6srPfPMM+Ti4kIqlYo+/PBDUqvVtGjRIvr8888pISGBPDw8SJZliouLUyw+0fNX49atWzR//nxSqVTk4+ND2dnZRGTYL8Gijy2RcRQBKyoqKDo6mkxNTalfv35a58SGHF97e/t6c5GTk6MpFH366acGW4dS1PwZw9wzFlwkaiYuXbpEixcvbtDuKVVVVRQdHU2hoaH6D+wO5eXlNG/ePDI1NdUsdKZrkcDu3bsrvtPA3Qu11TzfsWOHzv79+vWjfv36KRqjqPkzhrnXUJmZmRQTE6Nz8UB9eemll0iWZTp58mS9/WoKHUoX2aKjo0mSpAbPqZpCoFJEz19DGWLu3e3s2bP0xRdf0L///W/697//TV988QWdPXvWYPHUKCsroz179tCKFSto5syZNH36dAoPD6dt27YZpLhR49y5czRq1CgyNTXV7Kg3ePDgWguTl5WVUWpqKl24cMEgcYqavzuJOPdELmIRES1YsIBUKhVJkkRmZma0ceNGIiKKjY3VOqeRJIl8fX3p9u3bisYnev7udOTIEXJ1dSULCwtat26dQb8EE4k/tsZSBCQi+s9//kOPPvoomZub00svvUR//fWXQce3d+/e5O/vX2+fmiuK1Go1DRgwwKDnLKLlz5jmnugkIiJD3/LG2J0uX76MpKQknDhxAr///juqqqpga2uLLl26YPDgwfD19YUsK7ucVmxsrM52T09PjB07VqstKysLXbt2xezZs/Haa68pEZ4WEfPHHlx2djaioqIwcuRIBAcH19u3vLwcM2bMQF5entYaVfqUk5ODlJQU+Pr6wtnZ+Z79r1+/juLiYnTs2FH/wUH8/Bm7vXv3wtnZGT169DB0KMIqLy/H9evXYWdnhxYtWhg6nCZDpLmXlZWFrKws3Lx5E0D1ujFubm51Ll6ulKtXryI3Nxdubm5o2bKlpv3QoUP46quvcPv2bQwcOBDjx4836HmBqPm7U2lpKRYuXIi3334bAAy2cHUN0ce2tLQUcXFxiI+Px+XLl3X2cXR0xNSpUxEREaHoent3u337NqKiorBu3Tr07NkTJ0+exHPPPWeQ8V24cCFef/115Ofno23btnX2y8nJgb+/P/Lz8yFJEiorKxWMUptI+QOMa+6JjItEjDWy4uJiXL9+HS1btoS1tbWhw2GMMb0x5C4/rHnjuccM4fDhw8jIyIC7uzuGDBli6HCMgjEUAQHgu+++Q0hICLKzsw322ZKWloYnnngCCxYsQHh4eL19z58/rykUGbJIVEOE/N3NWOaeiLhIxBhjjLFajh8/fs8+3t7eGDt2LJYsWaJp69u3rz7DqiU3NxfJyck4e/YsCgoKIMsy2rRpg3/84x8YNmyY4jv76HLp0iWdJ6pOTk4GjkzM/BnL3KuoqMDp06dhYmICDw8Prd0K73Tq1CmcPHnynlczNjecPyaayspKFBcXw8zMDObm5oYOx+hw/poOLhIxo1BcXIzS0lK0atXKoJdEG+sJjSj5Y/p348YNFBcXo0OHDgaNo6SkBFu3bkVaWhpKSkrg7OyMSZMmYdCgQQaN615EyZ8IZFmu8zOuPkr9RfP8+fOYPXs29u/fX+sYEUGSJNjb2yM6OhqzZ89WJKY73b59Gxs2bMC2bduQk5Ojs4+LiwumT5+OuXPnwszMTNH4RM6f6HMPAJKSkjBr1iz8+eefAKpvX4iLi8OkSZNq9Y2NjcXKlSuF+Gt/jZYtWyIkJAQbNmwwyPsbS/5ELvDWxdBje7/i4+ORlpaG7du3GzoU1szw3KubiaEDYAwALly4gEceeQQ2NjZa7Z9//jmWL1+O06dPAwAsLS3x5JNPYu3atbCzs1M0xvs5ofnkk0+wcuVKxYpExpA/poyFCxdi165d+OuvvxR5v8GDByM0NFRrrufk5GDo0KHIy8vDnX+HePvtt7F06VK8+OKLisT2IJTOn+gsLS0RGBgIlUpV6xgRITExEW5ubhgwYICicV28eBEDBgzA1atX4enpCRcXF5w/fx4nT55Ez5498cwzz+D06dP4/PPPMWfOHPz000948803FYuvpKQEQ4YMwfHjx2FlZYXhw4fDzc1N8xldWFiIrKwspKWlYcmSJfjkk09w6NAhWFpaKhKf6PkDxJ17QPWVThMnToRKpcKwYcNgamqKQ4cOYfLkyUhJSVE8Vw+ioKAAJSUlBnlv0fMneoH3Xgw5tg8iNTUViYmJ/EVdB2MsUhoTnnv1MMhy2YzdRZblWts+JyYmkkqlIlmWyc3Njfr376+1Gn1Dt9xuDOnp6aRSqUitVtOIESNo9OjRZG5uTrIs08yZM2v1V3pLStHzx5Sj9BbzkiRRbGysVlvfvn1JkiQKDg6mtLQ0+vXXX2nnzp3k4OBAsizToUOHFIvvfimdP5GtWbOGzM3NqX///nTmzBmdfQy1i8mUKVNIlmX66KOPtNp3795NKpWKtm/fTkRERUVFNH78eJJluUE7LDaW8PBwkiSJFi9eXO/OTCUlJRQZGUmSJFFERIRi8YmeP5HnHhHR448/TqamppSamqppy8vLIx8fH5JlmUJCQqiqqkpzTOlzgm7dut3zIUkS2dnZaZ53795dsfhEzl9xcTH169ePJEkia2trCggIoLCwMFq2bBktW7aMwsLCKCAggKytrUmWZfL29qbi4mJFYiMSf2wfhNK/d3///Xd64YUXyMPDg3r16kWLFy+m69ev6+wbExNDKpVKsdiIqncrXrNmDXXq1ElrZ+U7H3//+98pLi7OIOfyoufvfvA5X924SMSEcPcXzeLiYrKzsyN7e3v6+uuvNe0lJSU0ceJEkmWZ1q1bp1h8Ip/QEImfP6YcQxeJ0tPTSZIkCgkJqdX3zJkzpFarKSgoSLH47hefMGg7ffo0eXl5UYsWLSguLk7rc47IcF/UHR0dady4cTqPBQUFkbu7u+Z5eXk5dezYkYYOHapUeOTs7EwBAQEN7j98+HBydnbWY0TaRM8fkbhzj4jIwcGBxo8fX6u9oqKCJk2aRJIk0TPPPKOJ2RDnBDVboNf10HVcKSLnT/QCr+hjS0S0c+fO+3oMGjRIsfEtKCjQFF/uzE+7du3oyJEjtfor/bMrepFS9PyJPPeMDReJmBDu/qL56aefkiRJtHnz5lp9y8rKqH379uTt7a1YfCKf0BCJnz/24FxcXO7rUXPioJS7596mTZtIlmXKyMjQ2T8wMJAcHR2VCk/4/BmDiooKio6OJlNTU+rXrx/98ssvmmOG+qKuVqvr/GIWERFB5ubmWm3PP/88tWzZUonQiIjIzMyMlixZ0uD+S5YsITMzMz1GpE30/NUQce4RVedv6dKlOo9VVVVRSEgISZJEkyZNosrKSsXPCXr27EnW1tb0xhtv1NmH86eb6AVe0ce25v3rugJG16OmvxJqCnvPP/88Xblyhf744w+Ki4sjS0tLatGiBe3bt0+rv9I/u6IXKUXPn8hzz9jwmkRMSFlZWZAkCaNHj651zNzcHEOHDsXHH3+sWDw3btzQuV2iiYkJ3nnnHZiamiIxMRFVVVXYtWuXYnHVRbT8sQeXm5sLWZZhamraoP4VFRV6jqh+hYWFAIDOnTvrPN65c2fs27dPsXiMLX8iMjExQUxMDMaMGYPg4GB4eXkhKioKkZGRBovJwcEBp06d0nns1KlTsLW11WqzsbFBaWmpEqEBqI7v5MmTDe5/4sQJODg46C+gu4ievxoizj2gOn/Xrl3TeUySJCQkJICIsGvXLlRVVaFTp06Kxvf9998jJiYGc+bMwUcffYT4+Hg4OzsrGkN9RM7flStXMHHixAb37927N44cOaLHiLSJPrYAoFar4ejoiBkzZjSof1JSEn788Uc9R1Vtz5498PLywubNmzVtERERGD58OEaNGoWgoCAkJSXpPH9WQlJSEkaMGIHVq1fX28/CwgJr1qzBjz/+iA8//BBxcXGKxCd6/kSee8aGi0RMSFVVVQBQ50lz27ZtUVZWplg8Ip/Q6CJa/tiDc3R0hL29PTIyMhrUPzQ0VPFC5Z27EDk6OgKo3lFP1/anJSUlsLCwUCw2Y8ifsfDy8sKJEycQFRWFFStWYPfu3Q+0A1VjCAgIwLZt27B582atnbfeeOMNHDhwABMmTNDqn5+fj7Zt2yoWX1BQEF599VUsW7YMy5cvR4sWLXT2Kysrw4svvoiDBw9i3rx5isUnev7uJtLcA4CuXbvi8OHDdR6XJAk7duwAAOzatQvW1tbKBPZfpqameOmllzB27FiEhITAw8MDq1evxgsvvKBoHHUROX+iF3hFH1sA8PDwwIULFxpczM3MzFTsi3pubq7O3Ro9PT2RkpICf39/PPHEE/jwww8xZswYRWK6k+hFStHzJ/LcMza8FzYTRm5uLo4ePYqjR4+ivLwcQPWHpS6//fabortzNfSEZvLkyfjggw/w2muvKRZbDZHzxx5c7969cebMGc2Y3oshvjht2LABrq6ucHV1xdKlSwEAP/30k86+eXl5in7ZNIb8GRO1Wo24uDikpKSgqKhIa/c6Ja1YsQKtWrXCnDlz4OjoiP79+8PR0RFhYWGwsrJCbGyspm9lZSUOHjwIb29vxeKLjY1Fjx49sHr1ajg4OOCxxx7D3LlzsWLFCqxYsQJz587FY489BgcHB6xZswY9evRATEyMYvGJnj9dRJl7ADBy5EhkZ2cjJSWlzj415wXBwcEoKipSMLr/6du3L06ePIlp06Zh3rx58PX1xblz5wwSy51Ezl9QUBD279+PZcuW1fvHtLKyMixduhQHDx7E448/rlh8NUQdW6D69+4ff/yB/Px8Q4dSi6WlZZ2fHa6urjh8+DDatm2LCRMmYM+ePQpHJ36RUvT8iTz3jI4Bb3VjTOPue0hrnu/YsUNn/379+lG/fv0Ui2/Dhg0kSRIdPXq03n533ktvyHtwRcsfe3DR0dEkSRKlp6c3qH/N/FNKx44dydnZudbj7t32iIhKS0vJxsaGnnrqKcXiEz1/xuyvv/6igoICKisrM8j7nzt3jkaNGkWmpqYkSRKZmJjQ4MGDa62HVVZWRqmpqXThwgVF4yspKaEVK1aQk5NTnQvMOjk5UXR0dL1rT+iL6Pmrj6Hn3qVLl2jx4sUN2vGtqqqKoqOjKTQ0VP+B1ePIkSPk6upKFhYWtG7dOoOuWyNy/goLC8nT05MkSSIbGxsaOXIkzZkzh6KioigqKormzJlDI0eO1NottrCwUJHY6iLS2BIRvfPOO+Ts7Ky1cUp9tm3bptj49u7dm/z9/evtc+7cOerQoQOp1WoaMGCAoufz8+fPJ1mWaenSpVRaWlpnv9LSUlqyZAnJskwLFixQLD7R8yfy3DM2EpEB/xTD2H/d+VfLO3l6emLs2LFabVlZWejatStmz56t2BU7ly9fxuuvv45+/fohMDCw3r5EhNjYWOTl5SEhIUGR+ETPH3twOTk5SElJga+vb4PWHbh+/TqKi4vRsWNH/Qd3n3799Ve8//778Pf3h4+PjyLv2ZTyx3QrLy/H9evXYWdnV+dtXYaWlZWFrKws3Lx5EwBga2sLNzc3nWvdKc0Y8scaR2lpKRYuXIi3334bADB16lRs2bLFwFGJp7S0FHFxcYiPj8fly5d19nF0dMTUqVMRERGh6C3UdeGxbZiFCxfi9ddfv+cttDk5OfD390d+fj4kSUJlZaUi8RUVFcHHxwcZGRmwtrbGwIED4ebmplkn7ubNm8jKykJaWhqKiorQs2dPHD16VLFbMkXPH2s8XCRiRqe4uBjXr19Hy5YtFb/Pvyng/DHGmOHt3bsXzs7O6NGjh6FDYc3M4cOHkZGRAXd3dwwZMsTQ4QhN5AKvLjy29UtLS8MTTzyBBQsWIDw8vN6+58+f1xQ6lCxyiFykNIb8scbBRSLGGGOMGbVLly7p/CLn5ORk4MjqJsuyMH/tN8b8McZYU2dsRUrWdPDuZkwoFRUVOH36NExMTODh4VHnIrKnTp3CyZMnERwcrHCEYuP8NR8lJSXYunUr0tLSUFJSAmdnZ0yaNAmDBg0ydGhGgfNn/G7fvo0NGzZg27ZtyMnJ0dnHxcUF06dPx9y5c2FmZqZYbMePH29Qv2vXrmn17du3r75CqkXk/LHGxUXA+2cs51M8tk0bF4SYofCVREwYSUlJmDVrFv78808A1ZdSxsXFYdKkSbX6xsbGYuXKlXz54h04f03T4MGDERoaqnUCmpOTg6FDhyIvL09rlwlJkrB06VK8+OKLhghVSJy/pqmkpARDhgzB8ePHYWVlpVm3wcbGBgBQWFioWbehpKQEffv2xaFDh2BpaalIfLIsP9BOeUp9JoueP/bwuAj44EQ/n+KxbTzGXmSLj49HWloatm/fbpD3N/b8sbrxlURMCMePH8fEiROhUqkwbNgwmJqa4tChQ5g8eTJSUlLw5ptvGjpEoXH+mq7Dhw/Dz89Pq23ixInIzc3F5MmTMWPGDLRq1QrHjh1DZGQkVq1aBT8/P16L4L84f01TbGwsjh8/jsjISERFRdW5JkNpaSlWrlyJtWvXYuXKlYiLi1MsRktLSwQGBkKlUtU6RkRITEyEm5sbBgwYoFhMNYwhf+zB3V0EHD58eJ1FwCVLluCTTz7hIuB/iX4+xWP78JpSkS01NRWJiYmKFomaUv5YPQyzqRpj2h5//HEyNTWl1NRUTVteXh75+PiQLMsUEhJCVVVVmmMxMTGKbqkoOs5f0yVJEsXGxmqep6enkyRJFBISUqvvmTNnSK1WU1BQkIIRio3z1zQ5OztTQEBAg/sPHz6cnJ2d9RiRtjVr1pC5uTn179+fzpw5o7OPIbepFj1/7OGEh4eTJEm0ePFiKikpqbNfSUkJRUZGkiRJFBERoWCE4hL9fIrH9uEUFxdTv379SJIksra2poCAAAoLC6Nly5bRsmXLKCwsjAICAsja2ppkWSZvb28qLi42dNh1Cg0NVXT+NbX8sbrxlURMCGlpaQgMDMTAgQM1bR06dMDXX3+NkJAQJCYmorKyEomJiQ90CX9Tx/lrPr7//ntIkoQFCxbUOta1a1c89thjOHbsmAEiMw6cv6bhypUrmDhxYoP79+7dG0eOHNFjRNoiIyMxatQohISEwMvLCzExMQgPDxfm81f0/LGHk5SUhBEjRmD16tX19rOwsMCaNWvw448/4sMPP+QrxSD++RSP7cMR/SrKxMTE++qfnZ2tp0h0Ez1/rPFwkYgJ4caNGzoXZjMxMcE777wDU1NTJCYmoqqqCrt27TJAhGLj/DUfhYWFAIDOnTvrPN65c2fs27dPyZCMCuevaXBwcMDJkycb3P/EiRNwcHDQX0A6uLu7Iz09Hf/3f/+H5cuX4+OPP0ZCQgK6deumaBy6GEP+2IPjIuCDE/18isf24YheZAsNDb2v4iMRKVqsFD1/rPFwkYgJwcHBAdeuXdN5TJIkJCQkgIiwa9cuVFVVoVOnTgpHKDbOX9N25wmAo6MjAKC4uBjm5ua1+paUlNT5l53mivPX9AQFBeHVV1/FsmXLsHz5crRo0UJnv7KyMrz44os4ePAg5s2bp2yQqP5iGRMTgzFjxiA4OBheXl6IiopCZGSk4rHcyVjyxx4MFwEfnOjnUzy2D0f0IptarYajoyNmzJjRoP5JSUn48ccf9RzV/4ieP9Z4uEjEhNC1a1ccPny4zuOSJGHHjh0AgF27dsHa2lqZwIwE569p27BhAxISEgAA5eXlAICffvqp1oLMAJCXl4e2bdsqGZ7wOH9NT2xsLJKTk7F69Wps2rRJszuXra0tAODmzZuaxVuLiorQs2dPxMTEGCxeLy8vnDhxAlFRUVixYgV2795t0FvPjC1/7P5wEfDBiX4+xWP7cEQvsnl4eODChQsN/kNCZmamokUi0fPHGpFhl0RirNqGDRtIkiQ6evRovf2qqqooJCSEJEnihZfvwPlrujp27EjOzs61HitXrqzVt7S0lGxsbOipp54yQKRi4vw1XSUlJbRixQpycnIiSZJ0PpycnCg6OrreBV6V9u2335Kbm5tBF64mMt78sXsrLCwkT09PkiSJbGxsaOTIkTRnzhyKioqiqKgomjNnDo0cOZJsbGxIkiTy9PSkwsJCQ4ctBNHPp3hsH878+fNJlmVaunQplZaW1tmvtLSUlixZQrIs04IFCxSLb8aMGSTLMl24cKFB/ZVeuFr0/LHGIxERGbpQxdjly5fx+uuvo1+/fggMDKy3LxEhNjYWeXl5mqsDmjvOHwOAX3/9Fe+//z78/f3h4+Nj6HCMDufPeGVlZSErKws3b94EANja2sLNzU3n2iIiqKysRHFxMczMzHTe9qg0Y8sfu7fS0lLExcUhPj4ely9f1tnH0dERU6dORUREBN9m+1/GcD7FY/vgioqK4OPjg4yMDFhbWzfoKsqjR48qdsXYu+++i+XLlyM+Ph6DBw++Z//4+HikpqYqNv9Ezx9rPFwkYowxxliTs3fvXjg7O6NHjx6GDsUocf6aDi4CNl08tvePi2wPh/PXPHCRiDHGGGNNjizLmDp1KrZs2WLoUIwS548x1tRxke3hcP6aLl64mjHGGGNG5fjx4w3qd+3aNa2+ffv21VdIRoXz1zxUVFTg9OnTMDExgYeHR52LpZ86dQonT55EcHCwwhGyB8Vj2zi4oPFwOH9NF19JxBhjjDGjIsvyA+0OVllZqYdojA/nr+lLSkrCrFmz8OeffwKovv0jLi4OkyZNqtU3NjYWK1eu5PE1Ejy2yomPj0daWhq2b99u6FCMEufPePGVRIwxxhgzOpaWlggMDIRKpap1jIiQmJgINzc3DBgwwADRiY/z13QdP34cEydOhEqlwrBhw2BqaopDhw5h8uTJSElJwZtvvmnoENkD4rFVVmpqKhITE7nI8YA4f8aLi0SMMcYYMyqrV69GTEwMsrOzsX37dnTt2rVWn8TERPj6+vKaOjpw/pq2tWvXQpZlfPPNNxg4cCAA4MKFC5g8eTK2bNmCsrIyJCQkPNDVZMyweGwZY0rgIhFjjDHGjEpkZCRGjRqFkJAQeHl5ISYmBuHh4fzFqIE4f01bWloaAgMDNUUEAOjQoQO+/vprhISEIDExEZWVlUhMTOQxNzI8tg8nMTHxvvpnZ2frKRLjxPlrPrhIxBhjjDGj4+7ujvT0dPzf//0fli9fjo8//hgJCQno1q2boUMzCpy/puvGjRs6F5M1MTHBO++8A1NTUyQmJqKqqgq7du0yQITsQfHYPpzQ0ND7Kp4RERfb7sD5az64SMQYY4wxo2RiYoKYmBiMGTMGwcHB8PLyQlRUFCIjIw0dmlHg/DVNDg4OuHbtms5jkiQhISEBRIRdu3ahqqoKnTp1UjhC9qB4bB+OWq2Go6MjZsyY0aD+SUlJ+PHHH/UclfHg/DUfXCRijDHGmFHz8vLCiRMnEBUVhRUrVmD37t3818v7wPlrWrp27YrDhw/XeVySJOzYsQMAsGvXLlhbWysTGHtoPLYPx8PDAxcuXGhwITwzM5OLHHfg/DUfsqEDYIwxxhh7WGq1GnFxcUhJSUFRURGIyNAhGRXOX9MxcuRIZGdnIyUlpc4+NcWE4OBgFBUVKRgdexg8tg+nd+/e+OOPP5Cfn2/oUIwS56/54CuJGGOMMdZk9O/fH2fOnEFxcTHMzMwMHY7R4fwZvwkTJuDq1au4fv16vf1qbk9ydnZGXl6eQtGxh8Fj+3D++c9/Yv/+/cjKykL79u3v2X/QoEEKRGU8OH/Nh0T8pyLGGGOMMcYYY4yxZo9vN2OMMcYYY4wxxhhjXCRijDHGGGOMMcYYY1wkYowxxhhjjDHGGGPgIhFjjDHGGGOMMcYYAxeJGGOMMWZghw8fhiRJiImJaVB/Pz8/SJKkl1hiYmIgSRIOHz6sl9dXirOzM5ydnR/qNXJzcyFJEkJDQxslJsYYY4yJj4tEjDHGGDN6O3bsgCRJ2LFjh6FDYYwxxhgzWiaGDoAxxhhj7H4kJiaitLRUL6/9wgsv4KmnnkKHDh308vqMMcYYYyLjIhFjjDHGjIo+CzitWrVCq1at9Pb6jDHGGGMi49vNGGOMMSaM1NRU+Pn5wdraGo888ggef/xxZGdna/W5e02i0NBQTJkyBQAwZcoUSJKkedS4cuUK5s6dCzc3N7Ro0QKPPPIIunXrhpkzZ+LmzZuafrrWJKp5v7oed6/ZU1RUhOjoaDz66KOa9xoxYgRSU1MfOC/Jycl49tln0aVLF1hZWcHKygr/+Mc/sGXLlga/xp3/b/Hx8fDw8IC5uTmcnJwwf/58FBUV1flvs7OzMW7cONjZ2cHS0hJDhw5FRkaGXuJkjDHGmOHwlUSMMcYYE8KxY8ewevVqBAQEICwsDD///DM++eQTpKSk4NixY3B1ddX57wIDA1FQUIA9e/Zg7Nix8PT01DpeWlqKgQMHIjc3F8OHD8e4ceNw+/ZtnD9/Hrt27cKiRYtga2tbZ1yhoaHw8/Or1f7ll1/i+PHjsLCw0LTduHEDPj4++PnnnzFw4EDMnDkThYWF2LNnD/z9/ZGUlITAwMD7zk1cXByys7Ph7e2NcePGoaCgAF999RVmzJiBX3/9FevWrWvwa61fvx5ff/01nnzySYwaNQqHDh3Cxo0bcezYMRw9ehSmpqZa/XNzc+Ht7Y1HH30Uzz77LM6dO6f5/zlz5gzatm2rlzgZY4wxZgDEGGOMMWZAycnJBIAA0FtvvaV17K233iIANHr0aE2br68v3X0Kk5CQQAAoISGh1uvv3buXANC8efNqHSsqKqJbt25pnkdHRxMASk5Orjfmo0ePklqtJldXV7p27ZqmfdKkSQSAtm7dqtX/6tWr1L59e2rdujWVlZXV+9q65OTk1GqrqKigYcOGkUqlory8PK1jHTt2pI4dO2q11fy/qdVqysjI0LRXVVVp4n7llVc07efPn9eMy5o1a7Rea/ny5QSAVq9e/VBxMsYYY0wsfLsZY4wxxoTQuXNnTJs2Tatt2rRpcHNzwxdffIFr16491Ou3aNGiVpuVlRXMzMzu63Vqbr2ysLDAF198oVnD6I8//sAHH3yAwYMHY+rUqVr/pk2bNggPD8e1a9dw6NCh+47dxcWlVpuJiQlmzpyJyspKJCcnN/i1goOD0aNHD81zSZKwatUqqFQqnbvDubi4IDw8XKvtueeeAwB8//33eouTMcYYY8rj280YY4wxJoSBAwdClrX/fiXLMgYOHIisrCxkZGRg6NCh9/26Pj4+aNeuHdasWYOMjAyMHj0avr6+6Natm9a6RQ3x559/YtSoUbh58ya++uordO3aVXPs+++/R2VlJcrLyxETE1Pr32ZlZQEAMjMzMXr06Pt636KiIrzyyiv49NNPce7cOZSUlGgdv3z5coNf65///Getto4dO6J9+/b4+eefcfv2bajVas0xT0/PWuPyt7/9DQBQUFCgtzgZY4wxpjwuEjHGGGNMCHeubaOr/c4Fpu+Hra0tjh07hhUrVuCzzz7Dvn37AADt27fH4sWL8fzzzzfodSoqKhAUFISzZ89iy5YtGDJkiNbxGzduAADS0tKQlpZW5+vcXTi5l9u3b8PPzw8nTpxAr169MHnyZNjb28PExAS5ubnYuXMnysvLG/x69eU5NzcXRUVFsLe317Tb2NjU6mtiUn0KWVlZqbc4GWOMMaY8LhIxxhhjTAhXr16tt72+xaXvpUOHDtixYweqqqpw6tQpHDhwAK+99hpmz54NOzs7TJw48Z6vMWPGDBw+fBgLFy6sdVsc8L9iysKFC/HKK688cKx327NnD06cOIHnnnsO27Zt0zr2/vvvY+fOnff1evXlWZIkWFtbCxEnY4wxxpTHaxIxxhhjTAhpaWmoqqrSaquqqsK3334LSZLQs2fPOv+tSqUCoH1liy6yLMPT0xMRERF47733AAB79+69Z2yrV69GQkICxo4di7Vr1+rs06dPH0iShO++++6er3c/zp07BwAYO3ZsrWMpKSn3/Xq6/k1eXh7y8/Px6KOPat1qdj8aO07GGGOMKY+LRIwxxhgTwtmzZ7F161attq1bt+Ls2bMYNWoUWrduXee/bdmyJQAgPz+/1rGff/5Z59UzNW3m5ub1xvXRRx9h2bJl8PLywrvvvltrfZ4aDg4OmDBhAr799lu8/PLLIKJafdLT01FaWlrv+92tY8eOAIDU1FSt9iNHjtTKV0MkJibi1KlTmudEhKVLl6KyshKhoaH3/Xr6ipMxxhhjyuPbzRhjjDEmhBEjRmDOnDnYt28fHn30Ufz888/47LPP0KpVK7z66qv1/tv+/fujRYsW2LhxI/78809NQWn58uU4ePAgwsPDMXDgQHTu3Bn29vbIycnB3r17YW5ujtmzZ9f72sHBwSAieHl54eWXX6513NPTE4GBgQCAN954A7/++isiIiKwa9cu9O/fH4888gjy8/Pxww8/ICsrC1euXIGFhUWD8/Kvf/0Lzs7OWLt2LX766Se4u7vj119/xeeff45x48bho48+avBrAdV57t+/P5566im0bt0aX3/9NX744Qd4e3sjLCzsvl5Ln3EyxhhjTHlcJGKMMcaYELy9vbF8+XIsX74cr732GlQqFQIDA7F27Vq4urrW+29btmyJjz76CDExMdi6dSvKysoAVBeJRowYgdzcXBw9ehQff/wxiouL4eTkhCeffBIRERHo3r17va9d81p3r7NTIyQkRFMkatmyJb799lts2rQJH3zwAd59911UVVXBwcEBPXv2RFRUFFq1anVfebGyssI333yD8PBwHD16FIcPH8ajjz6Kd999F23btr3v4suCBQswZswYbNy4EdnZ2WjZsiXmzp2LF1988YFvNdNHnIwxxhhTnkS6roVmjDHGGGNNSkxMDGJjY5GcnAw/Pz9Dh8MYY4wxAfGaRIwxxhhjjDHGGGOMi0SMMcYYY4wxxhhjjNckYowxxhhT3KeffoqTJ0/es5+fnx/fGsYYY4wxxfCaRIwxxhhjCgsNDcXOnTvv2S86OhoxMTH6D4gxxhhjDFwkYowxxhhjjDHGGGPgNYkYY4wxxhhjjDHGGLhIxBhjjDHGGGOMMcbARSLGGGOMMcYYY4wxBi4SMcYYY4wxxhhjjDFwkYgxxhhjjDHGGGOMgYtEjDHGGGOMMcYYYwxcJGKMMcYYY4wxxhhj4CIRY4wxxhhjjDHGGAPw/8phAw7SbqRCAAAAAElFTkSuQmCC", + "image/png": "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kmk7d167Y59w6NAht+tzxXHdt7vuukvXXntthvHFixfXoEGDJEnff/+9EhMTXT5PdvelTz/9tMvtTceOHa3/P//88y6vgehoc3kfXLFihbZv366IiAj169cv03n37t1bUuZ9SMp8m5lTd999t2rXrp1heJkyZfTII49IUoZr7nljW3Al6W95n5CQ4LQtPnr0qA4cOGDt5/JS8eLFrW1UXq/z6f3xxx+6++67dfHiRd17770aMWKE0/i8OtYAroSQCMgGc+msO5cPx4Xysqt58+Yuh/v7+6t06dKSLn1gckhJSdEff/whSYqJicn0eTO7he6BAwes21o/+OCDioqKcvkoW7asdaG7zG6Dff3112f94v5fkyZNFBoa6nJcjRo1rAO3DRs25Go+WSlZsqTLQE2SypUrZ/0/Ly9Emxey89oTEhI0YsQItWzZUqVKlZK/v791gcM6depIunQR38xemzvLplq1aqpVq5YuXLig5s2b65VXXtGWLVuy/LCdHZs2bbIO6Nq3b59puw4dOki6dDCeWTCbnWVXsmRJVatWzeW4yMhISVKdOnVUtGjRLNtcvmxXr14tSfrxxx8z7WNRUVGaPn26pMz7WNOmTa0PZXmlZcuWqlWrlvbs2WNdtDgnF6x29FN/f/8st0GO9yizfl2kSBE1atTI5bjNmzdb64E72zkHb/SNyy1dujTT/YWr8DErme0v0teTfn8hXepTknTjjTe6/GArXeor/v7+Lsc51uWpU6dmuS4vXrxYUu73F/7+/pmGf3a73XrPM1uvqlevrjJlymRrXlnJ6b7ZE7KzDFNSUjR58mTdfPPNKleunIKCgpwuenvkyBFJcrqpwOXcee233nqrJKlPnz565plntHz58lx/6ZKSkmIFLtnZH6SlpVnr++Wyu/45wu3LObb10qXtclZtMtsfJCYmqly5cpn2of79+0vKvA9ltc3MqXbt2l1x3PHjx7V79+4Mr8NT24LsmD59utM29eLFi9q/f78mT56shIQEDRw4UPfee2+eB0VFihSxvkjq1KmThg8frl9++SXTi3a7IyEhQV26dFFiYqJatWpl7afTy6tjDeBKXB8hAMg3xYsXz3Sc46A9/YfgEydOWB/E039IuVz58uVdDj948KD1/2PHjmWrxswO9LJ7IJ5ZLenH79+/3zp4dXc+WcnOcpaU4zPB8tuVXvvatWt1yy236NSpU9Ywxx1TbDabUlNTrfc5KSlJERERGZ7DnWXj5+en2bNn6/bbb9fu3bv1/PPP6/nnn1dISIhatWqlO+64Q3369HF5JlBW0q8DWa03jmDx4sWLOnHihNMBvEN21pvsvPac9lHpf/0sKSkpW2eL5LaP5VRsbKwGDx6s6dOnq1mzZvrqq6/k5+dnfZOdFcd7FBER4fIbdwfHe5RZvy5VqpTLs0WkS98AO7iznZO81zfykzvromNZZrUcg4KCFBERocOHD2cY51iXT58+neldBdPL7bp8pfXK8Z7n5/5Ccm9Z57crvbYjR46offv2Tmf5BAcHKyIiwjrj7+jRo0pLS8tyu+TOa3/11Ve1Y8cOLV26VBMmTNCECRPk5+enBg0aqEuXLnrooYeueCxwufTHO9nZH0i5Xy8ye+3p+/uV2mS2P7hw4YISEhKuWMO5c+dcDs9qm5lTWS3P9OOOHDli3e3L09sCd/j5+al8+fJ6+OGHVa5cOXXr1k2zZ89W586ds7V/y4mPPvpI3bp106+//qoxY8ZozJgxCgwMVNOmTXXbbbfpwQcfVMmSJd167nPnzum2227Tnj17VKVKFc2bN8/ldjGvjjWAK+FMIqAAyexb4aykP9Pjzz//zPKsKMcjs9ttZuenPHnBU/PxRVm99osXL6pnz546deqUGjRooO+++06nT5/WP//8o4SEBB0+fFg///yz1T6vv0mrX7++tm3bpi+//FIPPfSQrr32Wp07d06LFy/WY489plq1ann85xjpeXO9cfSzwYMHZ6uPZXbr3/x6Dffff7/8/Pz09ddfa/LkyTp37pw6deqksmXL5sv8XMnua3NnO+ftvuGL3FmO0v/W5ffffz9b6/Llty53YH+Re1d6bU8//bR+//13lSpVStOmTdOhQ4d07tw5HT16VIcPH9bhw4etsDCv1/kSJUrop59+0sqVKzVo0CDr7LSNGzdq9OjRqlGjRpY/Pc1vvrA/aN68ebb6UGbvjbfX7YK2LejatasVSH366ad5/vyVKlXSpk2btHDhQg0cOFCNGzdWWlqaVq9erUGDBql69erWz6Zzwhij3r1765dfflFYWJjmz59vncF3ubw61gCuhJAI8HElS5a0drDpzwq63IEDB1wOj4qKsv7vqdNOM6vl8vH5+e1SYbR27Vrt2bNHfn5+mj9/vjp37pzhG05XZwbkpcDAQN1xxx364IMP9Pvvv+vo0aOaPHmySpYsqX379qlPnz45er7060BWP4dwjPP393f7m7r85Ohnvnpqd9myZdWpUyedO3dOw4YNk5S9n5pJ/3uPjh07puTk5EzbOd4jd/p1+gNid7ZzvtA3fIVjWWa1HJOTkzM9s9TT6/KxY8ey/MkG+wvXLly4oK+++kqS9O677yo2NtZpfy/J6ey5/HLDDTfolVde0apVq3Tq1Cl98803uu6663Tu3Dk98MAD2TqTxiH98U529geSb64Xvrg/yOq4LP249MvTF1/HlVSuXFmSnH42l5fsdrs6duyot956Sxs2bNCJEyc0a9YsVapUSSdPntS9996b45+gvfDCC/riiy/k5+enOXPmWD+NdqUgvicomAiJAB8XGBiounXrSlKW3whkNi46Oto6lfg///lPXpfn0oYNG6zrG11ux44d1gFekyZNPFJPTjhO7fbFMw327dsn6dKHwMxOHXdcG8BTSpUqpYcfflivvPKKpEvXlsnJha0bNWpkLXPH9XJccbyu+vXrZ3rxdW9yXHNh8eLFOn/+vJercc1xAeuUlBRFRESoW7du2ZrO0U8vXryo5cuXZ9rO8R5ldv2OrDRs2NA688Wd7Zwv9g1vcVzDJKv3avXq1bp48aLLcY51ef78+XlfnAsXL17UypUrXY4zxlivw5f3F5Ln9xlHjx61tjUNGzZ02WbVqlUe3R4FBwerW7duVnh1/vx5rVq1KtvTBwYGql69epKytz+w2+15ds2evOToQ4cPH870WlqetnTp0iuOK1mypPVTM8nz24K84Di+zOy6gq7kph8XL15c9957r3WR74SEhBydUT1t2jS9/PLLkqS3337b6YLprhSEYw0UDoREQAFw1113Sbp054mdO3dmGH/8+HFNnjw50+kdF0ecOnWqNm/enOW88uLCnOfOndPrr7/uctzYsWMlXToYcVx80pc4Lrid/romviIsLEzS/+62d7n9+/fr7bffzpd5Z3UGiSSnO+Pk5BoKJUqUsA6KXnvtNZe/n//111/15ZdfSpJ69uyZ7ef2pAceeED+/v46duxYhruRXC4lJSXTEDU/de3aVc8995yeeeYZTZw4MdthW7169axvNseOHevyYuXfffedfvnlF0nuvUclS5a07pDzxhtvuPwmdsWKFZmGCd7sG77Gsb+Ij493+ZMLY4xeeumlTKd/6KGHJElbt27V+++/n+W8kpKS8uTCrePGjVNaWlqG4TNnzrQCwB49euR6Pnkt/Q0aPL3PCA0NtYLVX3/9NcP4ixcvaujQofky74sXL7p8vxzc3R9I0r/+9S9J0hdffKGtW7dmGH/mzBm9+uqrkqRbbrnF6vu+pG3bttYF8J9++ukr9hFPXBB97ty5+uuvvzIMP3bsmD744ANJGfuYN7YFubFs2TLrzmM5CZWz04+v9NrcWed/+ukn685yAwcO1GOPPXbFaQrCsQYKB0IioAAYMGCAIiMjdf78eXXq1EnLly+3vu3YsGGDOnTokOm3wtKl29ted911On/+vNq2bat3333X6WyPU6dO6fvvv1fv3r1zdYtph7CwMI0ZM0bjx4/XP//8I+nSgciTTz6pmTNnSpKGDRum4ODgXM8rrzluufvHH39ozZo1Xq7G2Q033KCiRYvKGKN77rlHf//9t6RLPyn44Ycf1KZNG7evQ3Ils2fP1vXXX68PPvhAu3btsoY75u24rXzLli0VHh6eo+ceO3asAgICtGPHDnXs2NH6Fi4tLU3fffedbrnlFl28eFHVqlXL89vD55Vq1apZP+N69dVX1bt3b6cPOBcvXtSWLVs0evRoVa9ePcvbUeeXgIAAvfrqq3r99ddd3ho9K44zxVauXKm77rrLOpX/woULmjVrlhUMtWrVyrr1bk6NGjVKNptNW7duVbdu3bR9+3ZJl5bdV199pTvvvDPTdcubfcPXtG7d2grg+/fvrxkzZlgh7/79+9WrVy+tXLky04vMx8TEWD9FfPzxx/X000879fnk5GT9/PPPGjRokCpXrpzphYOzKyQkRKtWrdK9995rnQVw/vx5ffjhh3r00UclSbfddlumd6Hypmuuuca6G+FHH33k0bOJihUrZp1VEBcXp59++skKbrZu3apbbrlFGzZsyNEZFdm1f/9+1ahRQ2PHjtXmzZudjj9+++033XfffZIunc2R1d0KXXn00UdVpUoVXbhwQZ07d9b3339vva7ff/9dHTt21O7duxUUFGR96eRr/P39NXnyZPn7+2vVqlW68cYbtWTJEqcLXO/atUuTJ09W06ZN9d577+V7TcHBwerUqZMWL15srafr169X+/btdezYMRUvXtzajzt4elvgruTkZH3zzTfWfs3f318DBw7M9vQlSpSwzkCdPn26y+PpNWvWqF69enrzzTf1559/WuukMUZr1qyxtlUVKlSwzobLyvbt23XnnXfqwoULuuWWWzRhwoRs1VoQjjVQSBgALo0YMcJIMjnpJo72S5cudRq+e/dua9zu3bsznb5y5cpGkpk+fXqGcStXrjTFihWznickJMT6u0SJEmbu3LnWuEOHDmWY/sCBA6ZFixZWG5vNZkqUKGFCQ0OtYZJM9erVs/26LtenTx8jyfTp08f06NHDSDJ+fn4mPDzc2Gw263l69+5tUlNTM0wfExNjJJkRI0ZkOZ+lS5dm+t5Mnz7dSDKVK1fOdPqs3o8LFy6YmjVrWuPDw8NN5cqVTeXKlc3cuXOzrCsrV1qfsruM33//faf3q1ixYiY4ONhIMhEREebbb7/N9LXlZtk4pnU8goKCTKlSpYzdbreGlStXzvz5558ZnjOr9dph9uzZJjAw0Hqu0NBQ63VJMhUrVjT//e9/M0yX1bqQ09fueI9iYmIybZN+Hb9cWlqaGTZsmNO6XqRIEVOqVCnj5+fntPxWrVqV7efNKcc8slrerjj6X2Y1TJgwwem1lShRwuk9u+6668yBAwcyTJedZe/w5ptvOi2nEiVKmKCgICPJXHvttdb4mjVrZpjWW33DGOf18Ep92CGr7V12+kxW68yhQ4dMrVq1rJoCAgJMiRIljCRjt9vNhx9+aCpVqmQkmc8++yzD9MnJyaZfv34Zlmd4eLhTn5dk9u/fn+3XlV76Zf7uu+9a61Z4eLgJCAiwnr9+/frm2LFjGabPTn91yM9984MPPui0X65UqZKpXLmyeeaZZzJ9viutL9ldhhs2bDBFixZ12i4XL17cSDL+/v7m448/zrT23Lz29NM69vMlS5Z02h4EBga63GdmZ1v3+++/m/Lly1vPFRwc7HSsEhQUlOn+ODv9MDuvPTv7littN77++mvr/XD0w1KlSlnbNMdj7NixOXrenHDMY9q0aSYqKspaT9MfTwYFBZn58+e7nN4T24IrSf9+hYaGmsjISOtRunRp4+/v79QHZ8+eneWycLVujBkzxml5VKxY0VSuXNn06NHDGOO8PqR/L9PPOzQ01KxYsSLT2jM7pgoPD3d6TZc/Bg4c6PScuTnWALKLM4mAAuKGG27Qb7/9ptjYWJUrV04XL15UiRIl9MADD2jTpk2qVq2a1bZEiRIZpi9XrpxWrVqlzz77TN26dVPZsmV19uxZpaSkKDo6Wl27dtXEiRO1YsWKPKn3s88+03vvvaeGDRvq4sWLKlq0qFq2bKmPP/5YM2fOzLPbuuY1f39/LVmyRP369VOVKlWUlJSkPXv2aM+ePT5x2u4jjzyiBQsWqE2bNipWrJguXryo8uXL64knntCvv/6q6667Ll/m261bN3388ceKjY1V/fr1FRYWpsTERBUvXlzNmjXTmDFj9Mcff6hWrVpuPX+PHj30xx9/6OGHH1a1atWUnJwsf39/NWjQQKNGjdLWrVtVu3btPH5Vectms2n06NH67bff9Nhjj6l27dry8/NTYmKiwsPD1apVKz333HNas2aNdQZAQfL0009rw4YNuu+++1SxYkWdPXtWRYoUUYsWLfTmm29q/fr1Wd52PTueeuopLVu2TLfccovCw8N1/vx5RUdH68UXX9TPP/9sfQPuahvnrb7hi6KiorR+/XoNGzZMNWvWlN1ul7+/v2655Rb99NNP6t+/vxITEyW5XpaBgYGaMmWK1qxZo759+6patWpKTU3VmTNnVKZMGbVp00bDhw/Xb7/9luPbnLvy+OOP64cfflCnTp1kt9tlt9tVq1YtjR49WmvXrlWpUqVyPY/8MmnSJI0cOdJav/bu3as9e/bk+wWjJalx48Zat26d7rnnHkVERCgtLU3FixfXPffcozVr1uj+++/Pl/mWL19e3377rZ5++mm1aNFCZcuW1ZkzZ+Tv7686dero8ccf19atW62fPubUtddeqz/++EMjR45UgwYN5O/vr+TkZFWrVk2PPPKI/vjjD7ef25O6d++uHTt2aMSIEWrWrJmKFSumU6dOKSgoSPXr11e/fv309ddf67nnnsv3WqpUqaLNmzfr8ccfV+nSpZWSkqIyZcqoZ8+e2rx5s7p06eJyOk9vC67k9OnT1s+KExISdOzYMYWEhKhx48YaNGiQ/vjjD7d+mvrCCy/orbfeUpMmTRQQEKD9+/drz5491g0PmjZtqs8//1yPPvqoGjdurIiICJ0+fVrBwcFq0KCBBg0apD///NOts/FPnjzp9Joufzi21Q6F/VgDvsFmHEdcAAq0KVOm6KGHHlLVqlVdXrfIE/r27auZM2eqT58+md4KFQDc1atXL3366ad64IEHrAuFIue2b9+ua665RtKlUKNixYoer2HGjBmKjY1V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2dwKAVEwrF69Wv/617+uGBBJly4Y3aNHD33xxRceqEy6/vrrs70uValSRfHx8flbUC5ERkZm+nPS/OLrt4uPjo7mp7N5hJDoKlG9enUtWLBAY8aMkb9/1m/7hQsXtGDBAlWvXt1D1V1y/vx5TZ8+XTt27NB1112n+++/X35+fjp48KCeeeYZLVu2TAEBAerSpYvGjh2rUqVKebQ+X1ajRg116tRJDz74oBo0aODtcpxER0crKChIf/75Z7bae/pgn75RuNE33Ddw4EDdf//9atasmYYOHaoOHTqoTJkyTm2OHDmiH3/8UePGjdPevXv10ksveay+I0eO6I033rD6xdNPP62wsDBt3bpV/fv31/r162Wz2dS+fXu9++67Hr3mT07s2LFDtWvXlt1u18WLFz0yz4CAAHXq1En9+vXTrbfe6vZZbfmlUaNGmj17tk6dOuWT1xQr6AGq5N0Q1ddDwOwi4HWNEBXeQgCdh7z7azd4yttvv21sNptp27atWbVqlUlLS8vQJi0tzaxcudK0adPG2O12884773isvrNnz5qGDRtadwlx3EkqKSnJ1K1b19hsNlOyZEnj5+dnbDabufbaa825c+c8Vl9ObNu2zdjtduPn5+exeaa/fkPjxo3N+++/bxITEz02/6zcddddxs/Pz5w5cyZb7T39+2D6hufQN5z5et8wxpixY8eagIAAaxmGhoaaihUrmooVK5rQ0FBreEBAgBk3bpzH6jpx4oR1HRXHnaSaNGlijh49aipUqGCCg4NNw4YNTVRUlLHZbKZixYrm5MmTHqsvJ3bu3GkqV65soqOjPTbP9P0iKirKDB482Pz9998em/+VvP7668Zms5nFixdnq/0zzzzj0eX3ySefGJvNZmrXrm0++eQTk5CQkKFNQkKC+fe//21q1apl7Ha7+fTTTz1Wn2P+gwYNMnfccYcZMWKEdYfM33//3bRo0cL4+fkZf39/06lTJ7Njxw6P1nbvvfcau92e7T7pq9cN2bZtm7HZbB7dp/n7+5tbb73VzJs3z1y8eNFj882JZs2amSpVqph//vnnim0TExNNdHS0adasmQcqy55z586ZlJQUb5dxRRcvXrSu24VLatWqZapUqZLt9r66bfEFhERXibS0NNOvXz/rwLB48eKmXr16pnXr1qZ169amXr16pnjx4tYBd//+/T1a35tvvmlsNpu5//77zbfffmseeughY7fbTe/evU3FihXN+vXrjTHGnDlzxjz44IPGbrebN954w6M1ZpfjoMFms3lsnjabzdxwww3muuuus97jokWLmj59+pjly5d7rA5XXnrpJWOz2bJ9q9M+ffp4dNnRNzyHvuHM1/uGw/bt282QIUNMq1atTOnSpU1gYKAJDAw0pUuXNq1atTJDhgzxeMAwcuRIY7PZzLBhw8xvv/1mLctOnTqZunXrOl1IdsSIEcZms5mRI0d6tEZfZrPZTNeuXU3Xrl2Nv7+/1TdiYmLMxx9/7PWg+ezZsyY+Pj7bAao3+GqAaozvh6i+HgJmFwGva74eovpygJoThJQZFZYA2hcQEl1lfvrpJ9OzZ09Trlw568DB8ShXrpzp2bOnWbp0qcfratKkibnuuusyDLPb7eazzz5zGn7hwgVTsWJFc/3113uyRJ+W/m4Dv/zyi+nfv78JDQ21DiZq1qxpXn31VZc76vx25MgRs2zZMq/MOyfoG4UTfaNwql+/vmnZsqXTMMeZfvPnz8/QvlatWqZJkyaeKs/npe8XBw8eNOPGjTPVqlWz+kWJEiXMY489ZjZu3OjlSn2bLwaoxvh+iFoQQkBf5esBr4Ovhqi+HqDmBCFlRoUlgPYFhERXsaSkJHPw4EFz8OBBk5SU5NVaIiIizBNPPOE07KmnnjJ2u93lB6jY2FhTsmRJT5Xn81zdkjIpKclMnz7d3HDDDdZGPTAw0Nx+++1mwYIFLn9WhUvoG4UHfcO7Jk6cmKNTv7OrRIkS5qmnnnIa9swzzxi73W6OHz+eoX3//v1NWFhYntdRUGV2G+Nly5aZ++67z4SEhFh9o2HDhmbSpEnWt+0FRX6tewUBIWrhVZACXl8MUX09QPV1vh5SEkDnHbu3r4kE7wkJCVHZsmVVtmxZhYSEXLH9zJkz1a5du3ypJSkpKcNF7hwXq7z8QqmSFBUV5dG7/BREISEh6tu3r1auXKlt27bpmWeeUcmSJTVv3jx17dpVlStX9naJ2Zaf654r9I3Cjb7hOadOndKePXvy/HkvXLig4OBgp2GOflKyZMkM7SMiInTu3Lk8ryM7Vq1apXHjxqlv3766/fbbdfvtt6tv374aN26cVq1a5ZWaMhMTE6N///vfOnTokN599101aNBAW7Zs0YABA1S+fHlvl5cj+bXu5ZW33npLVatWzZfn3rNnj5o3b+40rHHjxpKkli1bZmjfunVrbd++PV9qyS/5ufwKirJly+qFF17Qjh07tHTpUt17771KSUnR+++/r6ZNm6pRo0Z67733lJiY6JX6qlevrpdeekmrV6/WkSNHlJycrOTkZB05ckSrV6/WSy+9pBo1ani0pq+//lotWrTQ6NGjdd1112nIkCGKiYnRjz/+qFdeecXpVvIjR45UzZo1NX/+fI/W6OuaNGmib7/9Vnv37tXYsWNVpUoVrVixQn379lXZsmX1+OOPa9OmTV6prUiRIqpcubKKFi3qlfkXJtzdDNkWHx+v5cuX58tzR0RE6MiRI07DihQp4vJgX5KOHz/utTue7N+/X8uXL9f27dutHW9YWJhq1KihG2+8Mdu3s/aka665Rq+++qrGjx+v//znP5o6daoWLlzo7bKyLT/XvbxA37iEvuF5vt438kvp0qV1+PBhp2HlypVTo0aNXLZPSEhQeHi4J0qzrF27Vv3799eff/4pY4zLNjabTXXq1NGUKVPUokULj9aXldDQUD322GN67LHH9Ouvv+qjjz7Sp59+6u2yCpX8DLEKUojqLk+EgKtWrcp0nxYTE6MbbrghX+efEzExMYqJidGkSZP0ySefaOrUqdq8ebMGDBigQYMG6cyZM94uMUfeeustvfXWW9q1a1eePu+ePXvUt29fp2GNGzfWihUrMg1QP//88zytobBwhJQvvPCCli9fro8++khfffWV3n//fU2ePFn169dXv3791KtXL4WFhXm73GzLr3WvoCEkgk+oWbOmtm7d6jRs0KBBGjRokMv2u3bt8vgHzp07d2rAgAH68ccfJSnDQb/NZpMkdezYUW+//bbHb5OeHX5+furevbu6d+/OLR8LCPqGZ9A3Cpa6detqy5YtTsP69++v/v37u2y/fft2j551sHnzZusMrz59+qhjx46qUaOGQkNDJV26Lfr27du1cOFCzZ49W+3atdPatWtVv359j9WYXfXr19c777yj119/3dulIJsKQojqywh4vY+zUAkpvcXXz0L1FEIi+ISWLVtq0qRJSklJUWBgYJZtT548qVWrVunhhx/2UHXS7t271aJFCx0/flxt2rTJ8oB/4cKFatWqlX755RdVqVLFYzXmVNmyZb1dArKBvuF59A3fd/PNN2vatGnZ6hcHDx7Uzz//rGeeecZD1UnDhw9XUFCQVqxYoXr16rls06hRI/Xo0UNPPvmkYmJiNGzYMH377bceqzGngoKCvF0CssnXQ1RfRsBbuBWEAJWQEr6AkAg+YfTo0Ro9enS22p46dUqTJ0/W9ddfn89V/c/QoUP1zz//6LvvvlOnTp0ybTd48GB9//33uv322/Xiiy9q1qxZHqlv6dKlio6O9si84Fn0jdyhbxROAwcO1MCBA7PV1m63a9GiRapVq1Y+V/U/q1ev1r/+9a9MA6L0GjRooB49euiLL77wQGWX7N6922s/S0X+8/UQ1ZcR8BZuvh6gElLCVxASocCpUqWKx89CWLx4sXr06JHlh2CHzp0765577vHodU1iYmI8Ni/4LvpGRvQNREVFKSoqyqPzTElJyXDB+ayEhoYqJSUlHytyVpAuzo6c8/UQ1ZcR8BZuvh6gElLCVxASAdlw5swZlStXLtvty5UrV6B+fwu4i74BZFS3bl19+eWXGjFihIoVK5Zl29OnT+vLL79U3bp1PVQd8D/eCFF9GQFv4ebrASohJXyF3dsFAAVB9erVtWDBAl28ePGKbS9cuKAFCxb45MV5gbxG34CvS01N1d69e7V3716PzXPgwIGKj49Xs2bNNGvWrAx3KJSkI0eO6JNPPlHz5s21d+9ePfXUUx6rLye8sfwAb3EEvNn5MoOAt3CLiopSTEyMIiMjPTbPghBSFqQ7lcF9hEQocP766y/5+fnJ399zJ8L1799fW7du1c0336zVq1e7vJCcMUarVq3SzTffrP/+97966KGHPFZfTnhj+cEz6Bu5Q9/Ie8aYTC+86Sk7duxQdHS0R68r0atXL40ZM0Y7duxQ7969VbZsWYWFhalSpUqqVKmSwsLCVLZsWfXp00c7d+7UmDFj1LNnT4/VlxPeWH55wRfWvYKAENAZAS+8iZASvoIjYRRInj74GzBggH777TdNnTpVN954o4oWLaoqVapYaXpiYqJ2796tpKQkGWPUr18/DRgwwGP15RQHz4UXfSN36Bt5KzY2Vm3btvVqDQEBAapUqZJsNptH5zt06FD16NFD06ZNs25jnJCQIOnSbYyvvfZaxcTEKDY2VjVq1PBobTnhreWXW76w7mXFV7Y1O3bsUO3atWW327N1RqivyK/l16tXL8XHx2vUqFHq3bu3JKlYsWJO+zTHB3g/Pz+fD3gL4nvrK1JTU3XgwAFJUqVKlTwyz4EDB+r+++9Xs2bNNHToUHXo0EFlypRxanPkyBH9+OOPGjdunPbu3auXXnrJI7XllDeWH/KOzfjCHgoFwq+//qotW7aoT58+3i7Fa5YuXaopU6Zo+fLlOnTokNO4smXLKiYmRg899JDatGnjnQILKV9f93y9Pk+gb3iHp9a9/fv3W0FHYmKipEtBR40aNXTjjTeqYsWK+Tp/XL0K67q3Z88excfHe/3i+rt27VK7du1ks9m0e/dur9aSE/m9/Hbs2OEU8F6+7hWEgLegvreSNHLkSI0ePVppaWleq+Gvv/7ySsg2btw4jRo1SqmpqZKyDilHjhypF154wWO15YS3ll9u+cK65wsIia5CycnJ2rBhg8udXpMmTbgKfTadPXvWafmFhIR4uSLf5+vrnq/XV1DQN3LOV9e9nTt3asCAAfrxxx8lKcM3946zSzp27Ki3336b603lobfeektvvfWWdu3a5e1SvKKgrHuFNcTyFJYfXPGFENWbIRshpff4wrrnCwiJriLHjx/Xiy++qFmzZikpKUnS/w66HAdbRYsW1X333acxY8aoVKlSXqu1MJo5c6Zmzpypn376yduleJyvr3u+Xl9hR9/wzXVv9+7datasmY4fP642bdqoY8eOqlGjhkJDQyVduh7C9u3btXDhQi1fvlwRERH65ZdfVKVKFY/VWJiNGjVKo0ePtr5NvpoUhHWvoIRYvqowL7+rPeBNjxAQ3sK6lztck+gqcfToUbVq1Uo7d+5U1apV1aFDB5cHXIsWLdLkyZO1aNEirVmzRqVLl/Z4rYW1U8fHx2v58uX5Ph9fW36+vu75en3p+dp7m1foG7657g0dOlT//POPvvvuO3Xq1CnTdoMHD9b333+v22+/3Qq8PGnVqlVZftt6ww03eLSegsYXl5+vr3u7d+9WixYtshViLVy4UK1atSJATaewL79Tp05pz5493i7DqwpzCOjrrvaQknUvjxhcFR566CFjt9vN5MmTr9j2/fffN3a73Tz88MMeqOx/duzYYTp16mTsdrux2+3GZrM5PRzDO3fubLZv3+7R2vLCyJEjjd1uz7fn99Xl5+vrnq/XZ4zvvrd5hb7hm+te6dKlTe/evbPd/v777zelS5fOx4qcrVmzxtStW/f/2rvzuKjK9n/gn3NYRYEQF8RHBXNUFBSxXJNFUyT9ImJp+CjLV1PLXRM0RRYrwTJLbTU31N9TueRSpokhAhpW5pKpsQjikikGsgnkXL8//DKPIwOCOmfuwev9evF6NWduZz5d5x44c82Z++jcp/fuW1dXVzp69KhiuR4Xfb8uRK6f6HMvKCiILCws6Lvvvnvg2L1795KFhQWNHTtWgWTVpaSk0JtvvkkhISEUEBBAAQEBFBISQm+++SalpKQYJJMx1e9h6Pu1W0XEfUtElJ2dTc2aNSNJksjHx4fi4uJo+/btdODAATpw4ABt376d4uLiyNvbmyRJoubNm1N2drbB8jY0Ss0/EfHce3z4TKInxDfffIPAwEBMnjz5gWOnTJmCxMRE7NmzB5988okC6Rr+p0r6JnL9RJ97oucTed8aA5HrJ/rcKy4uhqOjY53HOzo61umyvY/Dr7/+ioEDBwIAQkJCat2vX3zxBQYOHIijR4+ie/fuiuQTnej1E3nuAUBiYiLGjBlT61lOVfz8/DB69Gjs27dPgWT/dfToUbzyyis4e/ZsjVcBkyQJXbp0wZo1a9CnTx/FshlD/UQm8r4FxD8TsIqIZ1EaExHrZyxzzygYukvFlGFpaUkLFiyo8/j58+eTpaWlHhNpa+ifKhHpt7Mvcv1En3ui5xN53z4u/NqoG6XnnpubG7m5uVFlZeUDx1ZUVJCrqyu5ubkpkIxo+PDhZGtrSydPnnzg2F9//ZVsbGzof/7nfxRI9vjo83Uhev1EnntERI0aNaL58+fXeXxERAQ1atRIj4m0HT9+nCwtLcnS0pLCwsLoiy++oF9++YUyMjIoIyODfvnlF/riiy8oNDSULC0tqVGjRnTixAnF8olev0elz9eu6PuWSPwzAUU+i/Jx4LNQxZ17xoSbRE8IlUpF/fr1q/P4vn37kkql0mMibU/Ci1qfv7RFrp/oc0/0fCLv28eFXxt1o/TcW7lypeaU7dTUVFKr1dXGqNVqSklJIW9vb5JlmVatWqVINjs7u3p99e6VV14hOzs7PSZ6/PT5uhC9fiLPPSLxm1jcBDSsJ7nBSyR2E9AYmmyP6kluUoo894yNbOgzmZgyxo0bh6NHj2L8+PHIy8urcVxeXh7GjRuH9PR0jB8/XrF8op9aLjqR6yf63BM9n8j71hiIXD/R5960adMwYcIEHDp0CJ6enrC1tUX37t3h6ekJT09PdO/eHba2tvDy8kJycjImTJiAadOmKZKtoqIC1tbWdR5vY2ODiooKPSYyLqLXT+S5BwCvvPIKfvvtNwwZMgRpaWk6v/JDREhNTcWQIUPw+++/Y9KkSYrlS0tLw8svv4xu3bo9cKy7uzvGjBmD1NRUBZLdJXr9RCb6vgWADh064Ntvv8U///zzwLGVlZX49ttvFVs8ePHixbCwsEB6ejrWrVuHMWPGwMPDAx06dECHDh3g4eGBMWPGYP369Th69CjMzMwQGRmpSDZjIHr9RJ57RsewPSqmlPLycvL19dWcAuji4kL+/v40fvx4Gj9+PPn7+5OLi4vm1MGhQ4dSRUWFYvka+qdKRPrt7ItcP9Hnnuj5RN63jwu/NsSce1V++OEHCgoKIkdHx2qnlDs6OlJQUBAlJSUpmqlXr17k7OxMRUVFDxxbWFhITk5O1KtXLwWSPT76fF0YS/1EnHtEd89imjhxoua1a21tTd26daMBAwbQgAEDqFu3bmRtba157b7yyiuK5mvcuDG9/vrrdR4/d+5caty4sR4TaRO9fo9Kn69d0fctkdhnAop+FuXjwGehijn3jA03iZ4garWa1q1bR3379iUTE5NqB1wmJibUt29fWr9+vc4XlT49CS9qff7SFr1+Is890fOJvm8fB35tiDn3dCkpKaErV67QlStXqKSkxGA5Nm/eTJIkkYuLC23evJmuXbtWbcy1a9do06ZN1LlzZ5Jlmf7f//t/Bkj68KKiokiSJL08tjHWT5S5dy9Rm1jcBDSsJ73BK3IT0BiabI/qSW5Sijz3jA03iZ5Qt2/fpjNnztCRI0foyJEjdObMGSorKzNYnifhRa3PX9rGVD/R5t79RMtnTPv2YfFr4y7R5p7o3nzzTTIzMyNZlkmWZbKxsaE2bdpQmzZtyMbGRrPdzMyM3nrrLUPHrbecnBw6dOiQ3h6/oddPaSI1sbgJaFjc4L1LxCagMTTZHtWT3qQkEnPuGRtuEjGhNOQX9YkTJ2jDhg16fY6GXL8nXUPet/zaYA8rIyODFixYQP369aPmzZuTubk5mZubU/Pmzalfv360YMEC+uOPPwyaMS8vjzZv3kxRUVE0a9YsmjVrFkVFRdHmzZvp4sWLBs1mDPVjD4ebgIbDDd7qRGkCGlOT7WFxk1KbKHPP2EhEOlaLY0wApaWlKCwsBADY2trCysrKwInuKi8vx88//4yMjAytfCqVCs888wwsLCwMnPAuUevHHp2o+5ZfG0+u/Px8fPjhh5AkiRf5/D9ZWVmYNm0avv/+ewCotjivJEkAAF9fX6xcuZIXz3xIPPdqlpmZiXXr1iE5OVnn72UvLy+EhYVBpVIZOKmYLl26VGPtPD090aZNG4Nl43378N566y3ExMTgzp07AIAmTZrA1tYWAFBYWKi5eIWJiQmio6PxxhtvGCzrw8jNzUVOTg68vLz08vgNvX7sLm4SsWpu3bqFnTt3AgCCg4MNG6YeNm7ciI0bN+KHH37Qy+Pn5+dj0aJF2LJlC0pKSgD896C/6mC/cePGGDduHJYsWQJ7e3u95NAXfdevLkSfe6Lnqwm/Nh4NvzYe7Pz583BxcYEkSZoDR9F98MEH+OCDD5Cdnf3YH/vChQvo1asX8vPz4e3tDV9fX6hUKtjY2AC4uz8zMjKwb98+JCcno1mzZkhPT4ezs/Njz6Iv+qxffYg+97iJ9WgMUT9u8DZ8xtBk4yYlMyRuErFqRD/gqklMTAxiY2P1kvn69evo168fsrKy0L59ewwePFjnAf+BAweQnZ2Np59+GkeOHEHz5s0fexZ90Wf96kr0uSd6vprwa+PR8GvjwfLz87Fq1SpIkoSoqChDx6kTfe7XsWPHYseOHdi5cyeGDh1a69jvvvsOI0eOxKhRo7Bly5bHnkVfRHhdAOLPPdFfuzV5UpuA3OBVFjdRq+MmpTJ47tXO1NABmHhsbW0RHBys+SXEgEWLFiE7Oxsff/wxJk+eXOvYTz75BFOnTkVkZCQ++eQThRI2DKLPPdHzGQK/NpQh+tyzt7dHdHS0oWMIIzExEWPGjHlggwgA/Pz8MHr0aOzbt0+BZA2P6HOvWbNmWLx4sbCv3ZoUFBQgNzfX0DEUr9/ChQtRVFSEvXv31vr6jYiI0DR4q86kNRai7FsAuHHjBqKjo43qjbq+z0Lt06dPnZqU+/btQ79+/bhJ+ZCMce4piZtErBoHBwds2LDB0DGE8s033yAwMPCBb4IBYMqUKUhMTMSePXv4jXA9iT73RM9nCPzaUAbPPeNSXFwMR0fHOo93dHTUrOPAGhbRm1iiU7p+3OBVljE2UfXZZOMmpXKMce4pSTZ0AMaMwc2bN+v1vVqVSoWbN2/qMRFjYuDXxpPr1q1buHbtGtRqtaGjCKdDhw749ttv8c8//zxwbGVlJb799lv+ykA98Nxj+sINXmVVNQFF/KqoITxMk/LAgQMKJGt4eO7VjptEjNVBmzZtkJycXOfxycnJBl1QjjGl8Guj4bp8+TKOHDlS7Y34p59+io4dO8LOzg6Ojo546qmnEBoair/++stAScXzyiuv4LfffsOQIUOQlpZWbU0J4O46E6mpqRgyZAh+//13TJo0yQBJxdQQ5l5paSkqKysNHcNoGap+3OBlhsRNSiYKbhI9IUpKSnDlypVq2/fv348hQ4agadOmaNSoEVxcXBAdHY2ysjIDpBTXuHHjcPToUYwfPx55eXk1jsvLy8O4ceOQnp6O8ePHK5hQXMY0927evIlbt27VOubixYs4fPiwQonEx6+Nx0PEuTdv3jz8+9//hiz/91AhPDwcr732mmYR8p49e8LU1BQJCQno27cvbty4oVg+kU2bNg0TJkzAoUOH4OnpCVtbW3Tv3h2enp7w9PRE9+7dYWtrCy8vLyQnJ2PChAmYNm2aoWMLwxjm3u+//46JEydixIgRWLVqlaah9c0336BTp06wtraGlZUVvLy88MsvvyiazRiIWj9u8Cpj9+7dOHXqlKFjCIeblPrHc6+OiD0RwsLCyMHBQWvbihUrSJZlkiSJLC0tqXnz5iRJEsmyTM8++yyVlJQYKO3DiY6OJlmW9fLY5eXl5Ovrq6mPi4sL+fv70/jx42n8+PHk7+9PLi4umnoOHTqUKioq9JJFX/RVP2OYeykpKeTq6kqyLJMsy9SnTx86fPiwzrH6nGf6wq+NR6PP+ok895ydnSkkJERzOzMzk0xMTKhLly7022+/abZXVlZSbGwsSZJEM2bMUCzfo1Kinj/88AMFBQWRo6MjSZKk9ePo6EhBQUGUlJSk1wz6os/6iT73srOzydbWVrMvZVmm6dOn05EjR8jMzIysrKzIw8OD2rRpQ5IkUZMmTejcuXOK5Xsc9Ll/Ra6fWq2miRMnanJZW1tTt27daMCAATRgwADq1q0bWVtba/6mvfLKK4rkepxEOI6RJIkmTZpk0AwPS5/1W7lyJUmSRD4+PpSamkpqtbraGLVaTSkpKeTt7U2yLNOqVav0kkVfDD3/jHnuKYkXrn5CpKWlYeDAgZrbV65cwfz589GqVSt8/vnn8PX1hSRJuHHjBhYsWIC1a9di6dKlWLJkiQFTi8Pc3BzfffcdNmzYgDVr1uDYsWM4d+6c1hhZltG7d29MmjQJISEhvBDa/xF97p0/fx6+vr4oKytDx44dYWZmhvT0dAwcOBBvvvkmIiIiFMlhrPi18fBEn3tXr17VOu09MTERRITPPvsMXbt21Ww3NTVFZGQkkpOTsWvXLnzwwQeGiCskHx8f+Pj4ALj79ZnCwkIAd69WZ2VlZchoQhN97sXHx6OoqAjvvfcehg8fjj179mD+/Pk4efIk3N3dsWfPHrRs2RLA3as6vvbaa1i6dCkvPv9/RK6fJElYs2YNxo4dizVr1iA5ORmnT5/WGtOqVSsMHz4ckyZNgre3t94zGZtjx47Vadxff/2lNbZXr176imQ0pk2bhlOnTmHt2rXw9PRE48aN4ezsDFtbWwBAYWEhLly4gJKSEhARJk6cyGeh3oPn3uPDTaInxKVLlxAYGKi5vX//flRWVmLNmjVai6M1a9YMa9aswenTp/Hll19yk+gekiQhLCwMYWFhKC8vR1ZWltYBf/v27WFpaWnglOIRfe69/fbbKCsrwxdffIHRo0cDuPtHJiQkBG+88QaKi4v5dfAA/Np4OKLPvcaNG6OoqEhzu6CgAADQo0cPneN79OiB1NRUJaI9FkSk86sk+mJlZdWgGkP6rJ/oc+/QoUPw9fXFrFmzAACzZ8/G/v37ceDAAaSkpGgaHMDdqzpu27YNP/zwg2L5RGcM9eMG78Pr06fPAz8MkiQJu3fvxu7duzXb7ty5o+9owuMm5aPhuff4cJPoCWFubo7y8nLN7WvXrgEAPD09dY5/7rnnsHr1akWyPS4BAQFwcnJS5LksLCzQpUsXRZ5LKfqqn+hzLykpCS+88ILmTTpw9xOF9PR0BAQE4O2338adO3fw9ttvK5bpcePXxqPRV/1En3s9evTA/v37QUSQJElzFbtz587Bw8Oj2vhz587B3t5e6ZgPLSwsTPMmkNWfPusn+tzLy8vDyJEjtba5u7vjwIEDcHd3rzbew8MDKSkpCqV7PPTZBDS2+nGDt/4aN26MgIAAmJiY6Hz+hIQEqFQq9OvXT685jBU3KR8ez73Hg5tETwhXV1ckJSVpblddXejSpUvo1KlTtfGXLl2CjY2NYvnuVV5ejp9//hkZGRlavxRVKhWeeeYZWFhY6Px33bt3R/fu3ZWMKiTR6if63Lt27Rrc3NyqbbexscHevXvh7++P+Ph4qNVqxMXFKZZLF9H2rbERrX6iz73XXnsNo0aNwsyZM/H+++9j+PDhUKlUmDp1Knbu3Kn1af/atWuxd+9ehIaGKp7z0qVLSE5O1rlfPT09a7yaXrt27dCuXTslo+qUn5+PDz/8EJIkITIyUvHnF7F+os89W1vbagvNV90uKCio9iauoKAA5ubmiuV7HPTZBHwS6icyfTfIly5diujoaGRmZmLdunXo3LlztTEJCQnw8vLCZ599prcc+sJnoT4afdavoc89RSm8BhIzkLVr15IkSfTOO+8QEVFRURE5OjrSsGHDqKysTGvsgQMHyMzMjF566SVFM964cYOmTJmiWRCwalHAqsUDqxYQfPXVV+nGjRuKZquPwsJC2rhxI23cuFHR5xW1fqLPPUdHR3rttddqvP/27ds0ePBgkmWZ5s2bZ5AF90Tdt/XFrw1txjD3Jk2aRJIkkUqlotdff53Cw8PJ1NSUGjduTF5eXjRixAjq2LEjybJMDg4OdOnSJcWyZWZm0tChQ6vt0/v3rZ+fH2VkZCiWq77OnTunyask0esn8tzz9vam1q1bU1FRERER3bp1ixwdHcnGxoaWLVumNbawsJBatmxJPXv2VCzfvfLy8mjz5s0UFRVFs2bNolmzZlFUVBRt3ryZLl68aJBMxlS/2ty4cYNiYmIoNjbWIM8v4r6tcvr0afLw8KBGjRpRfHx8tQWYjXXRbyKinJwcOnTokKFjGC19168hzz0lSUQKtkKZwRAR/P39sXfvXnh6euLFF1/E33//jZiYGLRs2RLPP/88nnrqKfz+++84ePAgrKyscOzYMbi4uCiS7/r16+jXrx+ysrLQvn17DB48GCqVSnNGya1bt5CRkYEDBw5oLn975MgRNG/eXJF89XH+/Hm4uLhAkiTFvuMqcv1En3teXl4oKCjAyZMnaxxz+/Zt+Pv74+DBg3BwcMCff/7J+/Yh8GtDm+hzr8oHH3yA2NhY/P3335AkSecngEOGDMFHH32E9u3bK5LpwoUL6NWrF/Lz8+Ht7Q1fX1+d+3Xfvn1ITk5Gs2bNkJ6eDmdnZ0Xy1Ud+fj5WrVoFSZIQFRWlyHMaS/1EnHsAsGPHDrz44otwdnZGv379kJaWhosXL+I///kPxo0bhxkzZsDb2xvXr1/He++9hzNnzmDp0qUIDw9XLGNWVhamTZuG77//HgCq1a5q3Q5fX1+sXLlS0ctoG0P96sIQf9MAsfftvf755x+8+eabePvtt+Hh4YH169drju1kWcbEiRMNejbHw55FKQpjPQtVCaLPPaNguP4UU1p5eTnNmjWLzMzMdH6aXvXfXbp0ofT0dEWzTZo0iWRZpk8++eSBYz/++GOSZZkmT56sQLL6u3r1KoWEhFBoaKhizyl6/USee2+99RbJskwnTpyodVxZWRkNHjxY8U/8Rd+39cGvDW2iz737M+zatYsWL15MU6ZMoUmTJtG8efPo888/p6ysLMXzBAUFkYWFBX333XcPHLt3716ysLCgsWPHKpDMOBhT/USbe1XmzJlDJiYmJEkSWVhY0Pvvv09ERDExMVpnYkmSRF5eXlRRUaFYtuzsbGrWrJnmUtpxcXG0fft2OnDgAB04cIC2b99OcXFx5O3tTZIkUfPmzSk7O1uxfERi16+ubty4QVFRURQdHa3YcxrDvr3fL7/8Ql27diVLS0t666236J9//jHo2Ryin0VZV3wW6oOJNveMCZ9J9AS6cuUKtm7diuPHj+Ovv/6CWq2Gra0tOnXqhIEDB8LLywuyLCuaqXXr1ujXrx+2bt1ap/Evvvgijh49isuXL+s5mXEwlvqJOPcyMzMRGRkJPz8/BAcH1zq2vLwckydPRm5urtY6S/pkLPtWVCLXT/S5J7IWLVrAz88PGzdurNP44OBg7Nu3D3/99ZeekxkHrt/jce3aNeTk5EClUqFp06aa7YmJidi3bx8qKirQv39/vPTSS4r+bRs7dix27NiBnTt3al1FVJfvvvsOI0eOxKhRo7BlyxaFEt4lav1EZiz79n4VFRWIjIzE8uXL0b17d5w4cQITJkxQ/GwOYzmLsi74LNS6EWXuGR1Dd6kYIyKytLSkBQsW1Hn8/PnzydLSUo+JjAvXr+HifftouH4NU6NGjWj+/Pl1Hh8REUGNGjXSY6L6KSwspD///JPu3LljkOc39vqx2jVv3pyCg4PrPH78+PHUvHlzPSZij4ux79sjR46QSqUy2NkcxnQWpYiMuX6GnnvGhq9uxoTQpk0bJCcn13l8cnKy8N8VVhLXr+HifftouH6PR05ODpKSkvDHH3+goKAAsiyjRYsWeOaZZzB48GDFrzzUoUMHfPvtt1iyZAlMTWs/lKmsrMS3336r6Locly9fRm5uLvr06aN1BsSnn36K5cuXIysrC8DdS/UGBgZi2bJlaNGihWL5RK/fvUSbe8aguLgYjo6OdR7v6OiI4uJiPSZqWEpLS2FmZgYzMzPFn9vY923fvn1x9uxZFBcX13hFUX1KTEzEmDFjHngWFgD4+flh9OjR2LdvnwLJjIMx18/Qc8/oGLpLxcRQVFRE165dM9inmlXfQR83blytV2S4ePEi/fvf/yZZlhW9mkRxcTFdvny52vZ9+/bR4MGDyc7OjiwtLalz584UFRVFpaWlimUjEr9+tTH03Kuv/Px8ys3NVez5jGnf5ufnU2FhYa1jcnNzKTk5WaFExlW/B1F67hHdXf/Cz89Ps8bAvT9Vaw80b96cVq9erWiulStXatbkSE1NrXb1EiIitVpNKSkp5O3tTbIs06pVqxTLFxQURE5OTlrb5s2bR7Isk4mJCalUKnr22WfJzs6OJEmi9u3b0/Xr1xXLJ3r9iMSde3VlZ2dHs2bNMshzu7m5kZubG1VWVj5wbEVFBbm6upKbm5sCyerOkPU7c+YMTZgwgfz9/WnlypWa45M9e/ZorqhnampKnp6e9PPPPyuarSHsW0NqCGdR7tq1i06ePGmQ524I9WN1w02iJ0Rubq7ON2979uyh7t27a10GeuLEiXTz5k1F85WXl5Ovr6/mwM/FxYX8/f1p/PjxNH78ePL39ycXFxfNweHQoUMVXcQwLCyMHBwctLatWLFCk8fS0pKaN2+uyf/ss89SSUmJYvlErp/oc6++QkNDycTERLHnE3nfVklJSSFXV1fNvuzTpw8dPnxY51ilL+NuDPWrK6XnXl5eHjk4OJAkSdSjRw8KDAykHj16kCRJ5O7uTu+++y6FhISQvb09ybJMU6ZMUSybWq2miRMnavartbU1devWjQYMGEADBgygbt26kbW1tWa/Kn1qubOzM4WEhGhuZ2ZmkomJCXXp0oV+++03zfbKykqKjY0lSZJoxowZiuUTvX4iz726MuRXGoyhCfgghqpfdnY22draai3CO336dDpy5AiZmZmRlZUVeXh4UJs2bUiSJGrSpAmdO3dOsXwNYd8aUkNoskmSRJMmTTLIczeE+rG64SbRE0LXp+MJCQlkYmJCsiyTSqWivn37ko2NjeYg7Pbt24pmVKvVtG7dOurbt6/mihf3/piYmFDfvn1p/fr1Ov8o6lPHjh21vlN7+fJlsrCwoNatW9N3332nyXP9+nXNgfeiRYsUzShq/Yxh7tVHaGio4leSEHXfEt29uoaVlRVJkkSdOnUiV1dXkiSJTE1NKS4urtp4pZtERGLXrz6UnnthYWEkyzJt27ZNa/v27dvJxMSE1q1bR0R3zwZ86aWXSJZl+vrrrxXLR0T0ww8/UFBQEDk6Olbbr46OjhQUFERJSUmKZiKqvhbWJ598QrIsU2pqqs7xgwYNonbt2imU7r9ErZ/oc8/FxeWBP5IkkZ2dneZ2ly5dFMsnehNQ5PpNnjyZZFmmFStWUEZGBr333ntkbm5Onp6e9Oyzz9Kff/6pGfvxxx+TJElaDWF9E33fVvnrr79o2rRp5ObmRj169KD58+dTfn6+zrHR0dGKfQAiepMtPT39gT+SJFFAQIDWNqWIXj8iceeeseEm0RNCkiSKiYnR3C4uLiY7Ozuyt7engwcParaXlJRQUFAQybJMy5cvN0RUIiK6ffs2nTlzho4cOUJHjhyhM2fOUFlZmcHyWFlZaZ1euW7dOpJlmfbu3atzfO/evUmlUikVrxqR6mdsc+9BDNEkupdI+5aIKDg4mCRJoi+//FKzLT09nTp37kyyLFdrlhqiSXQv0epXH0rPPUdHRxo5cqTO+wIDA8nV1VVzu7y8nNq1a0fPP/+8UvGqKSkpoStXrtCVK1cUPZNTF3t7e5o2bZrmdlxcHMmyXGOu119/nSwsLJSKp5NI9RN97lW9Qb+/sXb/ZaDv36Y0UZuAItevU6dO5Ofnp7XN19eXZFmmtLS0auMHDRpEbdq0USTbvUTdt0REBQUF1KFDh2r7sFWrVjq/bq7kcYHoTbZ7LyFfnx+liF4/keeeseGFq59QiYmJKCgowOrVqzFw4EDNdisrK6xbtw6pqanYunUr5syZY5B8FhYW6NKli0GeWxdzc3OUl5drbl+7dg0A4OnpqXP8c889h9WrVyuSTRfR6ncv0eZe+/bt6zX+xo0bekpSN6Lt26SkJLzwwgsYPXq0ZluvXr2Qnp6OgIAAvP3227hz5w7efvttA6b8L5HqJ/rcu3HjBlQqlc77OnTogL1792pum5ubY9iwYfjiiy+UileNlZUVrKysDPb89+rRowf2798PIoIkSZo6njt3Dh4eHtXGnzt3Dvb29krH1CJS/USfe926dUN2djbi4+Px6quv6hwjyzImTpxo0Mss+/j4wMfHB8DdxZYLCwsBALa2tgbd1yLXLy8vDyNHjtTa5u7ujgMHDsDd3b3aeA8PD6SkpCiU7r9E3bcAsHTpUmRlZeHVV19FZGQkzMzMsHbtWsTGxmLo0KHYvn07/Pz8DJJNkiSsWbMGY8eOxZo1a5CcnIzTp09rjWnVqhWGDx+OSZMmwdvbW/GMjRs3RkBAAExMTKrdR0RISEiASqVCv379FM8mev1EnnvGhptET6iMjAxIkoThw4dXu8/S0hLPP/88duzYYYBkYnJ1dUVSUpLmdtXVjy5duoROnTpVG3/p0iXY2Ngols+YiDb3cnJyIMtyna9SUllZqedExuXatWtwc3Ortt3GxgZ79+6Fv78/4uPjoVarERcXZ4CE4hJ97jk4OODUqVM67zt16hRsbW21ttnY2KC0tFSJaMJ77bXXMGrUKMycORPvv/8+hg8fDpVKhalTp2Lnzp1o2bKlZuzatWuxd+9ehIaGGi6wYESfez/99BOio6MxY8YMbNu2DWvXroWTk5Niz/8wRGoCilw/W1tb3Lp1S2tb1e2CgoJqNSwoKDD4FfZE2rcAsGvXLnh4eODDDz/UbAsPD8eQIUMwbNgwBAYGYuvWrTqPA5UiapNt6dKliI6ORmZmJtatW4fOnTtXG5OQkAAvLy9uQOtgDHPPWMgPHsIaIrVaDeDugZguLVu2RFlZmZKR6uzWrVtISEhAQkKCYs8ZFhaGkydP4t133wUAjBgxAg4ODpg7dy5u376tNTYxMRE7duwwyKcPdWGI+t1LtLnn6OiIrl27oqysrE4/48aNUyxbfRli3zZr1qzaAXUVS0tL7NmzB4MGDcI777yD8PBwxXI9DKXrJ/rcGzp0KL7//nutgy0A+Oijj/D9999rDhCr5OXlaTU/RJGfn4/Y2FgsWbJEseccOXIkXnnlFaxevRqdO3fGwoULMWLECPz88894+umn4e3tjYCAAHTq1AmTJk1CixYtEBsbq1i++jBE/USfe2ZmZnjrrbeQlpaGK1euwM3NzaBnDxsbkevXqVMn7Nq1S3PZ+KKiIuzatQtNmjTBli1btMbeunULu3fv1vlh4ZMsJydH5zGwu7s7UlJS0KJFC7z44ovYvXu38uF0sLKyQqtWrdCqVSuDN9siIiLw008/oby8HB4eHli2bBmIyKCZHkSk+hnb3BOagb/uxhQiSRKFhYVRcnIyJScnU2xsLMmyTDk5OTrHh4aGUsuWLRVOWTfnzp3TfBdWKWq1moYPH06yLJO3tzetXr2alixZQqamptS6dWsKCQmhmTNn0uDBg0mWZWrSpAn9/vvviuWrD6XrJ/rc8/f3JzMzszovlm3oNYlqY4jXhqenJ3Xr1q3WMWVlZZrXhqOjI9fv/4g+9y5dukQtWrQgWZapVatW1KdPH2rVqhXJskw2NjZ0/vx5zdh//vmHWrRoQWPGjFEsX10Z4nVR5f3336emTZvWugaLr68vZWVlKZ6trgxRP2Oae7dv36bZs2eTiYkJeXp6UmZmJhEZ9upm9XHjxg2KiYmpdoEJpYhWv+3bt5MkSdS+fXsaN24cOTs7k4mJCX311Vdkbm5Or7/+On3zzTe0fv16cnNzI1mWKT4+XvGcdWGofWtvb09z5syp8f7s7Gxq27YtWVhY0M6dO3ldGB0qKyspKiqKzMzMqHfv3lrvKYzld4sh8Nx7fLhJ9IS4fyG0qtsbNmzQOb53797Uu3dvhVPWzdWrVykkJIRCQ0MVfd7y8nKaNWsWmZmZadXx/oP/Ll26KHqlgfpSun6iz72oqCiSJKnO+ywkJMQgC5DWhSFeG2+99RbJskwnTpyodVxVo8hQb9brQun6GcPcy8rKomHDhpGZmZnmqnUDBw6kkydPao0rKyuj1NRUunjxoqL56uLGjRsUFRVF0dHRBnn+srIy2rVrFy1evJimTJlCkyZNonnz5tHnn38udHOoiqHqZ2xzLzk5mdq3b09WVla0fPlyo3kjZ8gm6r1Eqt+cOXM0V8K0sLCg999/n4iIYmJitI5pJEkiLy8vqqioMEjOBzHUvu3Zsyf5+PjUOiYrK4vatm1L5ubm1K9fP4PPP10M3UAlIvrll1+oa9euZGlpSW+99Rb9888/RvO7xRD1ayhzTwQSkeDnsLHHIiYmRud2d3d3jBgxQmtbRkYGOnfujKlTp2LlypVKxDMqV65cwdatW3H8+HH89ddfUKvVsLW1RadOnTBw4EB4eXlBlvmbnFVEn3vZ2dlISUmBl5dXndZEyM/PR3FxMdq1a6f/cEYgMzMTkZGR8PPzQ3BwcK1jy8vLMXnyZOTm5mqt8fWkMqa5V15ejvz8fNjZ2aFRo0aKPz97chnT3CstLcXcuXPx6aefAoDBF66ui/z8fKxatQqSJCEqKsqgWUSq37Vr15CTkwOVSoWmTZtqticmJmLfvn2oqKhA//798dJLLwl7zGeofTt37lysWrXqgV8Dzc7Oho+PD/Ly8iBJEu7cuaNYxro4f/48XFxcDJ6toqICkZGRWL58Obp3744TJ05gwoQJwv9uMUT9GsrcEwE3iVg1xcXFyM/PR9OmTWFtbW3oOOwJwnOPMcaYsTt06BBOnjwJV1dXDBo0yNBxjA7Xz7ilpaXhxRdfxJw5czBv3rxax164cEHzZl20N+oiNVAB4OjRowgJCUFmZiY3oGvQUOaeCLhJxBhjjLEHunz5MjIyMrSuYqJSqdC6dWsDJ6vu1q1bKCsrQ/PmzQ3+KX9OTg6SkpLwxx9/oKCgALIso0WLFnjmmWcwePBgg18ZSReR6gcY19xjjDF9uXPnDoqLi2FhYQFLS0tDx2ENGDeJnjCVlZU4ffo0TE1N4ebmBkmSdI47deoUTpw48cCvjzwuJSUlKCwshKOjo9b2/fv3Y/ny5fj5559RVlYGJycnjBkzBhEREUKddl5cXIzS0lI0a9bMIAfUxlA/UedeTUpKSrBmzRqkpaWhpKQETk5OGDt2LJ577jmDZbp58yZMTU1hY2NT45iLFy8iJycHnp6eCiaru5s3b6K4uBht27Y1yHMbQ/1EmnsVFRVYsWIFPv/8c2RnZ+sc4+zsjEmTJmHmzJmwsLBQJNfly5eRm5uLPn36aP3O/fTTT7F8+XJkZWUBABo3bozAwEAsW7YMLVq0UCRblQsXLmDq1KnYv39/tfuICJIkwd7eHlFRUZg6daqi2YyhfqLOPV2MsYlVWloKMzMzmJmZGTqK0dWvadOmCAkJwYoVKwwdRSeR9i1jzEgZbDUkprivvvqK7O3tNQvu/etf/6ItW7boHKv0au9hYWHk4OCgtW3FihWahQEtLS2pefPmmgX4nn32WSopKVEsX25uLhUWFlbbvmfPHurevbumptbW1jRx4kS6efOmYtmIxK+fyHPPx8eHNm7cqLUtKyuLnJ2dq12NSJZlWrRokWLZqqSkpJCrq6umfn369KHDhw/rHCv6lRpCQ0PJxMRE0ecUtX6iz73i4mLq3bs3SZJE1tbWNHToUJo+fTotXLiQFi5cSNOnT6ehQ4eStbW1pq7FxcWKZAsKCiInJyetbfPmzSNZlsnExIRUKhU9++yzZGdnp7lS0fXr1xXJRkSUl5dHDg4OJEkS9ejRgwIDA6lHjx4kSRK5u7vTu+++SyEhIZrfi1OmTFEsG5H49RN57lUpLy+nuLg46tChg9bFGe79efrppyk+Pr7OVzB8nM6cOUMTJkwgf39/WrlyJd25c4eI7h63dOzYkWRZJlNTU/L09KSff/5Z8Xyi1682hl44WPR9e79Lly5RUlIS7dy5k3bu3ElJSUl06dIlQ8eq0a5du6otkM/qTqT6GdvcEwk3iZ4Q6enpZGJiQubm5uTr60vDhw8nS0vLGg9OlX6j2bFjRxo7dqzm9uXLl8nCwoJat25N3333HanVaiIiun79Ok2cOJEkSVL0DZMsy9VW509ISCATExOSZZlUKhX17duXbGxsNG8ClDyoEbl+os89SZIoJiZGa1uvXr1IkiQKDg6mtLQ0On/+PG3cuJEcHBxIlmVKTExULN+5c+fIysqKJEmiTp06kaurq+ZKP3FxcdXGG0OTSMl8ItdP9Lk3b948kiSJ5s+fX2tTuaSkhCIiIkiSJAoPD1ckm7OzM4WEhGhuZ2ZmkomJCXXp0oV+++03zfbKykqKjY0lSZJoxowZimQjutu4l2WZtm3bprV9+/btZGJiQuvWrSMioqKiInrppZdIlmX6+uuvFcsnev1EnntE4jexsrOzydbWVqvJPH36dDpy5AiZmZmRlZUVeXh4UJs2bUiSJGrSpAmdO3dOsXwi18/FxeWBP5IkkZ2dneZ2ly5dFMlGJP6+rWLsTcBJkyYZ7Pn/+usvmjZtGrm5uVGPHj1o/vz5lJ+fr3NsdHS04h+8PYih62fMc08k3CR6QowaNYrMzMwoNTVVsy03N5c8PT1JlmUKCQnRNBKIlH+jaWVlRfPnz9fcXrduHcmyTHv37tU5vnfv3qRSqZSKV+3NXHFxMdnZ2ZG9vT0dPHhQs72kpISCgoJIlmVavny5YvlErp/oc+/+fZuenk6SJGm9gapy9uxZMjc3p8DAQMXyBQcHkyRJ9OWXX2pl7Ny5s86zS7hJpE3k+ok+95ycnGjo0KF1Hj9kyJBqZ6foi6WlJS1YsEBz+5NPPiFZlrV+z9xr0KBB1K5dO0WyERE5OjrSyJEjdd4XGBhIrq6umtvl5eXUrl07ev7555WKJ3z9RJ57ROI3sSZPnkyyLNOKFSsoIyOD3nvvPTI3NydPT0969tln6c8//9SM/fjjj2v8vaMvItevqvFy75mc9//oul8pou9bIrGbgOnp6Q/8kSSJAgICtLYppaCgQNPcuHd+tWrVipKTk6uNV/qYT/T6iTz3jA03iZ4QDg4O9NJLL1XbXllZSWPHjiVJkmjcuHGaN+tK/9J56qmnaPbs2ZrbS5cuJVmWa3zhzp07lywsLJSKV+3N3M6dO0mSJPrwww+rjS0rK6M2bdpQnz59FMsncv1En3v379vVq1eTLMs1niobEBBAjo6OSsWjNm3a0LBhw6ptLywsJB8fH5JlWevNntL1c3Z2rtdP1R9mpYhcP9HnnoWFhVZtHmTBggWK/V6xt7enadOmaW7HxcWRLMs1vuF8/fXXFf2bYW5uXuOb2vDwcLK0tNTa9tprr1HTpk2ViEZE4tdP5LlHJH4Tq1OnTuTn56e1zdfXl2RZprS0tGrjBw0aRG3atFEqntD16969O1lbW9NHH31U4xhDft1M9H1LZBxNwPr+KKWqHq+99hpdvXqVbty4QfHx8dS4cWNq1KhRtQ9/DXHMLHL9RJ57xsbU0GsiMWXcvHkTKpWq2nZTU1Ns3rwZZmZmSEhIgFqtxqZNmxTP5+rqiqSkJM3tNm3aAAAuXbqETp06VRt/6dKlWhef1beMjAxIkoThw4dXu8/S0hLPP/88duzYoVgekesn+ty7361btwAAHTt21Hl/x44dsXfvXsXyXLt2DW5ubtW229jYYO/evfD390d8fDzUajXi4uIUy1UlJycHsizXeYHMyspKPSfSJnr97iXa3HNwcMCJEyfqPP748eNwcHDQX6B79OjRA/v379csAF31O+bcuXPw8PCoNv7cuXOwt7dXJBtwt3anTp3Sed+pU6dga2urtc3GxgalpaVKRANgHPUTde4BwNWrVxEUFFTn8T179kRycrIeE2nLy8vDyJEjtba5u7vjwIEDcHd3rzbew8MDKSkpCqUTu34//fQToqOjMWPGDGzbtg1r166Fk5OTIs9dF6LvWwDYunUrfH19sXTp0lrHWVlZIS4uDr/++iu++uorxMfHK5KvcePGCAgIgImJSbX7iAgJCQlQqVTo16+fInnutWvXLnh4eODDDz/UbAsPD8eQIUMwbNgwBAYGYuvWrTrffyhF5PqJPveMieGva8oU4eDggOvXr+u8T5IkrF+/HuPHj8d//vMf/Pvf/8Y///yjaL6wsDCcPHkS7777LgBgxIgRcHBwwNy5c3H79m2tsYmJidixYwe8vb0VzXgvtVoNADUelLZs2RJlZWWK5RG5fqLPvaocVaquEFdcXKxzbElJCaysrBTJBQDNmjXTNA/uZ2lpiT179mDQoEF45513EB4erliuKo6OjujatSvKysrq9DNu3DhF84leP5HnXmBgIPbv34+FCxfW+vusrKwMb7zxBg4cOIBRo0Ypku21115DZmYmZs6cCbVajeHDh0OlUmHq1Km4du2a1ti1a9di7969GDp0qCLZAGDo0KH4/vvvtQ70AeCjjz7C999/Dx8fH63teXl5aNmypWL5RK+fyHMPEL+JZWtrW+33XtXtgoKCauMLCgpgbm6uRDQAYtfPzMwMb731FtLS0nDlyhW4ublh9erVijx3XYi+b4G7TcAePXrUeXzPnj1x9epVPSb6r6VLl6KyshKZmZmIiIjA+vXrtX42bNgAAPDy8tLarpScnBydx+fu7u5ISUlBixYt8OKLL2L37t2KZbqX6PUTee4ZHcOeyMSUMmTIkAeuQaNWqzXrd9jY2Ch6eqBarabhw4eTLMvk7e1Nq1evpiVLlpCpqSm1bt2aQkJCaObMmTR48GCSZZmaNGlCv//+u2L5JEmisLAwSk5OpuTkZIqNjSVZliknJ0fn+NDQUGrZsqVi+USun+hzr2oByqqvQzk6OpIsy5SUlKRz/PDhw6lTp06K5fP09KRu3brVOqasrEyzb6vyK8Xf35/MzMzqvPif0msSiVw/0eferVu3yN3dXfO69PPzoxkzZlBkZCRFRkbSjBkzyM/PT2vB/lu3bimWb9KkSSRJEqlUKnr99dcpPDycTE1NqXHjxuTl5UUjRozQXOnHwcFB0SuaXLp0iVq0aEGyLFOrVq2oT58+1KpVK5JlmWxsbOj8+fOasf/88w+1aNGCxowZo1g+IrHrJ/rcmz17NsmyTG+88QaVlpbWOK60tJQWLFhAsizTnDlzFMvn7e1NrVu3pqKiIiK6W09HR0eysbGhZcuWaY0tLCykli1bUs+ePRXLJ3r9qty+fZtmz55NJiYm5OnpSZmZmURk2K+bib5viYjatWtX7StxtfH19VV0zbPTp0+Th4cHNWrUiOLj47XWxSQy7P61t7evda5nZ2dT27ZtycLCgnbu3GmQdShFrp/oc8+YcJPoCbFixQqSJKnGyz5XUavVFBISovnOqZLKy8tp1qxZZGZmpvkOq65FArt06aLoImhE1b+DW3V7w4YNOsf37t2bevfurWhGUesn+txr164dOTk5Vfu5/2p2RHcPWG1sbOjll19WLN9bb71FsizTiRMnah1X1ehQun5RUVEkSVKd51TVPlaKyPUTfe4R3f3e/uLFi6l169Y1LuLaunVrioqKqvX7//ry/vvvU9OmTWtdbNbX15eysrIUz5aVlUXDhg0jMzMzzRX1Bg4cWG3NqbKyMkpNTaWLFy8qnlHk+ok890RvYm3fvp0kSaL27dvTuHHjyNnZmUxMTOirr74ic3Nzev311+mbb76h9evXk5ubG8myTPHx8YrlE71+90tOTqb27duTlZUVLV++3KBvgkXft0TG0QSsrKykqKgoMjMzo969e2t9cGrI/duzZ0/y8fGpdUxWVha1bduWzM3NqV+/fga5WImo9TOGuWcsJCIiQ5/NxPTvypUrWLVqFXr37o2AgIBaxxIRYmJikJubq+gpglWuXLmCrVu34vjx4/jrr7+gVqtha2uLTp06YeDAgfDy8oIsK/tNyZiYGJ3b3d3dMWLECK1tGRkZ6Ny5M6ZOnYqVK1cqEU+LaPUzprn3IOfPn8cXX3wBHx8feHp6KvKcmZmZiIyMhJ+fH4KDg2sdW15ejsmTJyM3N1drjSp9ys7ORkpKCry8vOq0bkN+fj6Ki4vRrl07/YeD+PWrK0PMvftlZGQgIyMDhYWFAO5+7UGlUulcc0xJt2/fxvfff49ffvml2u88Hx8ftG/f3qD5ysvLkZ+fDzs7OzRq1MigWXQRvX6AmHOvtLQU8fHxWLt2La5cuaJzjKOjIyZOnIjw8HBFvyoKAHPnzsUHH3wAtVoNc3NzxMfHY+bMmYiNjUV0dLTmq65EBE9PTxw4cKDOa8s9DqLX736lpaWYO3cuPv30UwDAxIkT8dlnnxkki+j7tqioCJ6enjh58iSsra3Rv39/qFQqzVpshYWFyMjIQFpaGoqKitC9e3ccPnwY1tbWimWscvz4cQQHByMrKwuRkZGIiIiAmZmZwfbv3LlzsWrVqgd+BTk7Oxs+Pj7Iy8uDJEm4c+eOgin/S7T6GdPcEx03iRh7zIqLi5Gfn4+mTZvyLx3GWIO2e/duODk5oVu3boaOwp4wIs09EZtYwN2F+3NycqBSqdC0aVPN9sTEROzbtw8VFRXo378/XnrpJcU/fLuXqPXT5dChQzh58iRcXV0xaNAgg+UQfd8aUxOwoqICkZGRWL58Obp3744TJ05gwoQJBmlypKWl4cUXX8ScOXMwb968WsdeuHBB0ygyVJMIEKt+gHHNPZFxk4gxxhhjD0WWZYN+om4sLl++rPNNcOvWrQ2czHjx3GPMOBhLE/Do0aMICQlBZmYm/255CCLWz1jmnohMDR2AsbooLi5GaWkpmjVrZtBPuyorK3H69GmYmprCzc1N68pE9zp16hROnDjxwK+3KEWU+jH9u3nzJoqLi9G2bVuD5igpKcGaNWuQlpaGkpISODk5YezYsXjuuecMmutBRKmfCI4dO1ancdevX9ca26tXL31F0iknJwdJSUn4448/UFBQAFmW0aJFCzzzzDMYPHiw4lf2qVJRUYEVK1bg888/R3Z2ts4xzs7OmDRpEmbOnAkLCwuFE94lYv2MZe4Z6zGBKIyhftzgfXTG8qa8b9++OHv2LIqLiw32+9iYiVg/Y5l7QjLUYkiM3Ss3N5cKCwurbd+zZw91795dsxCztbU1TZw4kW7evKl4xq+++ors7e01Wf71r3/Rli1bdI5V+moDxlA/pozQ0FAyMTFR7Pl8fHxo48aNWtuysrLI2dm52kK4sizTokWLFMv2MJSun8juX7C/rj9Kyc7OJj8/P50ZqrI3b96cVq9erVimKsXFxdS7d2+SJImsra1p6NChNH36dFq4cCEtXLiQpk+fTkOHDiVra2uSZZn69OlDxcXFimYUuX6izz0isY8J6sLOzo5mzZplsOcXuX7l5eUUFxdHHTp0qHGuPf300xQfH1/nK3sqydD7tr4+//xzCgsLM3QMIV26dImSkpJo586dtHPnTkpKSlL0SpMNHc+9mvGZREwIzs7OiI6ORmRkpGbbpk2bEBYWBiLC008/jWbNmuHMmTNYu3Ytfv75Z/z444+KdaqPHTuGoKAgmJiYYPDgwTAzM0NiYiLGjx+PlJQUfPzxx4rkqIno9WPKIgW/RXzo0CF4e3trbQsKCkJOTg7Gjx+PyZMno1mzZvjxxx8RERGBt99+G97e3gZdy+FBlKyf6Bo3boyAgACYmJhUu4+IkJCQAJVKhX79+ima69KlS+jXrx+uXbsGd3d3ODs748KFCzhx4gS6d++OcePG4fTp0/jmm28wY8YM/Pbbb4r+no6JicGxY8cQERGByMjIGtc8KC0tRWxsLJYtW4bY2FjEx8crkk/0+gHizj1A/GOCuigoKEBJSYlBnlvk+pWUlGDQoEE4duwYmjRpgiFDhkClUsHGxgYAcOvWLc3CtwsWLMDXX3+NxMRENG7c2GCZ72fIffswUlNTkZCQgHXr1hk6ihCM5SzUhoDnXi0M2aFirIokSRQTE6O5XVxcTHZ2dmRvb08HDx7UbC8pKaGgoCCSZZmWL1+uWL5Ro0aRmZkZpaamarbl5uaSp6cnybJMISEhpFarNfcp/amX6PVjygkNDTXo3EtPTydJkigkJKTa2LNnz5K5uTkFBgYqlq++lK6fyOLi4sjS0pL69u1LZ8+e1TnGUJe6DQsLI1mWadu2bVrbt2/fTiYmJrRu3ToiIioqKqKXXnqJZFmmr7/+WrF8Tk5ONHTo0DqPHzJkCDk5OekxkTbR6yfy3CMS/5jAxcXlgT+SJJGdnZ3mdpcuXRTLJ3L95s2bR5Ik0fz586mkpKTGcSUlJRQREUGSJFF4eLgi2YjE37cPQ+m/u3/99RdNmzaN3NzcqEePHjR//nzKz8/XOTY6OlrRs4uN4SxUketXX3zMVzM+k4gJKTExEQUFBVi9ejUGDhyo2W5lZYV169YhNTUVW7duxZw5cxTJk5aWhoCAAPTv31+zrW3btjh48CBCQkKQkJCAO3fuICEhocbv1CtJtPqxh1ffy0/fuHFDT0nq5qeffoIkSTrnVufOnfHCCy/gxx9/VCyPsdVPJBERERg2bBhCQkLg4eGB6OhozJs3T4jfcfv378eIESMwatQore2BgYEYMWIE3nvvPYSFhaFJkybYvHkzjh07hg8//BABAQGK5Lt69SqCgoLqPL5nz55ITk7WYyJtotdP5LkHiH9McO7cOUiSVOtZkZIkoaCgAAUFBcoF+z8i12/r1q3w9fXF0qVLax1nZWWFuLg4/Prrr/jqq68UOwtQ9H0LAAkJCfUan5mZqack1RUWFqJfv37Izs7W1PDEiRPYuHEjvvjiC3h6elb7N7XV+nET/SxU0esn8twzNtwkYkLKyMiAJEkYPnx4tfssLS3x/PPPY8eOHYrluXnzps6Fz0xNTbF582aYmZkhISEBarUamzZtUixXTUSrH3t4OTk5kGUZZmZmdRpfWVmp50S1u3XrFgCgY8eOOu/v2LEj9u7dq1geY6ufaFxdXZGeno4333wTixYtwo4dO7B+/Xq4uLgYNNeNGzdqXIyyQ4cOWnPM3Nwcw4YNwxdffKFUPDg4OODEiRN1Hn/8+HE4ODjoL9B9RK8fIO7cA8Q/JujWrRuys7MRHx+PV199VecYQ14dTuT6id7gFX3fAkBoaGi9mntEpFgzcOnSpcjKysKrr76KyMhImJmZYe3atYiNjcXQoUOxfft2+Pn5KZJFF9GblKLXT+S5Z2y4ScSEpFarAaDGg+aWLVuirKxMsTwODg64fv26zvskScL69etBRNi0aRPUajU6dOigWDZdRKsfe3iOjo6wt7fHyZMn6zQ+NDRU8YPqe//AOjo6Arh7RT1LS8tqY0tKSmr8ZEwfjKF+ojM1NUV0dDT8/f0RHBwMDw8PREZGIiIiwmCZHBwccOrUKZ33nTp1Cra2tlrbbGxsUFpaqkQ0AHfPyPnggw+wcOFCLFq0CI0aNdI5rqysDEuWLMGBAwcwa9YsxfKJXr8qIs49QPxjgp9++gnR0dGYMWMGtm3bhrVr18LJyUnRDLURuX6iN3hF37fA3cayo6MjJk+eXKfxW7duxa+//qrnVHft2rULHh4e+PDDDzXbwsPDMWTIEAwbNgyBgYHYunWrzg9ZlSB6k1L0+ok894yOgb7mxpgWSZIoLCyMkpOTKTk5mWJjY0mWZcrJydE5PjQ0lFq2bKlYviFDhpBKpap1jFqtpuDgYJIkiWxsbBRfF0bk+rGH5+/vT2ZmZnW+gooh1iSys7MjZ2dncnZ2JkdHR5JlmZKSknSOHz58OHXq1EmxfKLXz9iUl5dTeHg4mZiYkIeHB8mybJB1YSZNmkSyLFe78taHH35IsizTyy+/rLX93//+N7Vr106xfLdu3SJ3d3fN3wM/Pz+aMWMGRUZGUmRkJM2YMYP8/PzIxsaGJEkid3d3unXrlmL5RK+fLqLMPSLxjwmqpKenU+fOnalJkya0atUqrfsMuaaTyPWbPXs2ybJMb7zxBpWWltY4rrS0lBYsWECyLNOcOXMUyXYvUfctEdEzzzxDLVq0qPN4Jf/uWlpa0ty5c3Xel5WVRW3btiULCwvatWsXESm/nli7du3Iz8+vzuN9fX0V/d0sev1EnnvGhptETAj3X+626vaGDRt0ju/duzf17t1bsXwrVqwgSZLo8OHDtY5Tq9UUEhKiya8U0evHHl5UVBRJkkTp6el1Gl81/5TSrl07cnJyqvYTGxtbbWxpaSnZ2NhUewOqT6LXz1gdOXKEVCqVwd6MXLp0iVq0aEGyLFOrVq2oT58+1KpVK5JlmWxsbOj8+fOasf/88w+1aNGCxowZo2jGkpISWrx4MbVu3ZokSdL507p1a4qKiqp1gVx9MIb61cTQc49I/GOCe92+fZtmz55NJiYm5OnpSZmZmURk2EaCyPUTvcF7LxH3LRHR5MmTSZZlunjxYp3GK/lG3d7evtamXnZ2tqbRsXPnTsWbHKI3KUWvn8hzz9jw182YEKKionRuf+qpp6pty8jIwE8//YSpU6fqOdV/jR49GteuXUN+fn6t46pOk3ZyckJubq5C6cSvH3t4wcHBcHZ2RosWLeo0fvny5YiJidFzqv/Kycmp89iLFy9izpw58PHx0V+g+4heP2PVt29fnD17FsXFxQa5/G7r1q1x9OhRzJgxA99//z3+/PNPmJiYwNvbGytWrNBaE6uyshI7duxA27ZtFc1oZWWFmJgYxMTEICMjAxkZGSgsLAQA2NraQqVS1bgukL4ZQ/1qYui5B4h/THAvCwsLvPfeewgICEBYWBi6deuGJUuWGCRLFZHrZ21tjbS0NMTHx2Pt2rXYt28f9u3bV22co6MjZs+ejfDwcEW/Qn0vEfctAAwYMAD79+9HRkYG2rRp88Dxzz33nAKp7nJycqr160XOzs5ISkqCj48PRo8ejWeeeUaxbMDdhauTkpKwdOlSrF69Gv3794dKpdJ8BbiwsBAZGRlIS0tDUVERunfvjujoaMXyiV4/keeesZGIFFxynLHHoLi4GPn5+WjatCmsra0NHcfocP0YYw1JeXk58vPzYWdnV+PaPyLavXs3nJyc0K1bN4PmMNb6sforLS3F3Llz8emnnwKAQRc3NhaiNXhrwvu2bubOnYtVq1YhLy8PLVu2rHFcdnY2fHx8kJeXB0mScOfOHcUylpaWapqUV65c0TnG0dEREydOVLxJaQz1Y48HN4kYY4wxxhRm6CsQsSfXoUOHcPLkSbi6umLQoEGGjsMeI963tUtLS8OLL76IOXPmYN68ebWOvXDhgqbRYagmh2hNSmOrH3t43CRiQqmsrMTp06dhamoKNze3Gi9LeOrUKZw4cQLBwcEKJxQb1+/JUVJSgjVr1iAtLQ0lJSVwcnLC2LFj+dTZOuL6NSyXL1/WeSDdunVrg+Q5duzYA8f06dMHI0aMwIIFCzTbevXqpc9YNRKtfowZGh9PMcaeaIZcEImxe3311Vdkb2+vWXz5X//6F23ZskXnWKUXQjMGXL+GycfHhzZu3Ki1LSsri5ydnTWLlFf9yLJMixYtMlBSMXH9Gq7y8nKKi4ujDh06aC3cf+/P008/TfHx8XW+ut3jcv/FBOr6oySR68cer0uXLlFSUhLt3LmTdu7cSUlJSXTp0iVDxxKWMR1P8b59sn3++ecUFhZm6BisAeKFq5kQjh07hqCgIJiYmGDw4MEwMzNDYmIixo8fj5SUFHz88ceGjig0rl/DdejQIXh7e2ttCwoKQk5ODsaPH4/JkyejWbNm+PHHHxEREYG3334b3t7efJr5/+H6NUwlJSUYNGgQjh07hiZNmmDIkCFQqVSwsbEBANy6dUuzuOeCBQvw9ddfIzExEY0bN1YsY+PGjREQEAATE5Nq9xEREhISoFKp0K9fP8UyVTGG+rFHU1FRgRUrVuDzzz9Hdna2zjHOzs6YNGkSZs6cabBFwEVjDMdTvG8fH2M/izI1NRUJCQlYt26dQZ7f2OvHamHoLhVjRESjRo0iMzMzSk1N1WzLzc0lT09PkmWZQkJCSK1Wa+4z9Cc3ouH6NVySJFFMTIzmdnp6OkmSRCEhIdXGnj17lszNzSkwMFDBhGLj+jVM8+bNI0mSaP78+bVePr6kpIQiIiJIkiQKDw9XLF9cXBxZWlpS37596ezZszrHGPIy1aLXjz2a4uJi6t27N0mSRNbW1jR06FCaPn06LVy4kBYuXEjTp0+noUOHkrW1NcmyTH369KHi4mJDxxaC6MdTvG8fXUM6i9IQl3BvSPVjNeMziZgQ0tLSEBAQgP79+2u2tW3bFgcPHkRISAgSEhJw584dJCQk1Pi98CcZ1+/J8dNPP0GSJMyZM6fafZ07d8YLL7yAH3/80QDJjAPXr2HYunUrfH19sXTp0lrHWVlZIS4uDr/++iu++uorxMfHK5IvIiICw4YNQ0hICDw8PBAdHY158+YJ8/tX9PqxRxMTE4Njx44hIiICkZGRNV79qLS0FLGxsVi2bBliY2N5/0L84ynet49G9LMoExIS6jU+MzNTT0l0E71+7PHhJhETws2bN3Wu1G9qaorNmzfDzMwMCQkJUKvV2LRpkwESio3r9+S4desWAKBjx4467+/YsSP27t2rZCSjwvVrGK5evYqgoKA6j+/ZsyeSk5P1mKg6V1dXpKen480338SiRYuwY8cOrF+/Hi4uLorm0MUY6sceHjcBH57ox1O8bx+N6E220NDQejUfiUjRZqXo9WOPDzeJmBAcHBxw/fp1nfdJkoT169eDiLBp0yao1Wp06NBB4YRi4/o1bPceADg6OgIAiouLYWlpWW1sSUlJjX+0n1Rcv4bHwcEBJ06cqPP448ePw8HBQX+BamBqaoro6Gj4+/sjODgYHh4eiIyMREREhOJZ7mUs9WMPh5uAD0/04ynet49G9Cabubk5HB0dMXny5DqN37p1K3799Vc9p9J+PpHrxx4fbhIxIXTu3BmHDh2q8X5JkrBhwwYAwKZNm2Btba1MMCPB9WvYVqxYgfXr1wMAysvLAQC//fZbtQWZASA3NxctW7ZUMp7wuH4NT2BgID744AMsXLgQixYtQqNGjXSOKysrw5IlS3DgwAHMmjVL2ZD38PDwwPHjxxEZGYnFixdj+/btBv3qmbHVj9UPNwEfnujHU7xvH43oTTY3NzdcvHixzh8knDt3TtEmkej1Y4+PbOgAjAGAn58fMjMzkZKSUuOYqj/MwcHBKCoqUjCd+Lh+DVfbtm1ha2sLIgIRwdzcHG3bttW5r8vKynD48GH06NHDAEnFxPVrmGJiYtCtWzcsXboUDg4OeOGFFzBz5kwsXrwYixcvxsyZM/HCCy/AwcEBcXFx6NatG6Kjow2a2dzcHPHx8UhJSUFRURGIyGBZjLF+rO4CAwOxf/9+LFy4EGVlZTWOKysrwxtvvIEDBw5g1KhRCiYUl+jHU7xvH43oTbaePXvixo0byMvLU+w560P0+rHHh88kYkIYPXo0rl27hvz8/FrHVZ3q6+TkhNzcXIXSiY/r13Dl5OTUeezFixcxZ84c+Pj46C+QkeH6NUzW1tZIS0tDfHw81q5di3379mHfvn3Vxjk6OmL27NkIDw8X5muEffv2xdmzZ1FcXGywS1Mbc/3Yg8XExCApKQlLly7F6tWr0b9/f6hUKtja2gIACgsLNYvLFhUVoXv37twE/D+iH0/xvn00op9FOWDAAOzfvx8ZGRlo06bNA8c/99xzCqT6L9Hrxx4fiQz5URZjjDHG2CPKyMhARkYGCgsLAQC2trZQqVQ6F6Bl1XH9Gp7S0lJNE/DKlSs6xzg6OmLixIncBDQyvG8fXlFRETw9PXHy5ElYW1vXqcl2+PBhXqbh/3D9nhzcJGKMMcZYg7N79244OTmhW7duho5ilLh+DQc3ARsu3rf1x022R8P1ezJwk4gxxhhjDY4sy5g4cSI+++wzQ0cxSlw/xlhDx022R8P1a7h4TSLGGGOMGZVjx47Vadz169e1xvbq1UtfkYwK1+/JUFlZidOnT8PU1BRubm41XlHv1KlTOHHiBIKDgxVOyB4W79vHgxsaj4br13DxmUSMMcYYMyqyLD/UJeTv3LmjhzTGh+vX8G3duhWvvvoq/v77bwB3v/4RHx+PsWPHVhsbExOD2NhY3r9GgvetctauXYu0tDSsW7fO0FGMEtfPePGZRIwxxhgzOo0bN0ZAQABMTEyq3UdESEhIgEqlQr9+/QyQTnxcv4br2LFjCAoKgomJCQYPHgwzMzMkJiZi/PjxSElJwccff2zoiOwh8b5VVmpqKhISErjJ8ZC4fsaLm0SMMcYYMypLly5FdHQ0MjMzsW7dOnTu3LnamISEBHh5efGaOjpw/Rq2ZcuWQZZl/PDDD+jfvz8A4OLFixg/fjw+++wzlJWVYf369Q91NhkzLN63jDElcJOIMcYYY0YlIiICw4YNQ0hICDw8PBAdHY158+bxG6M64vo1bGlpaQgICNA0EQCgbdu2OHjwIEJCQpCQkIA7d+4gISGB97mR4X37aBISEuo1PjMzU09JjBPX78nBTSLGGGOMGR1XV1ekp6fjzTffxKJFi7Bjxw6sX78eLi4uho5mFLh+DdfNmzd1LiZramqKzZs3w8zMDAkJCVCr1di0aZMBErKHxfv20YSGhtareUZE3Gy7B9fvycFNIsYYY4wZJVNTU0RHR8Pf3x/BwcHw8PBAZGQkIiIiDB3NKHD9GiYHBwdcv35d532SJGH9+vUgImzatAlqtRodOnRQOCF7WLxvH425uTkcHR0xefLkOo3funUrfv31Vz2nMh5cvycHN4kYY4wxZtQ8PDxw/PhxREZGYvHixdi+fTt/elkPXL+GpXPnzjh06FCN90uShA0bNgAANm3aBGtra2WCsUfG+/bRuLm54eLFi3VuhJ87d46bHPfg+j05ZEMHYIwxxhh7VObm5oiPj0dKSgqKiopARIaOZFS4fg2Hn58fMjMzkZKSUuOYqmZCcHAwioqKFEzHHgXv20fTs2dP3LhxA3l5eYaOYpS4fk8OPpOIMcYYYw1G3759cfbsWRQXF8PCwsLQcYwO18/4jR49GteuXUN+fn6t46q+nuTk5ITc3FyF0rFHwfv20QwYMAD79+9HRkYG2rRp88Dxzz33nAKpjAfX78khEX9UxBhjjDHGGGOMMfbE46+bMcYYY4wxxhhjjDFuEjHGGGOMMcYYY4wxbhIxxhhjjDHGGGOMMXCTiDHGGGMGdujQIUiShOjo6DqN9/b21tsl2qOjoyFJUq2XmTYGTk5OcHJyeqTHyMnJgSRJCA0NfSyZGGOMMSY+bhIxxhhjzOht2LBBc+lnxhhjjDH2cEwNHYAxxhhjrD4SEhJQWlqql8eeNm0aXn75ZbRt21Yvj88YY4wxJjJuEjHGGGPMqOizgdOsWTM0a9ZMb4/PGGOMMSYy/roZY4wxxoSRmpoKb29vWFtb46mnnsKoUaOQmZmpNeb+NYlCQ0MRFhYGAAgLC4MkSZqfKlevXsXMmTOhUqnQqFEjPPXUU3BxccGUKVNQWFioGadrTaKq56vp5/41e4qKihAVFYWuXbtqnsvX1xepqakPXZekpCT87//+Lzp16oQmTZqgSZMmeOaZZ/DZZ5/V+THu/X9bu3Yt3NzcYGlpidatW2P27NkoKiqq8d9mZmZi5MiRsLOzQ+PGjfH888/j5MmTesnJGGOMMcPhM4kYY4wxJoQff/wRS5cuxdChQzF9+nScOXMGX3/9NVJSUvDjjz+iffv2Ov9dQEAACgoKsGvXLowYMQLu7u5a95eWlqJ///7IycnBkCFDMHLkSFRUVODChQvYtGkTXn/9ddja2taYKzQ0FN7e3tW2f/fddzh27BisrKw0227evAlPT0+cOXMG/fv3x5QpU3Dr1i3s2rULPj4+2Lp1KwICAupdm/j4eGRmZqJPnz4YOXIkCgoKsG/fPkyePBnnz5/H8uXL6/xY7733Hg4ePIgxY8Zg2LBhSExMxPvvv48ff/wRhw8fhpmZmdb4nJwc9OnTB127dsX//u//IisrS/P/c/bsWbRs2VIvORljjDFmAMQYY4wxZkBJSUkEgADQJ598onXfJ598QgBo+PDhmm1eXl50/yHM+vXrCQCtX7++2uPv3r2bANCsWbOq3VdUVES3b9/W3I6KiiIAlJSUVGvmw4cPk7m5ObVv356uX7+u2T527FgCQGvWrNEaf+3aNWrTpg01b96cysrKan1sXbKzs6ttq6yspMGDB5OJiQnl5uZq3deuXTtq166d1raq/zdzc3M6efKkZrtardbkfvfddzXbL1y4oNkvcXFxWo+1aNEiAkBLly59pJyMMcYYEwt/3YwxxhhjQujYsSNeeeUVrW2vvPIKVCoVvv32W1y/fv2RHr9Ro0bVtjVp0gQWFhb1epyqr15ZWVnh22+/1axhdOPGDXz55ZcYOHAgJk6cqPVvWrRogXnz5uH69etITEysd3ZnZ+dq20xNTTFlyhTcuXMHSUlJdX6s4OBgdOvWTXNbkiS8/fbbMDEx0Xl1OGdnZ8ybN09r24QJEwAAP/30k95yMsYYY0x5/HUzxhhjjAmhf//+kGXtz69kWUb//v2RkZGBkydP4vnnn6/343p6eqJVq1aIi4vDyZMnMXz4cHh5ecHFxUVr3aK6+PvvvzFs2DAUFhZi37596Ny5s+a+n376CXfu3EF5eTmio6Or/duMjAwAwLlz5zB8+PB6PW9RURHeffdd7Ny5E1lZWSgpKdG6/8qVK3V+rAEDBlTb1q5dO7Rp0wZnzpxBRUUFzM3NNfe5u7tX2y//+te/AAAFBQV6y8kYY4wx5XGTiDHGGGNCuHdtG13b711guj5sbW3x448/YvHixdizZw/27t0LAGjTpg3mz5+P1157rU6PU1lZicDAQPzxxx/47LPPMGjQIK37b968CQBIS0tDWlpajY9zf+PkQSoqKuDt7Y3jx4+jR48eGD9+POzt7WFqaoqcnBxs3LgR5eXldX682uqck5ODoqIi2Nvba7bb2NhUG2tqevcQ8s6dO3rLyRhjjDHlcZOIMcYYY0K4du1ardtrW1z6Qdq2bYsNGzZArVbj1KlT+P7777Fy5UpMnToVdnZ2CAoKeuBjTJ48GYcOHcLcuXOrfS0O+G8zZe7cuXj33XcfOuv9du3ahePHj2PChAn4/PPPte774osvsHHjxno9Xm11liQJ1tbWQuRkjDHGmPJ4TSLGGGOMCSEtLQ1qtVprm1qtxpEjRyBJErp3717jvzUxMQGgfWaLLrIsw93dHeHh4fjPf/4DANi9e/cDsy1duhTr16/HiBEjsGzZMp1jnn32WUiShKNHjz7w8eojKysLADBixIhq96WkpNT78XT9m9zcXOTl5aFr165aXzWrj8edkzHGGGPK4yYRY4wxxoTwxx9/YM2aNVrb1qxZgz/++APDhg1D8+bNa/y3TZs2BQDk5eVVu+/MmTM6z56p2mZpaVlrrm3btmHhwoXw8PDAli1bqq3PU8XBwQGjR4/GkSNH8M4774CIqo1JT09HaWlprc93v3bt2gEAUlNTtbYnJydXq1ddJCQk4NSpU5rbRIQ33ngDd+7cQWhoaL0fT185GWOMMaY8/roZY4wxxoTg6+uLGTNmYO/evejatSvOnDmDPXv2oFmzZvjggw9q/bd9+/ZFo0aN8P777+Pvv//WNJQWLVqEAwcOYN68eejfvz86duwIe3t7ZGdnY/fu3bC0tMTUqVNrfezg4GAQETw8PPDOO+9Uu9/d3R0BAQEAgI8++gjnz59HeHg4Nm3ahL59++Kpp55CXl4efv75Z2RkZODq1auwsrKqc13+53/+B05OTli2bBl+++03uLq64vz58/jmm28wcuRIbNu2rc6PBdytc9++ffHyyy+jefPmOHjwIH7++Wf06dMH06dPr9dj6TMnY4wxxpTHTSLGGGOMCaFPnz5YtGgRFi1ahJUrV8LExAQBAQFYtmwZ2rdvX+u/bdq0KbZt24bo6GisWbMGZWVlAO42iXx9fZGTk4PDhw9jx44dKC4uRuvWrTFmzBiEh4ejS5cutT521WPdv85OlZCQEE2TqGnTpjhy5AhWr16NL7/8Elu2bIFarYaDgwO6d++OyMhINGvWrF51adKkCX744QfMmzcPhw8fxqFDh9C1a1ds2bIFLVu2rHfzZc6cOfD398f777+PzMxMNG3aFDNnzsSSJUse+qtm+sjJGGOMMeVJpOtcaMYYY4wx1qBER0cjJiYGSUlJ8Pb2NnQcxhhjjAmI1yRijDHGGGOMMcYYY9wkYowxxhhjjDHGGGO8JhFjjDHGmOJ27tyJEydOPHCct7c3fzWMMcYYY4rhNYkYY4wxxhQWGhqKjRs3PnBcVFQUoqOj9R+IMcYYYwzcJGKMMcYYY4wxxhhj4DWJGGOMMcYYY4wxxhi4ScQYY4wxxhhjjDHGwE0ixhhjjDHGGGOMMQZuEjHGGGOMMcYYY4wxcJOIMcYYY4wxxhhjjIGbRIwxxhhjjDHGGGMM3CRijDHGGGOMMcYYY+AmEWOMMcYYY4wxxhgDN4kYY4wxxhhjjDHGGID/D+nbHcBijQ7pAAAAAElFTkSuQmCC", "text/plain": [ "
" ] @@ -663,39 +683,49 @@ "source": [ "# Best Fingerprint Method / Performance\n", "from collections import defaultdict\n", + "\n", "res_dict = defaultdict(list)\n", "for i, row in df_training_stats.iterrows():\n", - " fp_name = row['param_fp_transformer'] \n", - " if(\"Morgan\" in str(fp_name)):\n", + " fp_name = row[\"param_fp_transformer\"]\n", + " if \"Morgan\" in str(fp_name):\n", " res_dict[fp_name].append(row)\n", "\n", "for fp_type, rows in res_dict.items():\n", " df = pd.DataFrame(rows)\n", - " df =df.sort_values(by=\"mean_test_score\")\n", - "\n", - " #plot test score vs. approach\n", - " xlabels = map(lambda x: \"_\".join(x), zip(df.param_fp_transformer__nBits.astype(str), df.param_regressor__alpha.astype(str)))\n", - "\n", - " \n", - " plt.figure(figsize=[14,5])\n", + " df = df.sort_values(by=\"mean_test_score\")\n", + "\n", + " # plot test score vs. approach\n", + " xlabels = map(\n", + " lambda x: \"_\".join(x),\n", + " zip(\n", + " df.param_fp_transformer__fpSize.astype(str),\n", + " df.param_regressor__alpha.astype(str),\n", + " ),\n", + " )\n", + "\n", + " plt.figure(figsize=[14, 5])\n", " plt.bar(range(len(df)), df.mean_test_score, yerr=df.std_test_score)\n", " plt.xticks(range(len(df)), xlabels, rotation=90, fontsize=14)\n", " plt.ylabel(\"mean score\", fontsize=14)\n", " plt.xlabel(\"bitsize_alpha\", fontsize=14)\n", "\n", - " plt.title(\"Fingerprint Transformer \"+str(fp_type).split(\"(\")[0]+\" per Bitsize\", fontsize=18)\n", + " plt.title(\n", + " \"Fingerprint Transformer \" + str(fp_type).split(\"(\")[0] + \" per Bitsize\",\n", + " fontsize=18,\n", + " )\n", " pass" ] }, { "cell_type": "code", "execution_count": 8, + "id": "20f7e139", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:09.030301Z", - "iopub.status.busy": "2024-04-12T12:11:09.030024Z", - "iopub.status.idle": "2024-04-12T12:11:09.425867Z", - "shell.execute_reply": "2024-04-12T12:11:09.425174Z" + "iopub.execute_input": "2024-11-24T09:28:28.915675Z", + "iopub.status.busy": "2024-11-24T09:28:28.915430Z", + "iopub.status.idle": "2024-11-24T09:28:29.314170Z", + "shell.execute_reply": "2024-11-24T09:28:29.313570Z" } }, "outputs": [ @@ -711,10 +741,10 @@ } ], "source": [ - "#plot ALL test score vs. approach\n", - "df =df_training_stats.sort_values(by=\"mean_test_score\")\n", + "# plot ALL test score vs. approach\n", + "df = df_training_stats.sort_values(by=\"mean_test_score\")\n", "\n", - "plt.figure(figsize=[16,9])\n", + "plt.figure(figsize=[16, 9])\n", "plt.bar(range(len(df)), df.mean_test_score, yerr=df.std_test_score)\n", "plt.ylabel(\"mean score\", fontsize=14)\n", "plt.xticks(range(len(df))[::5], df.param_fp_transformer[::5], rotation=90, fontsize=14)\n", @@ -724,6 +754,7 @@ }, { "cell_type": "markdown", + "id": "f407671c", "metadata": {}, "source": [ "This file have the following licence:\n", @@ -955,5 +986,5 @@ } }, "nbformat": 4, - "nbformat_minor": 1 + "nbformat_minor": 5 } diff --git a/notebooks/09_Combinatorial_Method_Usage_with_FingerPrint_Transformers.py b/notebooks/09_Combinatorial_Method_Usage_with_FingerPrint_Transformers.py index d8c51bb..4a39a02 100644 --- a/notebooks/09_Combinatorial_Method_Usage_with_FingerPrint_Transformers.py +++ b/notebooks/09_Combinatorial_Method_Usage_with_FingerPrint_Transformers.py @@ -24,7 +24,7 @@ # * Training Phase # * Analysis # -# Authors: @VincentAlexanderScholz, @RiesBen +# Authors: @VincentAlexanderScholz, @RiesBen # # ## Imports: # First we will import all the stuff that we will need for our work. @@ -62,12 +62,13 @@ csv_file = "SLC6A4_active_excape_export.csv" if not os.path.exists(csv_file): import urllib.request + url = "https://ndownloader.figshare.com/files/25747817" urllib.request.urlretrieve(url, csv_file) else: - csv_file = '../tests/data/SLC6A4_active_excapedb_subset.csv' + csv_file = "../tests/data/SLC6A4_active_excapedb_subset.csv" -#Parse Database +# Parse Database data = pd.read_csv(csv_file) PandasTools.AddMoleculeColumnToFrame(data, smilesCol="SMILES") @@ -77,31 +78,42 @@ # ## Build Pipeline: # In this stage we will build the Pipeline consisting of the featurization part (finger print transformers) and the model part (Ridge Regression). # -# Note that the featurization in this section is an hyperparameter, living in `param_grid`, and the `"fp_transformer"` string is just a placeholder, being replaced during pipeline execution. +# Note that the featurization in this section is an hyperparameter, living in `param_grid`, and the `"fp_transformer"` string is just a placeholder, being replaced during pipeline execution. # # This way we can define multiple different scenarios in `param_grid`, that allow us to rapidly explore different combinations of settings and methodologies. # %% regressor = Ridge() -optimization_pipe = Pipeline([("fp_transformer", "fp_transformer"), # this is a placeholder for different transformers - ("regressor", regressor)]) - -param_grid = [ # Here pass different Options and Approaches +optimization_pipe = Pipeline( + [ + ( + "fp_transformer", + "fp_transformer", + ), # this is a placeholder for different transformers + ("regressor", regressor), + ] +) + +param_grid = [ # Here pass different Options and Approaches { - "fp_transformer": [fingerprints.MorganFingerprintTransformer(), - fingerprints.AvalonFingerprintTransformer()], - "fp_transformer__nBits": [2**x for x in range(8,13)], + "fp_transformer": [ + fingerprints.MorganFingerprintTransformer(), + fingerprints.AvalonFingerprintTransformer(), + ], + "fp_transformer__fpSize": [2**x for x in range(8, 13)], }, { - "fp_transformer": [fingerprints.RDKitFingerprintTransformer(), - fingerprints.AtomPairFingerprintTransformer(), - fingerprints.MACCSKeysFingerprintTransformer()], + "fp_transformer": [ + fingerprints.RDKitFingerprintTransformer(), + fingerprints.AtomPairFingerprintTransformer(), + fingerprints.MACCSKeysFingerprintTransformer(), + ], }, ] global_options = { - "regressor__alpha": np.linspace(0.1,1,5), + "regressor__alpha": np.linspace(0.1, 1, 5), } [params.update(global_options) for params in param_grid] @@ -114,18 +126,19 @@ # %% # Split Data -mol_list_train, mol_list_test, y_train, y_test = train_test_split(data.ROMol, data.pXC50, random_state=0) +mol_list_train, mol_list_test, y_train, y_test = train_test_split( + data.ROMol, data.pXC50, random_state=0 +) # Define Search Process -grid = GridSearchCV(optimization_pipe, n_jobs=1, - param_grid=param_grid) +grid = GridSearchCV(optimization_pipe, n_jobs=1, param_grid=param_grid) # Train t0 = time() grid.fit(mol_list_train, y_train.values) t1 = time() -print(f'Runtime: {t1-t0:0.2F}') +print(f"Runtime: {t1-t0:0.2F}") # %% [markdown] # ## Analysis @@ -140,17 +153,20 @@ # Best Fingerprint Method / Performance res_dict = {} for i, row in df_training_stats.iterrows(): - fp_name = row['param_fp_transformer'] - if(fp_name in res_dict and row['mean_test_score'] > res_dict[fp_name]["mean_test_score"]): + fp_name = row["param_fp_transformer"] + if ( + fp_name in res_dict + and row["mean_test_score"] > res_dict[fp_name]["mean_test_score"] + ): res_dict[fp_name] = row.to_dict() - elif(not fp_name in res_dict): + elif not fp_name in res_dict: res_dict[fp_name] = row.to_dict() - + df = pd.DataFrame(list(res_dict.values())) -df =df.sort_values(by="mean_test_score") +df = df.sort_values(by="mean_test_score") -#plot test score vs. approach -plt.figure(figsize=[14,5]) +# plot test score vs. approach +plt.figure(figsize=[14, 5]) plt.bar(range(len(df)), df.mean_test_score, yerr=df.std_test_score) plt.xticks(range(len(df)), df.param_fp_transformer, rotation=90, fontsize=14) plt.ylabel("mean score", fontsize=14) @@ -161,35 +177,44 @@ # %% # Best Fingerprint Method / Performance from collections import defaultdict + res_dict = defaultdict(list) for i, row in df_training_stats.iterrows(): - fp_name = row['param_fp_transformer'] - if("Morgan" in str(fp_name)): + fp_name = row["param_fp_transformer"] + if "Morgan" in str(fp_name): res_dict[fp_name].append(row) for fp_type, rows in res_dict.items(): df = pd.DataFrame(rows) - df =df.sort_values(by="mean_test_score") - - #plot test score vs. approach - xlabels = map(lambda x: "_".join(x), zip(df.param_fp_transformer__nBits.astype(str), df.param_regressor__alpha.astype(str))) - - - plt.figure(figsize=[14,5]) + df = df.sort_values(by="mean_test_score") + + # plot test score vs. approach + xlabels = map( + lambda x: "_".join(x), + zip( + df.param_fp_transformer__fpSize.astype(str), + df.param_regressor__alpha.astype(str), + ), + ) + + plt.figure(figsize=[14, 5]) plt.bar(range(len(df)), df.mean_test_score, yerr=df.std_test_score) plt.xticks(range(len(df)), xlabels, rotation=90, fontsize=14) plt.ylabel("mean score", fontsize=14) plt.xlabel("bitsize_alpha", fontsize=14) - plt.title("Fingerprint Transformer "+str(fp_type).split("(")[0]+" per Bitsize", fontsize=18) + plt.title( + "Fingerprint Transformer " + str(fp_type).split("(")[0] + " per Bitsize", + fontsize=18, + ) pass # %% -#plot ALL test score vs. approach -df =df_training_stats.sort_values(by="mean_test_score") +# plot ALL test score vs. approach +df = df_training_stats.sort_values(by="mean_test_score") -plt.figure(figsize=[16,9]) +plt.figure(figsize=[16, 9]) plt.bar(range(len(df)), df.mean_test_score, yerr=df.std_test_score) plt.ylabel("mean score", fontsize=14) plt.xticks(range(len(df))[::5], df.param_fp_transformer[::5], rotation=90, fontsize=14) diff --git a/notebooks/10_pipeline_pandas_output.ipynb b/notebooks/10_pipeline_pandas_output.ipynb index 09275ca..7fcff28 100644 --- a/notebooks/10_pipeline_pandas_output.ipynb +++ b/notebooks/10_pipeline_pandas_output.ipynb @@ -2,6 +2,7 @@ "cells": [ { "cell_type": "markdown", + "id": "454d87b5", "metadata": {}, "source": [ "# Preserving feature information in DataFrames\n", @@ -14,12 +15,13 @@ { "cell_type": "code", "execution_count": 1, + "id": "cb457069", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:10.927499Z", - "iopub.status.busy": "2024-04-12T12:11:10.927303Z", - "iopub.status.idle": "2024-04-12T12:11:11.787084Z", - "shell.execute_reply": "2024-04-12T12:11:11.786420Z" + "iopub.execute_input": "2024-11-24T09:28:31.171627Z", + "iopub.status.busy": "2024-11-24T09:28:31.171255Z", + "iopub.status.idle": "2024-11-24T09:28:32.152283Z", + "shell.execute_reply": "2024-11-24T09:28:32.151641Z" } }, "outputs": [], @@ -42,12 +44,13 @@ { "cell_type": "code", "execution_count": 2, + "id": "bc72ca09", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:11.789862Z", - "iopub.status.busy": "2024-04-12T12:11:11.789572Z", - "iopub.status.idle": "2024-04-12T12:11:11.796138Z", - "shell.execute_reply": "2024-04-12T12:11:11.795520Z" + "iopub.execute_input": "2024-11-24T09:28:32.155106Z", + "iopub.status.busy": "2024-11-24T09:28:32.154793Z", + "iopub.status.idle": "2024-11-24T09:28:32.161683Z", + "shell.execute_reply": "2024-11-24T09:28:32.161035Z" } }, "outputs": [], @@ -60,6 +63,7 @@ }, { "cell_type": "markdown", + "id": "f482cac3", "metadata": {}, "source": [ "Let's split the dataset in training and test, so we will be able to use the test set to evaluate the performance of models trained on the training set." @@ -68,12 +72,13 @@ { "cell_type": "code", "execution_count": 3, + "id": "6019d09f", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:11.798853Z", - "iopub.status.busy": "2024-04-12T12:11:11.798596Z", - "iopub.status.idle": "2024-04-12T12:11:11.803335Z", - "shell.execute_reply": "2024-04-12T12:11:11.802809Z" + "iopub.execute_input": "2024-11-24T09:28:32.164164Z", + "iopub.status.busy": "2024-11-24T09:28:32.163946Z", + "iopub.status.idle": "2024-11-24T09:28:32.168382Z", + "shell.execute_reply": "2024-11-24T09:28:32.167874Z" } }, "outputs": [], @@ -84,12 +89,13 @@ { "cell_type": "code", "execution_count": 4, + "id": "fe9efa0e", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:11.805768Z", - "iopub.status.busy": "2024-04-12T12:11:11.805514Z", - "iopub.status.idle": "2024-04-12T12:11:11.809489Z", - "shell.execute_reply": "2024-04-12T12:11:11.808992Z" + "iopub.execute_input": "2024-11-24T09:28:32.171037Z", + "iopub.status.busy": "2024-11-24T09:28:32.170722Z", + "iopub.status.idle": "2024-11-24T09:28:32.174941Z", + "shell.execute_reply": "2024-11-24T09:28:32.174393Z" } }, "outputs": [], @@ -105,6 +111,7 @@ }, { "cell_type": "markdown", + "id": "7b4cca39", "metadata": {}, "source": [ "## Descriptors pipeline that returns DataFrames\n", @@ -122,26 +129,432 @@ { "cell_type": "code", "execution_count": 5, + "id": "33ce774b", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:11.811852Z", - "iopub.status.busy": "2024-04-12T12:11:11.811625Z", - "iopub.status.idle": "2024-04-12T12:11:11.827762Z", - "shell.execute_reply": "2024-04-12T12:11:11.827206Z" + "iopub.execute_input": "2024-11-24T09:28:32.177459Z", + "iopub.status.busy": "2024-11-24T09:28:32.177241Z", + "iopub.status.idle": "2024-11-24T09:28:32.194656Z", + "shell.execute_reply": "2024-11-24T09:28:32.194079Z" } }, "outputs": [ { "data": { "text/html": [ - "
Pipeline(steps=[('smilestomoltransformer', SmilesToMolTransformer()),\n",
+       "
Pipeline(steps=[('smilestomoltransformer', SmilesToMolTransformer()),\n",
        "                ('standardizer', Standardizer()),\n",
        "                ('moleculardescriptortransformer',\n",
        "                 MolecularDescriptorTransformer(desc_list=['MaxAbsEStateIndex',\n",
        "                                                           'MaxEStateIndex',\n",
        "                                                           'MinAbsEStateIndex',\n",
        "                                                           'MinEStateIndex',\n",
-       "                                                           'qed', 'MolWt',\n",
+       "                                                           'qed', 'SPS',\n",
+       "                                                           'MolWt',\n",
        "                                                           'HeavyAtomMolWt',\n",
        "                                                           'ExactMolWt',\n",
        "                                                           'NumValenceElectrons',\n",
@@ -162,15 +575,15 @@
        "                                                           'BCUT2D_MRHI',\n",
        "                                                           'BCUT2D_MRLOW',\n",
        "                                                           'AvgIpc', 'BalabanJ',\n",
-       "                                                           'BertzCT', 'Chi0',\n",
-       "                                                           'Chi0n', ...]))])
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" ], "text/plain": [ "Pipeline(steps=[('smilestomoltransformer', SmilesToMolTransformer()),\n", @@ -218,7 +631,8 @@ " 'MaxEStateIndex',\n", " 'MinAbsEStateIndex',\n", " 'MinEStateIndex',\n", - " 'qed', 'MolWt',\n", + " 'qed', 'SPS',\n", + " 'MolWt',\n", " 'HeavyAtomMolWt',\n", " 'ExactMolWt',\n", " 'NumValenceElectrons',\n", @@ -239,8 +653,7 @@ " 'BCUT2D_MRHI',\n", " 'BCUT2D_MRLOW',\n", " 'AvgIpc', 'BalabanJ',\n", - " 'BertzCT', 'Chi0',\n", - " 'Chi0n', ...]))])" + " 'BertzCT', 'Chi0', ...]))])" ] }, "execution_count": 5, @@ -260,15 +673,541 @@ { "cell_type": "code", "execution_count": 6, + "id": "2cb55603", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:11.830134Z", - "iopub.status.busy": "2024-04-12T12:11:11.829918Z", - "iopub.status.idle": "2024-04-12T12:11:13.735020Z", - "shell.execute_reply": "2024-04-12T12:11:13.734450Z" + "iopub.execute_input": "2024-11-24T09:28:32.196995Z", + "iopub.status.busy": "2024-11-24T09:28:32.196792Z", + "iopub.status.idle": "2024-11-24T09:28:34.209289Z", + "shell.execute_reply": "2024-11-24T09:28:34.208617Z" } }, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:32] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:33] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:34] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, { "data": { "text/html": [ @@ -295,11 +1234,11 @@ " MinAbsEStateIndex\n", " MinEStateIndex\n", " qed\n", + " SPS\n", " MolWt\n", " HeavyAtomMolWt\n", " ExactMolWt\n", " NumValenceElectrons\n", - " NumRadicalElectrons\n", " ...\n", " fr_sulfide\n", " fr_sulfonamd\n", @@ -321,11 +1260,11 @@ " 0.056985\n", " -0.432587\n", " 0.353101\n", - " 522.592\n", - " 490.336\n", - " 522.233014\n", + " 14.289474\n", + " 522.591980\n", + " 490.335999\n", + " 522.233032\n", " 200.0\n", - " 0.0\n", " ...\n", " 0.0\n", " 0.0\n", @@ -345,11 +1284,11 @@ " 0.026212\n", " -0.050849\n", " 0.682187\n", - " 425.558\n", - " 398.342\n", - " 425.188546\n", + " 16.033333\n", + " 425.558014\n", + " 398.342010\n", + " 425.188538\n", " 158.0\n", - " 0.0\n", " ...\n", " 0.0\n", " 0.0\n", @@ -369,11 +1308,11 @@ " 0.266700\n", " -0.413763\n", " 0.443905\n", - " 465.588\n", - " 432.324\n", - " 465.259169\n", + " 15.852942\n", + " 465.588013\n", + " 432.324005\n", + " 465.259155\n", " 180.0\n", - " 0.0\n", " ...\n", " 0.0\n", " 0.0\n", @@ -388,16 +1327,16 @@ " \n", " \n", " 3\n", - " 12.725824\n", - " 12.725824\n", + " 12.725823\n", + " 12.725823\n", " 0.052996\n", " -0.052996\n", " 0.577709\n", - " 478.468\n", - " 445.204\n", - " 477.206216\n", + " 17.812500\n", + " 478.467987\n", + " 445.204010\n", + " 477.206207\n", " 174.0\n", - " 0.0\n", " ...\n", " 0.0\n", " 0.0\n", @@ -407,7 +1346,7 @@ " 0.0\n", " 0.0\n", " 0.0\n", - " 1.0\n", + " 0.0\n", " 0.0\n", " \n", " \n", @@ -417,11 +1356,11 @@ " 0.898244\n", " 0.898244\n", " 0.658108\n", - " 246.313\n", - " 232.201\n", - " 246.115698\n", + " 13.052631\n", + " 246.313004\n", + " 232.201004\n", + " 246.115692\n", " 92.0\n", - " 0.0\n", " ...\n", " 0.0\n", " 0.0\n", @@ -465,11 +1404,11 @@ " 0.175664\n", " 0.175664\n", " 0.916154\n", - " 312.240\n", - " 293.088\n", - " 311.084370\n", + " 35.700001\n", + " 312.239990\n", + " 293.088013\n", + " 311.084381\n", " 108.0\n", - " 0.0\n", " ...\n", " 0.0\n", " 0.0\n", @@ -489,11 +1428,11 @@ " 0.420312\n", " 0.420312\n", " 0.378112\n", - " 465.645\n", - " 430.365\n", + " 21.714285\n", + " 465.644989\n", + " 430.364990\n", " 465.289246\n", " 180.0\n", - " 0.0\n", " ...\n", " 0.0\n", " 0.0\n", @@ -513,11 +1452,11 @@ " 0.300870\n", " -4.299737\n", " 0.919340\n", - " 328.378\n", - " 305.194\n", - " 328.176248\n", + " 23.565218\n", + " 328.377991\n", + " 305.194000\n", + " 328.176239\n", " 128.0\n", - " 0.0\n", " ...\n", " 0.0\n", " 0.0\n", @@ -537,11 +1476,11 @@ " 0.127623\n", " -0.127623\n", " 0.918995\n", - " 323.223\n", - " 307.095\n", - " 322.063968\n", + " 19.428572\n", + " 323.222992\n", + " 307.095001\n", + " 322.063965\n", " 110.0\n", - " 0.0\n", " ...\n", " 0.0\n", " 0.0\n", @@ -561,11 +1500,11 @@ " 0.086367\n", " 0.086367\n", " 0.911854\n", - " 296.414\n", - " 272.222\n", - " 296.188863\n", + " 17.136364\n", + " 296.414001\n", + " 272.221985\n", + " 296.188873\n", " 116.0\n", - " 0.0\n", " ...\n", " 0.0\n", " 0.0\n", @@ -580,7 +1519,7 @@ " \n", " \n", "\n", - "

159 rows × 209 columns

\n", + "

159 rows × 210 columns

\n", "" ], "text/plain": [ @@ -588,7 +1527,7 @@ "0 13.448610 13.448610 0.056985 -0.432587 \n", "1 12.863074 12.863074 0.026212 -0.050849 \n", "2 13.424788 13.424788 0.266700 -0.413763 \n", - "3 12.725824 12.725824 0.052996 -0.052996 \n", + "3 12.725823 12.725823 0.052996 -0.052996 \n", "4 6.356910 6.356910 0.898244 0.898244 \n", ".. ... ... ... ... \n", "154 6.217065 6.217065 0.175664 0.175664 \n", @@ -597,31 +1536,31 @@ "157 6.238476 6.238476 0.127623 -0.127623 \n", "158 6.371723 6.371723 0.086367 0.086367 \n", "\n", - " qed MolWt HeavyAtomMolWt ExactMolWt NumValenceElectrons \\\n", - "0 0.353101 522.592 490.336 522.233014 200.0 \n", - "1 0.682187 425.558 398.342 425.188546 158.0 \n", - "2 0.443905 465.588 432.324 465.259169 180.0 \n", - "3 0.577709 478.468 445.204 477.206216 174.0 \n", - "4 0.658108 246.313 232.201 246.115698 92.0 \n", - ".. ... ... ... ... ... \n", - "154 0.916154 312.240 293.088 311.084370 108.0 \n", - "155 0.378112 465.645 430.365 465.289246 180.0 \n", - "156 0.919340 328.378 305.194 328.176248 128.0 \n", - "157 0.918995 323.223 307.095 322.063968 110.0 \n", - "158 0.911854 296.414 272.222 296.188863 116.0 \n", - "\n", - " NumRadicalElectrons ... fr_sulfide fr_sulfonamd fr_sulfone \\\n", - "0 0.0 ... 0.0 0.0 0.0 \n", - "1 0.0 ... 0.0 0.0 0.0 \n", - "2 0.0 ... 0.0 0.0 0.0 \n", - "3 0.0 ... 0.0 0.0 0.0 \n", - "4 0.0 ... 0.0 0.0 0.0 \n", + " qed SPS MolWt HeavyAtomMolWt ExactMolWt \\\n", + "0 0.353101 14.289474 522.591980 490.335999 522.233032 \n", + "1 0.682187 16.033333 425.558014 398.342010 425.188538 \n", + "2 0.443905 15.852942 465.588013 432.324005 465.259155 \n", + "3 0.577709 17.812500 478.467987 445.204010 477.206207 \n", + "4 0.658108 13.052631 246.313004 232.201004 246.115692 \n", + ".. ... ... ... ... ... \n", + "154 0.916154 35.700001 312.239990 293.088013 311.084381 \n", + "155 0.378112 21.714285 465.644989 430.364990 465.289246 \n", + "156 0.919340 23.565218 328.377991 305.194000 328.176239 \n", + "157 0.918995 19.428572 323.222992 307.095001 322.063965 \n", + "158 0.911854 17.136364 296.414001 272.221985 296.188873 \n", + "\n", + " NumValenceElectrons ... fr_sulfide fr_sulfonamd fr_sulfone \\\n", + "0 200.0 ... 0.0 0.0 0.0 \n", + "1 158.0 ... 0.0 0.0 0.0 \n", + "2 180.0 ... 0.0 0.0 0.0 \n", + "3 174.0 ... 0.0 0.0 0.0 \n", + "4 92.0 ... 0.0 0.0 0.0 \n", ".. ... ... ... ... ... \n", - "154 0.0 ... 0.0 0.0 0.0 \n", - "155 0.0 ... 0.0 0.0 0.0 \n", - "156 0.0 ... 0.0 0.0 0.0 \n", - "157 0.0 ... 0.0 0.0 0.0 \n", - "158 0.0 ... 0.0 0.0 0.0 \n", + "154 108.0 ... 0.0 0.0 0.0 \n", + "155 180.0 ... 0.0 0.0 0.0 \n", + "156 128.0 ... 0.0 0.0 0.0 \n", + "157 110.0 ... 0.0 0.0 0.0 \n", + "158 116.0 ... 0.0 0.0 0.0 \n", "\n", " fr_term_acetylene fr_tetrazole fr_thiazole fr_thiocyan fr_thiophene \\\n", "0 0.0 0.0 0.0 0.0 0.0 \n", @@ -640,7 +1579,7 @@ "0 0.0 0.0 \n", "1 0.0 0.0 \n", "2 0.0 0.0 \n", - "3 1.0 0.0 \n", + "3 0.0 0.0 \n", "4 0.0 0.0 \n", ".. ... ... \n", "154 0.0 0.0 \n", @@ -649,7 +1588,7 @@ "157 0.0 0.0 \n", "158 0.0 0.0 \n", "\n", - "[159 rows x 209 columns]" + "[159 rows x 210 columns]" ] }, "execution_count": 6, @@ -664,6 +1603,7 @@ }, { "cell_type": "markdown", + "id": "40d6024a", "metadata": {}, "source": [ "All scikit-mol transformers are now compatible with the scikit-learn [set_output API](https://scikit-learn.org/stable/auto_examples/miscellaneous/plot_set_output.html).\n", @@ -675,25 +1615,430 @@ { "cell_type": "code", "execution_count": 7, + "id": "f56c539c", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:13.737598Z", - "iopub.status.busy": "2024-04-12T12:11:13.737383Z", - "iopub.status.idle": "2024-04-12T12:11:13.745000Z", - "shell.execute_reply": "2024-04-12T12:11:13.744500Z" + "iopub.execute_input": "2024-11-24T09:28:34.211959Z", + "iopub.status.busy": "2024-11-24T09:28:34.211717Z", + "iopub.status.idle": "2024-11-24T09:28:34.220439Z", + "shell.execute_reply": "2024-11-24T09:28:34.219746Z" } }, "outputs": [ { "data": { "text/html": [ - "
Pipeline(steps=[('smilestomoltransformer', SmilesToMolTransformer()),\n",
+       "
Pipeline(steps=[('smilestomoltransformer', SmilesToMolTransformer()),\n",
        "                ('standardizer', Standardizer()),\n",
        "                ('morganfingerprinttransformer',\n",
-       "                 MorganFingerprintTransformer())])
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SmilesToMolTransformer()
Standardizer()
MorganFingerprintTransformer()
" ], "text/plain": [ "Pipeline(steps=[('smilestomoltransformer', SmilesToMolTransformer()),\n", @@ -719,12 +2064,13 @@ { "cell_type": "code", "execution_count": 8, + "id": "781d1bc8", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:13.747288Z", - "iopub.status.busy": "2024-04-12T12:11:13.747073Z", - "iopub.status.idle": "2024-04-12T12:11:14.181998Z", - "shell.execute_reply": "2024-04-12T12:11:14.181388Z" + "iopub.execute_input": "2024-11-24T09:28:34.222936Z", + "iopub.status.busy": "2024-11-24T09:28:34.222716Z", + "iopub.status.idle": "2024-11-24T09:28:34.618391Z", + "shell.execute_reply": "2024-11-24T09:28:34.617722Z" } }, "outputs": [ @@ -1123,6 +2469,7 @@ }, { "cell_type": "markdown", + "id": "19a13ca2", "metadata": {}, "source": [ "## Analyze feature importance of regression pipeline\n", @@ -1135,31 +2482,438 @@ { "cell_type": "code", "execution_count": 9, + "id": "4872ecab", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:14.184553Z", - "iopub.status.busy": "2024-04-12T12:11:14.184344Z", - "iopub.status.idle": "2024-04-12T12:11:14.201432Z", - "shell.execute_reply": "2024-04-12T12:11:14.200853Z" + "iopub.execute_input": "2024-11-24T09:28:34.621103Z", + "iopub.status.busy": "2024-11-24T09:28:34.620854Z", + "iopub.status.idle": "2024-11-24T09:28:34.640701Z", + "shell.execute_reply": "2024-11-24T09:28:34.640027Z" } }, "outputs": [ { "data": { "text/html": [ - "
Pipeline(steps=[('smilestomoltransformer', SmilesToMolTransformer()),\n",
+       "
Pipeline(steps=[('smilestomoltransformer', SmilesToMolTransformer()),\n",
        "                ('standardizer', Standardizer()),\n",
        "                ('moleculardescriptortransformer',\n",
        "                 MolecularDescriptorTransformer(desc_list=['MaxAbsEStateIndex',\n",
        "                                                           'MaxEStateIndex',\n",
        "                                                           'MinAbsEStateIndex',\n",
        "                                                           'MinEStateIndex',\n",
-       "                                                           'qed', 'MolWt',\n",
+       "                                                           'qed', 'SPS',\n",
+       "                                                           'MolWt',\n",
        "                                                           'HeavyAtomMolWt',\n",
        "                                                           'ExactMolWt',\n",
        "                                                           'NumValenceElectrons',\n",
        "                                                           'NumRadicalElectrons',\n",
-       "                                                           'MaxPartialC...\n",
+       "                                                           'MaxPa...\n",
+       "                                                           'MaxAbsPartialCharge',\n",
        "                                                           'MinAbsPartialCharge',\n",
        "                                                           'FpDensityMorgan1',\n",
        "                                                           'FpDensityMorgan2',\n",
@@ -1173,22 +2927,23 @@
        "                                                           'BCUT2D_MRHI',\n",
        "                                                           'BCUT2D_MRLOW',\n",
        "                                                           'AvgIpc', 'BalabanJ',\n",
-       "                                                           'BertzCT', 'Chi0',\n",
-       "                                                           'Chi0n', ...])),\n",
+       "                                                           'BertzCT', 'Chi0', ...])),\n",
        "                ('standardscaler', StandardScaler()),\n",
-       "                ('randomforestregressor', RandomForestRegressor(max_depth=5))])
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
StandardScaler()
RandomForestRegressor(max_depth=5)
" ], "text/plain": [ "Pipeline(steps=[('smilestomoltransformer', SmilesToMolTransformer()),\n", @@ -1231,12 +2986,14 @@ " 'MaxEStateIndex',\n", " 'MinAbsEStateIndex',\n", " 'MinEStateIndex',\n", - " 'qed', 'MolWt',\n", + " 'qed', 'SPS',\n", + " 'MolWt',\n", " 'HeavyAtomMolWt',\n", " 'ExactMolWt',\n", " 'NumValenceElectrons',\n", " 'NumRadicalElectrons',\n", - " 'MaxPartialC...\n", + " 'MaxPa...\n", + " 'MaxAbsPartialCharge',\n", " 'MinAbsPartialCharge',\n", " 'FpDensityMorgan1',\n", " 'FpDensityMorgan2',\n", @@ -1250,8 +3007,7 @@ " 'BCUT2D_MRHI',\n", " 'BCUT2D_MRLOW',\n", " 'AvgIpc', 'BalabanJ',\n", - " 'BertzCT', 'Chi0',\n", - " 'Chi0n', ...])),\n", + " 'BertzCT', 'Chi0', ...])),\n", " ('standardscaler', StandardScaler()),\n", " ('randomforestregressor', RandomForestRegressor(max_depth=5))])" ] @@ -1279,15 +3035,680 @@ { "cell_type": "code", "execution_count": 10, + "id": "f0b2f44f", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:14.203799Z", - "iopub.status.busy": "2024-04-12T12:11:14.203546Z", - "iopub.status.idle": "2024-04-12T12:11:17.092871Z", - "shell.execute_reply": "2024-04-12T12:11:17.092220Z" + "iopub.execute_input": "2024-11-24T09:28:34.643396Z", + "iopub.status.busy": "2024-11-24T09:28:34.643148Z", + "iopub.status.idle": "2024-11-24T09:28:37.656343Z", + "shell.execute_reply": "2024-11-24T09:28:37.655703Z" } }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:35] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:36] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:37] DEPRECATION WARNING: please use MorganGenerator\n" + ] + } + ], "source": [ "regression_pipeline.fit(smis_train, target_train)\n", "pred_test = regression_pipeline.predict(smis_test)" @@ -1295,6 +3716,7 @@ }, { "cell_type": "markdown", + "id": "3aa6802d", "metadata": {}, "source": [ "Let's define a simple function to compute regression metrics, and use it to evaluate the test set performance of the pipeline." @@ -1303,21 +3725,30 @@ { "cell_type": "code", "execution_count": 11, + "id": "8b59851a", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:17.095680Z", - "iopub.status.busy": "2024-04-12T12:11:17.095437Z", - "iopub.status.idle": "2024-04-12T12:11:17.102165Z", - "shell.execute_reply": "2024-04-12T12:11:17.101654Z" + "iopub.execute_input": "2024-11-24T09:28:37.658965Z", + "iopub.status.busy": "2024-11-24T09:28:37.658741Z", + "iopub.status.idle": "2024-11-24T09:28:37.666594Z", + "shell.execute_reply": "2024-11-24T09:28:37.665979Z" } }, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/esben/python_envs/vscode/lib/python3.10/site-packages/sklearn/metrics/_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.\n", + " warnings.warn(\n" + ] + }, { "data": { "text/plain": [ - "{'RMSE': 0.8750229695931232,\n", - " 'MAE': 0.7227101414064178,\n", - " 'R2': 0.11946989572680278}" + "{'RMSE': 0.8736959928049254,\n", + " 'MAE': 0.707222432887994,\n", + " 'R2': 0.12213852746646214}" ] }, "execution_count": 11, @@ -1341,19 +3772,424 @@ { "cell_type": "code", "execution_count": 12, + "id": "68528957", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:17.104450Z", - "iopub.status.busy": "2024-04-12T12:11:17.104246Z", - "iopub.status.idle": "2024-04-12T12:11:17.108860Z", - "shell.execute_reply": "2024-04-12T12:11:17.108329Z" + "iopub.execute_input": "2024-11-24T09:28:37.668899Z", + "iopub.status.busy": "2024-11-24T09:28:37.668697Z", + "iopub.status.idle": "2024-11-24T09:28:37.673651Z", + "shell.execute_reply": "2024-11-24T09:28:37.672957Z" } }, "outputs": [ { "data": { "text/html": [ - "
RandomForestRegressor(max_depth=5)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" + "
RandomForestRegressor(max_depth=5)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" ], "text/plain": [ "RandomForestRegressor(max_depth=5)" @@ -1371,6 +4207,7 @@ }, { "cell_type": "markdown", + "id": "d8f32688", "metadata": {}, "source": [ "Since we used `set_output(transform=\"pandas\")` on the pipeline, the last step of the pipeline (the regression model) has the descriptor names in the `feature_names_in_` attribute. We can use them and the `feature_importances_` attribute to easily analyze the feature importances." @@ -1379,12 +4216,13 @@ { "cell_type": "code", "execution_count": 13, + "id": "24011e90", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:17.111179Z", - "iopub.status.busy": "2024-04-12T12:11:17.110981Z", - "iopub.status.idle": "2024-04-12T12:11:17.124017Z", - "shell.execute_reply": "2024-04-12T12:11:17.123440Z" + "iopub.execute_input": "2024-11-24T09:28:37.677173Z", + "iopub.status.busy": "2024-11-24T09:28:37.676324Z", + "iopub.status.idle": "2024-11-24T09:28:37.690728Z", + "shell.execute_reply": "2024-11-24T09:28:37.690184Z" } }, "outputs": [ @@ -1417,27 +4255,27 @@ " \n", " 0\n", " MaxAbsEStateIndex\n", - " 0.003899\n", + " 0.002776\n", " \n", " \n", " 1\n", " MaxEStateIndex\n", - " 0.001640\n", + " 0.003859\n", " \n", " \n", " 2\n", " MinAbsEStateIndex\n", - " 0.002302\n", + " 0.006311\n", " \n", " \n", " 3\n", " MinEStateIndex\n", - " 0.002898\n", + " 0.004721\n", " \n", " \n", " 4\n", " qed\n", - " 0.008949\n", + " 0.007605\n", " \n", " \n", " ...\n", @@ -1445,50 +4283,50 @@ " ...\n", " \n", " \n", - " 204\n", + " 205\n", " fr_thiazole\n", " 0.000000\n", " \n", " \n", - " 205\n", + " 206\n", " fr_thiocyan\n", " 0.000000\n", " \n", " \n", - " 206\n", + " 207\n", " fr_thiophene\n", - " 0.000286\n", + " 0.000046\n", " \n", " \n", - " 207\n", + " 208\n", " fr_unbrch_alkane\n", - " 0.000020\n", + " 0.000000\n", " \n", " \n", - " 208\n", + " 209\n", " fr_urea\n", - " 0.000015\n", + " 0.000000\n", " \n", " \n", "\n", - "

209 rows × 2 columns

\n", + "

210 rows × 2 columns

\n", "" ], "text/plain": [ " feature importance\n", - "0 MaxAbsEStateIndex 0.003899\n", - "1 MaxEStateIndex 0.001640\n", - "2 MinAbsEStateIndex 0.002302\n", - "3 MinEStateIndex 0.002898\n", - "4 qed 0.008949\n", + "0 MaxAbsEStateIndex 0.002776\n", + "1 MaxEStateIndex 0.003859\n", + "2 MinAbsEStateIndex 0.006311\n", + "3 MinEStateIndex 0.004721\n", + "4 qed 0.007605\n", ".. ... ...\n", - "204 fr_thiazole 0.000000\n", - "205 fr_thiocyan 0.000000\n", - "206 fr_thiophene 0.000286\n", - "207 fr_unbrch_alkane 0.000020\n", - "208 fr_urea 0.000015\n", + "205 fr_thiazole 0.000000\n", + "206 fr_thiocyan 0.000000\n", + "207 fr_thiophene 0.000046\n", + "208 fr_unbrch_alkane 0.000000\n", + "209 fr_urea 0.000000\n", "\n", - "[209 rows x 2 columns]" + "[210 rows x 2 columns]" ] }, "execution_count": 13, @@ -1503,6 +4341,7 @@ }, { "cell_type": "markdown", + "id": "64ac369d", "metadata": {}, "source": [ "Sort the features by most to least important:" @@ -1511,12 +4350,13 @@ { "cell_type": "code", "execution_count": 14, + "id": "713d24f1", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:17.126745Z", - "iopub.status.busy": "2024-04-12T12:11:17.126312Z", - "iopub.status.idle": "2024-04-12T12:11:17.134339Z", - "shell.execute_reply": "2024-04-12T12:11:17.133744Z" + "iopub.execute_input": "2024-11-24T09:28:37.693255Z", + "iopub.status.busy": "2024-11-24T09:28:37.693046Z", + "iopub.status.idle": "2024-11-24T09:28:37.700756Z", + "shell.execute_reply": "2024-11-24T09:28:37.700214Z" } }, "outputs": [ @@ -1549,27 +4389,27 @@ " \n", " 0\n", " PEOE_VSA6\n", - " 0.145391\n", + " 0.147449\n", " \n", " \n", " 1\n", " VSA_EState5\n", - " 0.087551\n", + " 0.087963\n", " \n", " \n", " 2\n", " MaxAbsPartialCharge\n", - " 0.050707\n", + " 0.057491\n", " \n", " \n", " 3\n", " VSA_EState6\n", - " 0.032544\n", + " 0.034922\n", " \n", " \n", " 4\n", " SlogP_VSA6\n", - " 0.030168\n", + " 0.028875\n", " \n", " \n", " ...\n", @@ -1577,50 +4417,50 @@ " ...\n", " \n", " \n", - " 204\n", - " fr_isocyan\n", - " 0.000000\n", - " \n", - " \n", " 205\n", - " fr_isothiocyan\n", + " fr_hdrzine\n", " 0.000000\n", " \n", " \n", " 206\n", - " fr_ketone\n", + " fr_hdrzone\n", " 0.000000\n", " \n", " \n", " 207\n", - " fr_ketone_Topliss\n", + " fr_imidazole\n", " 0.000000\n", " \n", " \n", " 208\n", - " fr_C_S\n", + " fr_imide\n", + " 0.000000\n", + " \n", + " \n", + " 209\n", + " fr_urea\n", " 0.000000\n", " \n", " \n", "\n", - "

209 rows × 2 columns

\n", + "

210 rows × 2 columns

\n", "" ], "text/plain": [ " feature importance\n", - "0 PEOE_VSA6 0.145391\n", - "1 VSA_EState5 0.087551\n", - "2 MaxAbsPartialCharge 0.050707\n", - "3 VSA_EState6 0.032544\n", - "4 SlogP_VSA6 0.030168\n", + "0 PEOE_VSA6 0.147449\n", + "1 VSA_EState5 0.087963\n", + "2 MaxAbsPartialCharge 0.057491\n", + "3 VSA_EState6 0.034922\n", + "4 SlogP_VSA6 0.028875\n", ".. ... ...\n", - "204 fr_isocyan 0.000000\n", - "205 fr_isothiocyan 0.000000\n", - "206 fr_ketone 0.000000\n", - "207 fr_ketone_Topliss 0.000000\n", - "208 fr_C_S 0.000000\n", + "205 fr_hdrzine 0.000000\n", + "206 fr_hdrzone 0.000000\n", + "207 fr_imidazole 0.000000\n", + "208 fr_imide 0.000000\n", + "209 fr_urea 0.000000\n", "\n", - "[209 rows x 2 columns]" + "[210 rows x 2 columns]" ] }, "execution_count": 14, @@ -1636,12 +4476,13 @@ { "cell_type": "code", "execution_count": 15, + "id": "4b97778f", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:17.136673Z", - "iopub.status.busy": "2024-04-12T12:11:17.136477Z", - "iopub.status.idle": "2024-04-12T12:11:17.140656Z", - "shell.execute_reply": "2024-04-12T12:11:17.140049Z" + "iopub.execute_input": "2024-11-24T09:28:37.703238Z", + "iopub.status.busy": "2024-11-24T09:28:37.703004Z", + "iopub.status.idle": "2024-11-24T09:28:37.707129Z", + "shell.execute_reply": "2024-11-24T09:28:37.706557Z" } }, "outputs": [ @@ -1668,6 +4509,7 @@ }, { "cell_type": "markdown", + "id": "f79c93a0", "metadata": {}, "source": [ "## Including external features\n", @@ -1686,12 +4528,13 @@ { "cell_type": "code", "execution_count": 16, + "id": "bf8ddaf9", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:17.143445Z", - "iopub.status.busy": "2024-04-12T12:11:17.142907Z", - "iopub.status.idle": "2024-04-12T12:11:17.189933Z", - "shell.execute_reply": "2024-04-12T12:11:17.189323Z" + "iopub.execute_input": "2024-11-24T09:28:37.709630Z", + "iopub.status.busy": "2024-11-24T09:28:37.709389Z", + "iopub.status.idle": "2024-11-24T09:28:37.755699Z", + "shell.execute_reply": "2024-11-24T09:28:37.755108Z" } }, "outputs": [ @@ -2079,6 +4922,7 @@ }, { "cell_type": "markdown", + "id": "92dc6bf5", "metadata": {}, "source": [ "The CDDD features are stored in columns `cddd_1`, `cddd_2`, ..., `cddd_512`. The file has the identifier column `Ambit_InchiKey` that we can use to combine the CDDD features with the rest of the data:" @@ -2087,12 +4931,13 @@ { "cell_type": "code", "execution_count": 17, + "id": "db83be01", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:17.192512Z", - "iopub.status.busy": "2024-04-12T12:11:17.192295Z", - "iopub.status.idle": "2024-04-12T12:11:17.203133Z", - "shell.execute_reply": "2024-04-12T12:11:17.202544Z" + "iopub.execute_input": "2024-11-24T09:28:37.758200Z", + "iopub.status.busy": "2024-11-24T09:28:37.757994Z", + "iopub.status.idle": "2024-11-24T09:28:37.769048Z", + "shell.execute_reply": "2024-11-24T09:28:37.768408Z" } }, "outputs": [], @@ -2114,12 +4959,13 @@ { "cell_type": "code", "execution_count": 18, + "id": "dae995b7", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:17.205740Z", - "iopub.status.busy": "2024-04-12T12:11:17.205517Z", - "iopub.status.idle": "2024-04-12T12:11:17.209117Z", - "shell.execute_reply": "2024-04-12T12:11:17.208573Z" + "iopub.execute_input": "2024-11-24T09:28:37.771772Z", + "iopub.status.busy": "2024-11-24T09:28:37.771516Z", + "iopub.status.idle": "2024-11-24T09:28:37.775128Z", + "shell.execute_reply": "2024-11-24T09:28:37.774567Z" } }, "outputs": [], @@ -2134,6 +4980,7 @@ }, { "cell_type": "markdown", + "id": "2ec82fc8", "metadata": {}, "source": [ "Now we can define a pipeline that uses the original SMILES column to compute the descriptors available in scikit-mol, then concatenates them with the pre-computed CDDD features, and uses all of them to train the regression model. We will need a slightly more complex pipeline with column selectors and transformers. For more details on this technique, please refer to the [official documentation](https://scikit-learn.org/stable/modules/generated/sklearn.compose.make_column_selector.html).\n", @@ -2144,19 +4991,424 @@ { "cell_type": "code", "execution_count": 19, + "id": "dc6de049", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:17.211432Z", - "iopub.status.busy": "2024-04-12T12:11:17.211209Z", - "iopub.status.idle": "2024-04-12T12:11:17.241254Z", - "shell.execute_reply": "2024-04-12T12:11:17.240639Z" + "iopub.execute_input": "2024-11-24T09:28:37.777567Z", + "iopub.status.busy": "2024-11-24T09:28:37.777354Z", + "iopub.status.idle": "2024-11-24T09:28:37.808615Z", + "shell.execute_reply": "2024-11-24T09:28:37.808024Z" } }, "outputs": [ { "data": { "text/html": [ - "
ColumnTransformer(transformers=[('pipeline-1',\n",
+       "
ColumnTransformer(transformers=[('pipeline-1',\n",
        "                                 Pipeline(steps=[('smilestomoltransformer',\n",
        "                                                  SmilesToMolTransformer()),\n",
        "                                                 ('standardizer',\n",
@@ -2167,10 +5419,11 @@
        "                                                                                            'MinAbsEStateIndex',\n",
        "                                                                                            'MinEStateIndex',\n",
        "                                                                                            'qed',\n",
+       "                                                                                            'SPS',\n",
        "                                                                                            'MolWt',\n",
        "                                                                                            'HeavyAtomMolWt',\n",
        "                                                                                            'ExactMolWt',\n",
-       "                                                                                            'NumValenc...\n",
+       "                                                                                            'Num...\n",
        "                                                                                            'BCUT2D_LOGPHI',\n",
        "                                                                                            'BCUT2D_LOGPLOW',\n",
        "                                                                                            'BCUT2D_MRHI',\n",
@@ -2178,13 +5431,12 @@
        "                                                                                            'AvgIpc',\n",
        "                                                                                            'BalabanJ',\n",
        "                                                                                            'BertzCT',\n",
-       "                                                                                            'Chi0',\n",
-       "                                                                                            'Chi0n', ...]))]),\n",
-       "                                 <sklearn.compose._column_transformer.make_column_selector object at 0x7d90d7ff6e30>),\n",
+       "                                                                                            'Chi0', ...]))]),\n",
+       "                                 <sklearn.compose._column_transformer.make_column_selector object at 0x729f1412c520>),\n",
        "                                ('pipeline-2',\n",
        "                                 Pipeline(steps=[('functiontransformer',\n",
        "                                                  FunctionTransformer())]),\n",
-       "                                 <sklearn.compose._column_transformer.make_column_selector object at 0x7d90d7ff6a40>)])
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
<sklearn.compose._column_transformer.make_column_selector object at 0x729f1412ebf0>
FunctionTransformer()
" ], "text/plain": [ "ColumnTransformer(transformers=[('pipeline-1',\n", @@ -2242,10 +5495,11 @@ " 'MinAbsEStateIndex',\n", " 'MinEStateIndex',\n", " 'qed',\n", + " 'SPS',\n", " 'MolWt',\n", " 'HeavyAtomMolWt',\n", " 'ExactMolWt',\n", - " 'NumValenc...\n", + " 'Num...\n", " 'BCUT2D_LOGPHI',\n", " 'BCUT2D_LOGPLOW',\n", " 'BCUT2D_MRHI',\n", @@ -2253,13 +5507,12 @@ " 'AvgIpc',\n", " 'BalabanJ',\n", " 'BertzCT',\n", - " 'Chi0',\n", - " 'Chi0n', ...]))]),\n", - " ),\n", + " 'Chi0', ...]))]),\n", + " ),\n", " ('pipeline-2',\n", " Pipeline(steps=[('functiontransformer',\n", " FunctionTransformer())]),\n", - " )])" + " )])" ] }, "execution_count": 19, @@ -2290,27 +5543,424 @@ { "cell_type": "code", "execution_count": 20, + "id": "6ee85c3c", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:17.243604Z", - "iopub.status.busy": "2024-04-12T12:11:17.243400Z", - "iopub.status.idle": "2024-04-12T12:11:17.309327Z", - "shell.execute_reply": "2024-04-12T12:11:17.308716Z" + "iopub.execute_input": "2024-11-24T09:28:37.811016Z", + "iopub.status.busy": "2024-11-24T09:28:37.810811Z", + "iopub.status.idle": "2024-11-24T09:28:37.883600Z", + "shell.execute_reply": "2024-11-24T09:28:37.882894Z" } }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/esben/python_envs/vscode/lib/python3.10/site-packages/sklearn/preprocessing/_function_transformer.py:345: UserWarning: With transform=\"pandas\", `func` should return a DataFrame to follow the set_output API.\n", - " warnings.warn(\n" - ] - }, { "data": { "text/html": [ - "
Pipeline(steps=[('columntransformer',\n",
+       "
Pipeline(steps=[('columntransformer',\n",
        "                 ColumnTransformer(transformers=[('pipeline-1',\n",
        "                                                  Pipeline(steps=[('smilestomoltransformer',\n",
        "                                                                   SmilesToMolTransformer()),\n",
@@ -2322,16 +5972,16 @@
        "                                                                                                             'MinAbsEStateIndex',\n",
        "                                                                                                             'MinEStateIndex',\n",
        "                                                                                                             'qed',\n",
-       "                                                                                                             'MolWt',\n",
-       "                                                                                                             'He...\n",
-       "                                                                                                             'Chi0n', ...]))]),\n",
-       "                                                  <sklearn.compose._column_transformer.make_column_selector object at 0x7d90d7ff6e30>),\n",
+       "                                                                                                             'SPS',\n",
+       "                                                                                                             'MolW...\n",
+       "                                                                                                             'Chi0', ...]))]),\n",
+       "                                                  <sklearn.compose._column_transformer.make_column_selector object at 0x729f1412c520>),\n",
        "                                                 ('pipeline-2',\n",
        "                                                  Pipeline(steps=[('functiontransformer',\n",
        "                                                                   FunctionTransformer())]),\n",
-       "                                                  <sklearn.compose._column_transformer.make_column_selector object at 0x7d90d7ff6a40>)])),\n",
+       "                                                  <sklearn.compose._column_transformer.make_column_selector object at 0x729f1412ebf0>)])),\n",
        "                ('standardscaler', StandardScaler()),\n",
-       "                ('randomforestregressor', RandomForestRegressor(max_depth=5))])
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
<sklearn.compose._column_transformer.make_column_selector object at 0x729f1412ebf0>
FunctionTransformer()
StandardScaler()
RandomForestRegressor(max_depth=5)
" ], "text/plain": [ "Pipeline(steps=[('columntransformer',\n", @@ -2411,14 +6062,14 @@ " 'MinAbsEStateIndex',\n", " 'MinEStateIndex',\n", " 'qed',\n", - " 'MolWt',\n", - " 'He...\n", - " 'Chi0n', ...]))]),\n", - " ),\n", + " 'SPS',\n", + " 'MolW...\n", + " 'Chi0', ...]))]),\n", + " ),\n", " ('pipeline-2',\n", " Pipeline(steps=[('functiontransformer',\n", " FunctionTransformer())]),\n", - " )])),\n", + " )])),\n", " ('standardscaler', StandardScaler()),\n", " ('randomforestregressor', RandomForestRegressor(max_depth=5))])" ] @@ -2440,21 +6091,672 @@ { "cell_type": "code", "execution_count": 21, + "id": "03960958", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:17.311956Z", - "iopub.status.busy": "2024-04-12T12:11:17.311703Z", - "iopub.status.idle": "2024-04-12T12:11:22.426687Z", - "shell.execute_reply": "2024-04-12T12:11:22.426127Z" + "iopub.execute_input": "2024-11-24T09:28:37.886041Z", + "iopub.status.busy": "2024-11-24T09:28:37.885822Z", + "iopub.status.idle": "2024-11-24T09:28:42.859220Z", + "shell.execute_reply": "2024-11-24T09:28:42.858489Z" } }, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:38] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:39] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "[10:28:42] DEPRECATION WARNING: please use MorganGenerator\n", + "/home/esben/python_envs/vscode/lib/python3.10/site-packages/sklearn/metrics/_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.\n", + " warnings.warn(\n" + ] + }, { "data": { "text/plain": [ - "{'RMSE': 0.8103900599888356,\n", - " 'MAE': 0.686626458034167,\n", - " 'R2': 0.2498289359739927}" + "{'RMSE': 0.8314055216871027,\n", + " 'MAE': 0.7061918187521163,\n", + " 'R2': 0.2104167870060334}" ] }, "execution_count": 21, @@ -2471,6 +6773,7 @@ }, { "cell_type": "markdown", + "id": "c49ecd90", "metadata": {}, "source": [ "Let's combine the performance metrics obtained using only the scikit-mol descriptors as input features, and the performance metrics obtained using also the CDDD features:" @@ -2479,12 +6782,13 @@ { "cell_type": "code", "execution_count": 22, + "id": "6ce2fe53", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:22.429148Z", - "iopub.status.busy": "2024-04-12T12:11:22.428932Z", - "iopub.status.idle": "2024-04-12T12:11:22.436592Z", - "shell.execute_reply": "2024-04-12T12:11:22.435962Z" + "iopub.execute_input": "2024-11-24T09:28:42.861769Z", + "iopub.status.busy": "2024-11-24T09:28:42.861505Z", + "iopub.status.idle": "2024-11-24T09:28:42.869169Z", + "shell.execute_reply": "2024-11-24T09:28:42.868553Z" } }, "outputs": [ @@ -2517,15 +6821,15 @@ " \n", " \n", " descriptors\n", - " 0.875023\n", - " 0.722710\n", - " 0.119470\n", + " 0.873696\n", + " 0.707222\n", + " 0.122139\n", " \n", " \n", " combined\n", - " 0.810390\n", - " 0.686626\n", - " 0.249829\n", + " 0.831406\n", + " 0.706192\n", + " 0.210417\n", " \n", " \n", "\n", @@ -2533,8 +6837,8 @@ ], "text/plain": [ " RMSE MAE R2\n", - "descriptors 0.875023 0.722710 0.119470\n", - "combined 0.810390 0.686626 0.249829" + "descriptors 0.873696 0.707222 0.122139\n", + "combined 0.831406 0.706192 0.210417" ] }, "execution_count": 22, @@ -2549,6 +6853,7 @@ }, { "cell_type": "markdown", + "id": "83b7fd13", "metadata": {}, "source": [ "All performance metrics were improved by the includion of the CDDD features.\n", @@ -2558,12 +6863,13 @@ { "cell_type": "code", "execution_count": 23, + "id": "9c98ac71", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:22.439263Z", - "iopub.status.busy": "2024-04-12T12:11:22.438951Z", - "iopub.status.idle": "2024-04-12T12:11:22.453688Z", - "shell.execute_reply": "2024-04-12T12:11:22.453096Z" + "iopub.execute_input": "2024-11-24T09:28:42.872116Z", + "iopub.status.busy": "2024-11-24T09:28:42.871685Z", + "iopub.status.idle": "2024-11-24T09:28:42.886733Z", + "shell.execute_reply": "2024-11-24T09:28:42.886003Z" } }, "outputs": [ @@ -2595,28 +6901,28 @@ " \n", " \n", " 0\n", - " pipeline-2__cddd_102\n", - " 0.077721\n", + " pipeline-1__PEOE_VSA6\n", + " 0.078597\n", " \n", " \n", " 1\n", - " pipeline-1__PEOE_VSA6\n", - " 0.060011\n", + " pipeline-2__cddd_102\n", + " 0.064366\n", " \n", " \n", " 2\n", " pipeline-2__cddd_378\n", - " 0.042489\n", + " 0.045695\n", " \n", " \n", " 3\n", - " pipeline-2__cddd_369\n", - " 0.030706\n", + " pipeline-1__VSA_EState5\n", + " 0.032759\n", " \n", " \n", " 4\n", - " pipeline-1__VSA_EState5\n", - " 0.026225\n", + " pipeline-2__cddd_369\n", + " 0.030738\n", " \n", " \n", " ...\n", @@ -2624,50 +6930,50 @@ " ...\n", " \n", " \n", - " 716\n", - " pipeline-1__SMR_VSA5\n", - " 0.000000\n", - " \n", - " \n", " 717\n", - " pipeline-1__SMR_VSA8\n", + " pipeline-1__fr_lactam\n", " 0.000000\n", " \n", " \n", " 718\n", - " pipeline-1__RingCount\n", + " pipeline-1__fr_NH2\n", " 0.000000\n", " \n", " \n", " 719\n", - " pipeline-1__fr_isocyan\n", + " pipeline-1__SMR_VSA2\n", " 0.000000\n", " \n", " \n", " 720\n", - " pipeline-1__fr_azide\n", + " pipeline-1__fr_Imine\n", + " 0.000000\n", + " \n", + " \n", + " 721\n", + " pipeline-1__fr_phos_acid\n", " 0.000000\n", " \n", " \n", "\n", - "

721 rows × 2 columns

\n", + "

722 rows × 2 columns

\n", "" ], "text/plain": [ - " feature importance\n", - "0 pipeline-2__cddd_102 0.077721\n", - "1 pipeline-1__PEOE_VSA6 0.060011\n", - "2 pipeline-2__cddd_378 0.042489\n", - "3 pipeline-2__cddd_369 0.030706\n", - "4 pipeline-1__VSA_EState5 0.026225\n", - ".. ... ...\n", - "716 pipeline-1__SMR_VSA5 0.000000\n", - "717 pipeline-1__SMR_VSA8 0.000000\n", - "718 pipeline-1__RingCount 0.000000\n", - "719 pipeline-1__fr_isocyan 0.000000\n", - "720 pipeline-1__fr_azide 0.000000\n", - "\n", - "[721 rows x 2 columns]" + " feature importance\n", + "0 pipeline-1__PEOE_VSA6 0.078597\n", + "1 pipeline-2__cddd_102 0.064366\n", + "2 pipeline-2__cddd_378 0.045695\n", + "3 pipeline-1__VSA_EState5 0.032759\n", + "4 pipeline-2__cddd_369 0.030738\n", + ".. ... ...\n", + "717 pipeline-1__fr_lactam 0.000000\n", + "718 pipeline-1__fr_NH2 0.000000\n", + "719 pipeline-1__SMR_VSA2 0.000000\n", + "720 pipeline-1__fr_Imine 0.000000\n", + "721 pipeline-1__fr_phos_acid 0.000000\n", + "\n", + "[722 rows x 2 columns]" ] }, "execution_count": 23, @@ -2684,12 +6990,13 @@ { "cell_type": "code", "execution_count": 24, + "id": "9dbd2a9e", "metadata": { "execution": { - "iopub.execute_input": "2024-04-12T12:11:22.456280Z", - "iopub.status.busy": "2024-04-12T12:11:22.456047Z", - "iopub.status.idle": "2024-04-12T12:11:22.460105Z", - "shell.execute_reply": "2024-04-12T12:11:22.459602Z" + "iopub.execute_input": "2024-11-24T09:28:42.889250Z", + "iopub.status.busy": "2024-11-24T09:28:42.889020Z", + "iopub.status.idle": "2024-11-24T09:28:42.893106Z", + "shell.execute_reply": "2024-11-24T09:28:42.892486Z" } }, "outputs": [ @@ -2698,11 +7005,11 @@ "output_type": "stream", "text": [ "The 5 most important features are:\n", - "pipeline-2__cddd_102\n", "pipeline-1__PEOE_VSA6\n", + "pipeline-2__cddd_102\n", "pipeline-2__cddd_378\n", - "pipeline-2__cddd_369\n", - "pipeline-1__VSA_EState5\n" + "pipeline-1__VSA_EState5\n", + "pipeline-2__cddd_369\n" ] } ], @@ -2715,6 +7022,7 @@ }, { "cell_type": "markdown", + "id": "7b394662", "metadata": {}, "source": [ "As we can see, some CDDD features are among the most important features for the regression model.\n", @@ -2746,5 +7054,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 5 } diff --git a/notebooks/11_safe_inference.ipynb b/notebooks/11_safe_inference.ipynb index 6ee786e..93859ae 100644 --- a/notebooks/11_safe_inference.ipynb +++ b/notebooks/11_safe_inference.ipynb @@ -2,6 +2,7 @@ "cells": [ { "cell_type": "markdown", + "id": "f34dacf0", "metadata": {}, "source": [ "# Safe inference mode\n", @@ -15,22 +16,30 @@ }, { "cell_type": "code", - "execution_count": 12, - "metadata": {}, + "execution_count": 1, + "id": "ac780f4c", + "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:28:44.417205Z", + "iopub.status.busy": "2024-11-24T09:28:44.417002Z", + "iopub.status.idle": "2024-11-24T09:28:45.205864Z", + "shell.execute_reply": "2024-11-24T09:28:45.205244Z" + } + }, "outputs": [ { "data": { "text/plain": [ - "array([[],\n", - " [],\n", - " [],\n", - " [],\n", + "array([[],\n", + " [],\n", + " [],\n", + " [],\n", " [InvalidMol('SmilesToMolTransformer(safe_inference_mode=True)', error='Invalid Molecule: Explicit valence for atom # 0 N, 4, is greater than permitted')],\n", " [InvalidMol('SmilesToMolTransformer(safe_inference_mode=True)', error='Invalid SMILES: I'm not a SMILES')]],\n", " dtype=object)" ] }, - "execution_count": 12, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -39,9 +48,10 @@ "from rdkit import Chem\n", "from scikit_mol.conversions import SmilesToMolTransformer\n", "\n", - "#We have some deprecation warnings, we are adressing them, but they just distract from this demonstration\n", + "# We have some deprecation warnings, we are adressing them, but they just distract from this demonstration\n", "import warnings\n", - "warnings.filterwarnings(\"ignore\", category=DeprecationWarning) \n", + "\n", + "warnings.filterwarnings(\"ignore\", category=DeprecationWarning)\n", "\n", "smiles = [\"C1=CC=C(C=C1)F\", \"C1=CC=C(C=C1)O\", \"C1=CC=C(C=C1)N\", \"C1=CC=C(C=C1)Cl\"]\n", "smiles_with_invalid = smiles + [\"N(C)(C)(C)C\", \"I'm not a SMILES\"]\n", @@ -54,6 +64,7 @@ }, { "cell_type": "markdown", + "id": "bdd18682", "metadata": {}, "source": [ "Without the safe inference mode, the transformation would simply fail, but now we get the expected array back with our RDKit molecules and a last entry which is an object of the type InvalidMol. InvalidMol is simply a placeholder that tells what step failed the conversion and the error. InvalidMol evaluates to `False` in boolean contexts, so it gets easy to filter away and handle in `if`s and list comprehensions. As example:" @@ -61,19 +72,27 @@ }, { "cell_type": "code", - "execution_count": 13, - "metadata": {}, + "execution_count": 2, + "id": "44a6019c", + "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:28:45.208884Z", + "iopub.status.busy": "2024-11-24T09:28:45.208436Z", + "iopub.status.idle": "2024-11-24T09:28:45.213259Z", + "shell.execute_reply": "2024-11-24T09:28:45.212730Z" + } + }, "outputs": [ { "data": { "text/plain": [ - "[array([], dtype=object),\n", - " array([], dtype=object),\n", - " array([], dtype=object),\n", - " array([], dtype=object)]" + "[array([], dtype=object),\n", + " array([], dtype=object),\n", + " array([], dtype=object),\n", + " array([], dtype=object)]" ] }, - "execution_count": 13, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } @@ -84,6 +103,7 @@ }, { "cell_type": "markdown", + "id": "176a44de", "metadata": {}, "source": [ "or" @@ -91,19 +111,27 @@ }, { "cell_type": "code", - "execution_count": 14, - "metadata": {}, + "execution_count": 3, + "id": "8286fd44", + "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:28:45.215847Z", + "iopub.status.busy": "2024-11-24T09:28:45.215431Z", + "iopub.status.idle": "2024-11-24T09:28:45.219372Z", + "shell.execute_reply": "2024-11-24T09:28:45.218875Z" + } + }, "outputs": [ { "data": { "text/plain": [ - "array([,\n", - " ,\n", - " ,\n", - " ], dtype=object)" + "array([,\n", + " ,\n", + " ,\n", + " ], dtype=object)" ] }, - "execution_count": 14, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -115,6 +143,7 @@ }, { "cell_type": "markdown", + "id": "c7be8909", "metadata": {}, "source": [ "Having a failsafe SmilesToMol conversion leads us to next step, featurization. The transformers in safe inference mode now return a NumPy masked array instead of a regular NumPy array. It simply evaluates the incoming mols in a boolean context, so e.g. `None`, `np.nan` and other Python objects that evaluates to False will also get masked (i.e. if you use a dataframe with an ROMol column produced with the PandasTools utility)" @@ -122,31 +151,30 @@ }, { "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n" - ] + "execution_count": 4, + "id": "9a705642", + "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:28:45.221712Z", + "iopub.status.busy": "2024-11-24T09:28:45.221465Z", + "iopub.status.idle": "2024-11-24T09:28:45.246566Z", + "shell.execute_reply": "2024-11-24T09:28:45.245960Z" }, + "lines_to_next_cell": 2 + }, + "outputs": [ { "data": { "text/plain": [ "masked_array(\n", - " data=[[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1,\n", - " 0, 1, 1, 0],\n", - " [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1,\n", - " 0, 0, 1, 0],\n", - " [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1,\n", - " 0, 0, 0, 0],\n", - " [1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1,\n", - " 0, 1, 0, 1],\n", + " data=[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0,\n", + " 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0],\n", + " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0,\n", + " 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0],\n", + " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0,\n", + " 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0],\n", + " [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0,\n", + " 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0],\n", " [--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,\n", " --, --, --, --, --, --, --, --, --],\n", " [--, --, --, --, --, --, --, --, --, --, --, --, --, --, --, --,\n", @@ -169,11 +197,10 @@ " [ True, True, True, True, True, True, True, True, True,\n", " True, True, True, True, True, True, True, True, True,\n", " True, True, True, True, True, True, True]],\n", - " fill_value=999999,\n", - " dtype=int8)" + " fill_value=1e+20)" ] }, - "execution_count": 15, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -181,13 +208,14 @@ "source": [ "from scikit_mol.fingerprints import MorganFingerprintTransformer\n", "\n", - "mfp = MorganFingerprintTransformer(radius=2, nBits=25, safe_inference_mode=True)\n", + "mfp = MorganFingerprintTransformer(radius=2, fpSize=25, safe_inference_mode=True)\n", "fps = mfp.transform(mols_with_invalid)\n", - "fps\n" + "fps" ] }, { "cell_type": "markdown", + "id": "a5e2b301", "metadata": {}, "source": [ "However, currently scikit-learn models accepts masked arrays, but they do not respect the mask! So if you fed it directly to the model to train, it would seemingly work, but the invalid samples would all have the fill_value, meaning you could get weird results. Instead we need the last part of the puzzle, the SafeInferenceWrapper class." @@ -195,8 +223,17 @@ }, { "cell_type": "code", - "execution_count": 16, - "metadata": {}, + "execution_count": 5, + "id": "37987dc9", + "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:28:45.249048Z", + "iopub.status.busy": "2024-11-24T09:28:45.248844Z", + "iopub.status.idle": "2024-11-24T09:28:45.318911Z", + "shell.execute_reply": "2024-11-24T09:28:45.318291Z" + }, + "lines_to_next_cell": 2 + }, "outputs": [ { "name": "stderr", @@ -212,7 +249,7 @@ "array([ 0., 1., 0., 1., nan, nan])" ] }, - "execution_count": 16, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -224,17 +261,19 @@ "\n", "regressor = LogisticRegression()\n", "wrapper = SafeInferenceWrapper(regressor, safe_inference_mode=True)\n", - "wrapper.fit(fps, [0,1,0,1,0,1])\n", - "wrapper.predict(fps)\n" + "wrapper.fit(fps, [0, 1, 0, 1, 0, 1])\n", + "wrapper.predict(fps)" ] }, { "cell_type": "markdown", + "id": "7aa1223f", "metadata": {}, "source": [] }, { "cell_type": "markdown", + "id": "f08d26d5", "metadata": {}, "source": [ "The prediction went fine both in fit and in prediction, where the result shows `nan` for the invalid entries. However, please note fit in sage_inference_mode is not recommended in a training session, but you are warned and not blocked, because maybe you know what you do and do it on purpose.\n", @@ -246,8 +285,16 @@ }, { "cell_type": "code", - "execution_count": 17, - "metadata": {}, + "execution_count": 6, + "id": "51436aa8", + "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:28:45.321557Z", + "iopub.status.busy": "2024-11-24T09:28:45.321253Z", + "iopub.status.idle": "2024-11-24T09:28:45.333442Z", + "shell.execute_reply": "2024-11-24T09:28:45.332830Z" + } + }, "outputs": [ { "name": "stdout", @@ -259,33 +306,21 @@ "With safe inference mode:\n", "[ 1. 0. 1. 0. nan nan]\n" ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n" - ] } ], "source": [ "from scikit_mol.safeinference import set_safe_inference_mode\n", "from sklearn.pipeline import Pipeline\n", "\n", - "pipe = Pipeline([\n", - " (\"smi2mol\", SmilesToMolTransformer()),\n", - " (\"mfp\", MorganFingerprintTransformer(radius=2, nBits=25)),\n", - " (\"safe_regressor\", SafeInferenceWrapper(LogisticRegression()))\n", - "])\n", + "pipe = Pipeline(\n", + " [\n", + " (\"smi2mol\", SmilesToMolTransformer()),\n", + " (\"mfp\", MorganFingerprintTransformer(radius=2, fpSize=25)),\n", + " (\"safe_regressor\", SafeInferenceWrapper(LogisticRegression())),\n", + " ]\n", + ")\n", "\n", - "pipe.fit(smiles, [1,0,1,0])\n", + "pipe.fit(smiles, [1, 0, 1, 0])\n", "\n", "print(\"Without safe inference mode:\")\n", "try:\n", @@ -302,6 +337,7 @@ }, { "cell_type": "markdown", + "id": "cf53d58f", "metadata": {}, "source": [ "We see that the prediction fail without safe inference mode, and proceeds when it's conveniently set by the `set_safe_inference_mode` utility. The model is now ready for save and reuse in a more failsafe manner :-)" @@ -309,6 +345,7 @@ }, { "cell_type": "markdown", + "id": "685e22fd", "metadata": {}, "source": [ "## Combining safe_inference_mode with pandas output\n", @@ -317,19 +354,17 @@ }, { "cell_type": "code", - "execution_count": 18, - "metadata": {}, + "execution_count": 7, + "id": "b8dbd88c", + "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:28:45.336071Z", + "iopub.status.busy": "2024-11-24T09:28:45.335859Z", + "iopub.status.idle": "2024-11-24T09:28:45.351873Z", + "shell.execute_reply": "2024-11-24T09:28:45.351251Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n" - ] - }, { "data": { "text/html": [ @@ -504,7 +539,7 @@ "[4 rows x 25 columns]" ] }, - "execution_count": 18, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -520,6 +555,7 @@ }, { "cell_type": "markdown", + "id": "092ca859", "metadata": {}, "source": [ "Then lets see if we transform a batch with an invalid molecule:" @@ -527,19 +563,17 @@ }, { "cell_type": "code", - "execution_count": 19, - "metadata": {}, + "execution_count": 8, + "id": "710ceeb0", + "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:28:45.354427Z", + "iopub.status.busy": "2024-11-24T09:28:45.354176Z", + "iopub.status.idle": "2024-11-24T09:28:45.377892Z", + "shell.execute_reply": "2024-11-24T09:28:45.377253Z" + } + }, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n" - ] - }, { "data": { "text/html": [ @@ -770,7 +804,7 @@ "[6 rows x 25 columns]" ] }, - "execution_count": 19, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -782,24 +816,31 @@ }, { "cell_type": "markdown", + "id": "b87b46b3", "metadata": {}, "source": [ - "The second output is no longer integers, but floats. As most sklearn models cast input arrays to float32 internally, this difference is likely benign, but that's not guaranteed! Thus if you want to use pandas output for your production models, do check that the final outputs are the same for the valid rows, with and without a single invalid row. Alternatively the dtype for the output of the transformer can be switched to float for consistency." + "The second output is no longer integers, but floats. As most sklearn models cast input arrays to float32 internally, this difference is likely benign, but that's not guaranteed! Thus if you want to use pandas output for your production models, do check that the final outputs are the same for the valid rows, with and without a single invalid row. Alternatively the dtype for the output of the transformer can be switched to float for consistency if its supported by the transformer." ] }, { "cell_type": "code", - "execution_count": 20, - "metadata": {}, + "execution_count": 9, + "id": "bbfe1ec0", + "metadata": { + "execution": { + "iopub.execute_input": "2024-11-24T09:28:45.380434Z", + "iopub.status.busy": "2024-11-24T09:28:45.380233Z", + "iopub.status.idle": "2024-11-24T09:28:45.393639Z", + "shell.execute_reply": "2024-11-24T09:28:45.393095Z" + } + }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n", - "[17:02:50] DEPRECATION WARNING: please use MorganGenerator\n" + "/home/esben/git/scikit-mol/scikit_mol/fingerprints/morgan.py:69: DeprecationWarning: dtype is no longer supported, due to move to generator based fingerprints\n", + " self.dtype = dtype\n" ] }, { @@ -849,99 +890,99 @@ " \n", " \n", " 0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " 1.0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 1\n", + " 1\n", " ...\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " 1.0\n", - " 1.0\n", - " 1.0\n", - " 0.0\n", - " 1.0\n", - " 1.0\n", - " 0.0\n", + " 0\n", + " 1\n", + " 0\n", + " 1\n", + " 1\n", + " 1\n", + " 0\n", + " 1\n", + " 1\n", + " 0\n", " \n", " \n", " 1\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " 1.0\n", - " 1.0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 1\n", + " 1\n", + " 1\n", " ...\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " 1.0\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", + " 0\n", + " 1\n", + " 0\n", + " 0\n", + " 1\n", + " 1\n", + " 0\n", + " 0\n", + " 1\n", + " 0\n", " \n", " \n", " 2\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " 1.0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 1\n", + " 1\n", " ...\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " 1.0\n", - " 1.0\n", - " 1.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", + " 0\n", + " 1\n", + " 0\n", + " 1\n", + " 1\n", + " 1\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", " \n", " \n", " 3\n", - " 1.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " 1.0\n", + " 1\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 0\n", + " 1\n", + " 1\n", " ...\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " 0.0\n", - " 1.0\n", - " 1.0\n", - " 0.0\n", - " 1.0\n", - " 0.0\n", - " 1.0\n", + " 0\n", + " 1\n", + " 0\n", + " 0\n", + " 1\n", + " 1\n", + " 0\n", + " 1\n", + " 0\n", + " 1\n", " \n", " \n", "\n", @@ -950,39 +991,41 @@ ], "text/plain": [ " fp_morgan_1 fp_morgan_2 fp_morgan_3 fp_morgan_4 fp_morgan_5 \\\n", - "0 0.0 0.0 0.0 0.0 0.0 \n", - "1 0.0 0.0 0.0 0.0 0.0 \n", - "2 0.0 0.0 0.0 0.0 0.0 \n", - "3 1.0 0.0 0.0 0.0 0.0 \n", + "0 0 0 0 0 0 \n", + "1 0 0 0 0 0 \n", + "2 0 0 0 0 0 \n", + "3 1 0 0 0 0 \n", "\n", " fp_morgan_6 fp_morgan_7 fp_morgan_8 fp_morgan_9 fp_morgan_10 ... \\\n", - "0 0.0 0.0 0.0 1.0 1.0 ... \n", - "1 0.0 0.0 1.0 1.0 1.0 ... \n", - "2 0.0 0.0 0.0 1.0 1.0 ... \n", - "3 0.0 0.0 0.0 1.0 1.0 ... \n", + "0 0 0 0 1 1 ... \n", + "1 0 0 1 1 1 ... \n", + "2 0 0 0 1 1 ... \n", + "3 0 0 0 1 1 ... \n", "\n", " fp_morgan_16 fp_morgan_17 fp_morgan_18 fp_morgan_19 fp_morgan_20 \\\n", - "0 0.0 1.0 0.0 1.0 1.0 \n", - "1 0.0 1.0 0.0 0.0 1.0 \n", - "2 0.0 1.0 0.0 1.0 1.0 \n", - "3 0.0 1.0 0.0 0.0 1.0 \n", + "0 0 1 0 1 1 \n", + "1 0 1 0 0 1 \n", + "2 0 1 0 1 1 \n", + "3 0 1 0 0 1 \n", "\n", " fp_morgan_21 fp_morgan_22 fp_morgan_23 fp_morgan_24 fp_morgan_25 \n", - "0 1.0 0.0 1.0 1.0 0.0 \n", - "1 1.0 0.0 0.0 1.0 0.0 \n", - "2 1.0 0.0 0.0 0.0 0.0 \n", - "3 1.0 0.0 1.0 0.0 1.0 \n", + "0 1 0 1 1 0 \n", + "1 1 0 0 1 0 \n", + "2 1 0 0 0 0 \n", + "3 1 0 1 0 1 \n", "\n", "[4 rows x 25 columns]" ] }, - "execution_count": 20, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "mfp_float = MorganFingerprintTransformer(radius=2, nBits=25, safe_inference_mode=True, dtype=np.float32)\n", + "mfp_float = MorganFingerprintTransformer(\n", + " radius=2, fpSize=25, safe_inference_mode=True, dtype=np.float32\n", + ")\n", "mfp_float.set_output(transform=\"pandas\")\n", "fps = mfp_float.transform(mols)\n", "fps" @@ -990,6 +1033,7 @@ }, { "cell_type": "markdown", + "id": "2c7b382c", "metadata": {}, "source": [ "I hope this new feature of Scikit-Mol will make it even easier to handle models, even when used in environments without SMILES or molecule validity guarantees." @@ -1019,5 +1063,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 5 } diff --git a/notebooks/11_safe_inference.py b/notebooks/11_safe_inference.py index 83d4d99..14b97f7 100644 --- a/notebooks/11_safe_inference.py +++ b/notebooks/11_safe_inference.py @@ -26,9 +26,10 @@ from rdkit import Chem from scikit_mol.conversions import SmilesToMolTransformer -#We have some deprecation warnings, we are adressing them, but they just distract from this demonstration +# We have some deprecation warnings, we are adressing them, but they just distract from this demonstration import warnings -warnings.filterwarnings("ignore", category=DeprecationWarning) + +warnings.filterwarnings("ignore", category=DeprecationWarning) smiles = ["C1=CC=C(C=C1)F", "C1=CC=C(C=C1)O", "C1=CC=C(C=C1)N", "C1=CC=C(C=C1)Cl"] smiles_with_invalid = smiles + ["N(C)(C)(C)C", "I'm not a SMILES"] @@ -57,7 +58,7 @@ # %% from scikit_mol.fingerprints import MorganFingerprintTransformer -mfp = MorganFingerprintTransformer(radius=2, nBits=25, safe_inference_mode=True) +mfp = MorganFingerprintTransformer(radius=2, fpSize=25, safe_inference_mode=True) fps = mfp.transform(mols_with_invalid) fps @@ -72,7 +73,7 @@ regressor = LogisticRegression() wrapper = SafeInferenceWrapper(regressor, safe_inference_mode=True) -wrapper.fit(fps, [0,1,0,1,0,1]) +wrapper.fit(fps, [0, 1, 0, 1, 0, 1]) wrapper.predict(fps) @@ -90,13 +91,15 @@ from scikit_mol.safeinference import set_safe_inference_mode from sklearn.pipeline import Pipeline -pipe = Pipeline([ - ("smi2mol", SmilesToMolTransformer()), - ("mfp", MorganFingerprintTransformer(radius=2, nBits=25)), - ("safe_regressor", SafeInferenceWrapper(LogisticRegression())) -]) +pipe = Pipeline( + [ + ("smi2mol", SmilesToMolTransformer()), + ("mfp", MorganFingerprintTransformer(radius=2, fpSize=25)), + ("safe_regressor", SafeInferenceWrapper(LogisticRegression())), + ] +) -pipe.fit(smiles, [1,0,1,0]) +pipe.fit(smiles, [1, 0, 1, 0]) print("Without safe inference mode:") try: @@ -133,10 +136,12 @@ fps # %% [markdown] -# The second output is no longer integers, but floats. As most sklearn models cast input arrays to float32 internally, this difference is likely benign, but that's not guaranteed! Thus if you want to use pandas output for your production models, do check that the final outputs are the same for the valid rows, with and without a single invalid row. Alternatively the dtype for the output of the transformer can be switched to float for consistency. +# The second output is no longer integers, but floats. As most sklearn models cast input arrays to float32 internally, this difference is likely benign, but that's not guaranteed! Thus if you want to use pandas output for your production models, do check that the final outputs are the same for the valid rows, with and without a single invalid row. Alternatively the dtype for the output of the transformer can be switched to float for consistency if its supported by the transformer. # %% -mfp_float = MorganFingerprintTransformer(radius=2, nBits=25, safe_inference_mode=True, dtype=np.float32) +mfp_float = MorganFingerprintTransformer( + radius=2, fpSize=25, safe_inference_mode=True, dtype=np.float32 +) mfp_float.set_output(transform="pandas") fps = mfp_float.transform(mols) fps diff --git a/scikit_mol/fingerprints.py b/scikit_mol/fingerprints.py deleted file mode 100644 index f044a06..0000000 --- a/scikit_mol/fingerprints.py +++ /dev/null @@ -1,722 +0,0 @@ -from multiprocessing import Pool, get_context -import multiprocessing -import re -from typing import Union -from rdkit import Chem -from rdkit import DataStructs - -# from rdkit.Chem.AllChem import GetMorganFingerprintAsBitVect -from rdkit.Chem import rdMolDescriptors -from rdkit.Chem import rdFingerprintGenerator -from rdkit.Chem import rdMHFPFingerprint -from rdkit.Avalon import pyAvalonTools - -import numpy as np -import pandas as pd -from scipy.sparse import lil_matrix -from scipy.sparse import vstack - -from sklearn.base import BaseEstimator, TransformerMixin -from scikit_mol.core import check_transform_input - -from abc import ABC, abstractmethod - - -_PATTERN_FINGERPRINT_TRANSFORMER = re.compile( - r"^(?P\w+)FingerprintTransformer$" -) - - -class FpsTransformer(ABC, BaseEstimator, TransformerMixin): - def __init__( - self, - parallel: Union[bool, int] = False, - start_method: str = None, - safe_inference_mode: bool = False, - dtype: np.dtype = np.int8, - ): - self.parallel = parallel - self.start_method = start_method - self.safe_inference_mode = safe_inference_mode - self.dtype = dtype - - def _get_column_prefix(self) -> str: - matched = _PATTERN_FINGERPRINT_TRANSFORMER.match(type(self).__name__) - if matched: - fingerprint_name = matched.group("fingerprint_name") - return f"fp_{fingerprint_name.lower()}" - else: - return "fp" - - def _get_n_digits_column_suffix(self) -> int: - return len(str(self.nBits)) - - def get_display_feature_names_out(self, input_features=None): - """Get feature names for display purposes - - All feature names will have the same length, - since the different elements will be prefixed with zeros - depending on the number of bits. - """ - prefix = self._get_column_prefix() - n_digits = self._get_n_digits_column_suffix() - return np.array( - [f"{prefix}_{str(i).zfill(n_digits)}" for i in range(1, self.nBits + 1)] - ) - - def get_feature_names_out(self, input_features=None): - """Get feature names for fingerprint transformers - - This method is used by the scikit-learn set_output API - to get the column names of the transformed dataframe. - """ - prefix = self._get_column_prefix() - return np.array([f"{prefix}_{i}" for i in range(1, self.nBits + 1)]) - - @abstractmethod - def _mol2fp(self, mol): - """Generate fingerprint from mol - - MUST BE OVERWRITTEN - """ - raise NotImplementedError("_mol2fp not implemented") - - def _fp2array(self, fp): - if fp: - arr = np.zeros((self.nBits,), dtype=self.dtype) - DataStructs.ConvertToNumpyArray(fp, arr) - return arr - else: - return np.ma.masked_all((self.nBits,), dtype=self.dtype) - - def _transform_mol(self, mol): - if not mol and self.safe_inference_mode: - return self._fp2array(False) - try: - fp = self._mol2fp(mol) - return self._fp2array(fp) - except Exception as e: - if self.safe_inference_mode: - return self._fp2array(False) - else: - raise e - - def fit(self, X, y=None): - """Included for scikit-learn compatibility - - Also sets the column prefix for use by the transform method with dataframe output. - """ - return self - - @check_transform_input - def _transform(self, X): - if self.safe_inference_mode: - # Use the new method with masked arrays if we're in safe inference mode - arrays = [self._transform_mol(mol) for mol in X] - return np.ma.stack(arrays) - else: - # Use the original, faster method if we're not in safe inference mode - arr = np.zeros((len(X), self.nBits), dtype=self.dtype) - for i, mol in enumerate(X): - arr[i, :] = self._transform_mol(mol) - return arr - - def _transform_sparse(self, X): - arr = np.zeros((len(X), self.nBits), dtype=self.dtype) - for i, mol in enumerate(X): - arr[i, :] = self._transform_mol(mol) - - return lil_matrix(arr) - - def transform(self, X, y=None): - """Transform a list of RDKit molecule objects into a fingerprint array - - Parameters - ---------- - X : (List, np.array, pd.Series) - A list of RDKit molecules - y : NoneType, optional - Target values for scikit-learn compatibility, not used, by default None - - Returns - ------- - np.array - Fingerprints, shape (samples, fingerprint size) - """ - if not self.parallel: - return self._transform(X) - - elif self.parallel: - n_processes = ( - self.parallel if self.parallel > 1 else None - ) # Pool(processes=None) autodetects - n_chunks = ( - n_processes if n_processes is not None else multiprocessing.cpu_count() - ) - - with get_context(self.start_method).Pool(processes=n_processes) as pool: - x_chunks = np.array_split(X, n_chunks) - # TODO check what is fastest, pickle or recreate and do this only for classes that need this - # arrays = pool.map(self._transform, x_chunks) - parameters = self.get_params() - # TODO: create "transform_parallel" function in the core module, - # and use it here and in the descriptors transformer - # x_chunks = [np.array(x).reshape(-1, 1) for x in x_chunks] - arrays = pool.map( - parallel_helper, - [ - (self.__class__.__name__, parameters, x_chunk) - for x_chunk in x_chunks - ], - ) - if self.safe_inference_mode: - arr = np.ma.concatenate(arrays) - else: - arr = np.concatenate(arrays) - return arr - - -class MACCSKeysFingerprintTransformer(FpsTransformer): - def __init__( - self, - parallel: Union[bool, int] = False, - safe_inference_mode: bool = False, - dtype: np.dtype = np.int8, - ): - """MACCS keys fingerprinter - calculates the 167 fixed MACCS keys - """ - super().__init__( - parallel=parallel, safe_inference_mode=safe_inference_mode, dtype=dtype - ) - self.nBits = 167 - - @property - def nBits(self): - return self._nBits - - @nBits.setter - def nBits(self, nBits): - if nBits != 167: - raise ValueError( - "nBits can only be 167, matching the number of defined MACCS keys!" - ) - self._nBits = nBits - - def _mol2fp(self, mol): - return rdMolDescriptors.GetMACCSKeysFingerprint(mol) - - -class RDKitFingerprintTransformer(FpsTransformer): - def __init__( - self, - minPath: int = 1, - maxPath: int = 7, - useHs: bool = True, - branchedPaths: bool = True, - useBondOrder: bool = True, - countSimulation: bool = False, - countBounds=None, - fpSize: int = 2048, - numBitsPerFeature: int = 2, - atomInvariantsGenerator=None, - parallel: Union[bool, int] = False, - safe_inference_mode: bool = False, - dtype: np.dtype = np.int8, - ): - """Calculates the RDKit fingerprints - - Parameters - ---------- - minPath : int, optional - the minimum path length (in bonds) to be included, by default 1 - maxPath : int, optional - the maximum path length (in bonds) to be included, by default 7 - useHs : bool, optional - toggles inclusion of Hs in paths (if the molecule has explicit Hs), by default True - branchedPaths : bool, optional - toggles generation of branched subgraphs, not just linear paths, by default True - useBondOrder : bool, optional - toggles inclusion of bond orders in the path hashes, by default True - countSimulation : bool, optional - if set, use count simulation while generating the fingerprint, by default False - countBounds : _type_, optional - boundaries for count simulation, corresponding bit will be set if the count is higher than the number provided for that spot, by default None - fpSize : int, optional - size of the generated fingerprint, does not affect the sparse versions, by default 2048 - numBitsPerFeature : int, optional - the number of bits set per path/subgraph found, by default 2 - atomInvariantsGenerator : _type_, optional - atom invariants to be used during fingerprint generation, by default None - """ - super().__init__( - parallel=parallel, safe_inference_mode=safe_inference_mode, dtype=dtype - ) - self.minPath = minPath - self.maxPath = maxPath - self.useHs = useHs - self.branchedPaths = branchedPaths - self.useBondOrder = useBondOrder - self.countSimulation = countSimulation - self.countBounds = countBounds - self.fpSize = fpSize - self.numBitsPerFeature = numBitsPerFeature - self.atomInvariantsGenerator = atomInvariantsGenerator - - @property - def fpSize(self): - return self.nBits - - # Scikit-Learn expects to be able to set fpSize directly on object via .set_params(), so this updates nBits used by the abstract class - @fpSize.setter - def fpSize(self, fpSize): - self.nBits = fpSize - - def _mol2fp(self, mol): - generator = rdFingerprintGenerator.GetRDKitFPGenerator( - minPath=int(self.minPath), - maxPath=int(self.maxPath), - useHs=bool(self.useHs), - branchedPaths=bool(self.branchedPaths), - useBondOrder=bool(self.useBondOrder), - countSimulation=bool(self.countSimulation), - countBounds=bool(self.countBounds), - fpSize=int(self.fpSize), - numBitsPerFeature=int(self.numBitsPerFeature), - atomInvariantsGenerator=self.atomInvariantsGenerator, - ) - return generator.GetFingerprint(mol) - - -class AtomPairFingerprintTransformer(FpsTransformer): - def __init__( - self, - minLength: int = 1, - maxLength: int = 30, - fromAtoms=0, - ignoreAtoms=0, - atomInvariants=0, - nBitsPerEntry: int = 4, - includeChirality: bool = False, - use2D: bool = True, - confId: int = -1, - nBits=2048, - useCounts: bool = False, - parallel: Union[bool, int] = False, - safe_inference_mode: bool = False, - dtype: np.dtype = np.int8, - ): - super().__init__( - parallel=parallel, safe_inference_mode=safe_inference_mode, dtype=dtype - ) - self.minLength = minLength - self.maxLength = maxLength - self.fromAtoms = fromAtoms - self.ignoreAtoms = ignoreAtoms - self.atomInvariants = atomInvariants - self.includeChirality = includeChirality - self.use2D = use2D - self.confId = confId - self.nBits = nBits - self.nBitsPerEntry = nBitsPerEntry - self.useCounts = useCounts - - def _mol2fp(self, mol): - if self.useCounts: - return rdMolDescriptors.GetHashedAtomPairFingerprint( - mol, - nBits=int(self.nBits), - minLength=int(self.minLength), - maxLength=int(self.maxLength), - fromAtoms=self.fromAtoms, - ignoreAtoms=self.ignoreAtoms, - atomInvariants=self.atomInvariants, - includeChirality=bool(self.includeChirality), - use2D=bool(self.use2D), - confId=int(self.confId), - ) - else: - return rdMolDescriptors.GetHashedAtomPairFingerprintAsBitVect( - mol, - nBits=int(self.nBits), - minLength=int(self.minLength), - maxLength=int(self.maxLength), - fromAtoms=self.fromAtoms, - ignoreAtoms=self.ignoreAtoms, - atomInvariants=self.atomInvariants, - nBitsPerEntry=int(self.nBitsPerEntry), - includeChirality=bool(self.includeChirality), - use2D=bool(self.use2D), - confId=int(self.confId), - ) - - -class TopologicalTorsionFingerprintTransformer(FpsTransformer): - def __init__( - self, - targetSize: int = 4, - fromAtoms=0, - ignoreAtoms=0, - atomInvariants=0, - includeChirality: bool = False, - nBitsPerEntry: int = 4, - nBits=2048, - useCounts: bool = False, - parallel: Union[bool, int] = False, - safe_inference_mode: bool = False, - dtype: np.dtype = np.int8, - ): - super().__init__( - parallel=parallel, safe_inference_mode=safe_inference_mode, dtype=dtype - ) - self.targetSize = targetSize - self.fromAtoms = fromAtoms - self.ignoreAtoms = ignoreAtoms - self.atomInvariants = atomInvariants - self.includeChirality = includeChirality - self.nBitsPerEntry = nBitsPerEntry - self.nBits = nBits - self.useCounts = useCounts - - def _mol2fp(self, mol): - if self.useCounts: - return rdMolDescriptors.GetHashedTopologicalTorsionFingerprint( - mol, - nBits=int(self.nBits), - targetSize=int(self.targetSize), - fromAtoms=self.fromAtoms, - ignoreAtoms=self.ignoreAtoms, - atomInvariants=self.atomInvariants, - includeChirality=bool(self.includeChirality), - ) - else: - return rdMolDescriptors.GetHashedTopologicalTorsionFingerprintAsBitVect( - mol, - nBits=int(self.nBits), - targetSize=int(self.targetSize), - fromAtoms=self.fromAtoms, - ignoreAtoms=self.ignoreAtoms, - atomInvariants=self.atomInvariants, - includeChirality=bool(self.includeChirality), - nBitsPerEntry=int(self.nBitsPerEntry), - ) - - -class MHFingerprintTransformer(FpsTransformer): - def __init__( - self, - radius: int = 3, - rings: bool = True, - isomeric: bool = False, - kekulize: bool = False, - min_radius: int = 1, - n_permutations: int = 2048, - seed: int = 42, - parallel: Union[bool, int] = False, - safe_inference_mode: bool = False, - dtype: np.dtype = np.int32, - ): - """Transforms the RDKit mol into the MinHash fingerprint (MHFP) - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-018-0321-8 - - Args: - radius (int, optional): The MHFP radius. Defaults to 3. - rings (bool, optional): Whether or not to include rings in the shingling. Defaults to True. - isomeric (bool, optional): Whether the isomeric SMILES to be considered. Defaults to False. - kekulize (bool, optional): Whether or not to kekulize the extracted SMILES. Defaults to False. - min_radius (int, optional): The minimum radius that is used to extract n-gram. Defaults to 1. - n_permutations (int, optional): The number of permutations used for hashing. Defaults to 0, - this is effectively the length of the FP - seed (int, optional): The value used to seed numpy.random. Defaults to 0. - """ - super().__init__( - parallel=parallel, safe_inference_mode=safe_inference_mode, dtype=dtype - ) - self.radius = radius - self.rings = rings - self.isomeric = isomeric - self.kekulize = kekulize - self.min_radius = min_radius - # Set the .n_permutations and .seed without creating the encoder twice - self._n_permutations = n_permutations - self._seed = seed - # create the encoder instance - self._recreate_encoder() - - def __getstate__(self): - # Get the state of the parent class - state = super().__getstate__() - # Remove the unpicklable property from the state - state.pop("mhfp_encoder", None) # mhfp_encoder is not picklable - return state - - def __setstate__(self, state): - # Restore the state of the parent class - super().__setstate__(state) - # Re-create the unpicklable property - self._recreate_encoder() - - def _mol2fp(self, mol): - fp = self.mhfp_encoder.EncodeMol( - mol, self.radius, self.rings, self.isomeric, self.kekulize, self.min_radius - ) - return fp - - def _fp2array(self, fp): - return np.array(fp) - - def _recreate_encoder(self): - self.mhfp_encoder = rdMHFPFingerprint.MHFPEncoder( - self._n_permutations, self._seed - ) - - @property - def seed(self): - return self._seed - - @seed.setter - def seed(self, seed): - self._seed = seed - # each time the seed parameter is modified refresh an instance of the encoder - self._recreate_encoder() - - @property - def n_permutations(self): - return self._n_permutations - - @n_permutations.setter - def n_permutations(self, n_permutations): - self._n_permutations = n_permutations - # each time the n_permutations parameter is modified refresh an instance of the encoder - self._recreate_encoder() - - @property - def nBits(self): - # to be compliant with the requirement of the base class - return self._n_permutations - - -class SECFingerprintTransformer(FpsTransformer): - # https://jcheminf.biomedcentral.com/articles/10.1186/s13321-018-0321-8 - def __init__( - self, - radius: int = 3, - rings: bool = True, - isomeric: bool = False, - kekulize: bool = False, - min_radius: int = 1, - length: int = 2048, - n_permutations: int = 0, - seed: int = 0, - parallel: Union[bool, int] = False, - safe_inference_mode: bool = False, - dtype: np.dtype = np.int8, - ): - """Transforms the RDKit mol into the SMILES extended connectivity fingerprint (SECFP) - - Args: - radius (int, optional): The MHFP radius. Defaults to 3. - rings (bool, optional): Whether or not to include rings in the shingling. Defaults to True. - isomeric (bool, optional): Whether the isomeric SMILES to be considered. Defaults to False. - kekulize (bool, optional): Whether or not to kekulize the extracted SMILES. Defaults to False. - min_radius (int, optional): The minimum radius that is used to extract n-gram. Defaults to 1. - length (int, optional): The length of the folded fingerprint. Defaults to 2048. - n_permutations (int, optional): The number of permutations used for hashing. Defaults to 0. - seed (int, optional): The value used to seed numpy.random. Defaults to 0. - """ - super().__init__( - parallel=parallel, safe_inference_mode=safe_inference_mode, dtype=dtype - ) - self.radius = radius - self.rings = rings - self.isomeric = isomeric - self.kekulize = kekulize - self.min_radius = min_radius - self.length = length - # Set the .n_permutations and seed without creating the encoder twice - self._n_permutations = n_permutations - self._seed = seed - # create the encoder instance - self._recreate_encoder() - - def __getstate__(self): - # Get the state of the parent class - state = super().__getstate__() - # Remove the unpicklable property from the state - state.pop("mhfp_encoder", None) # mhfp_encoder is not picklable - return state - - def __setstate__(self, state): - # Restore the state of the parent class - super().__setstate__(state) - # Re-create the unpicklable property - self._recreate_encoder() - - def _mol2fp(self, mol): - return self.mhfp_encoder.EncodeSECFPMol( - mol, - self.radius, - self.rings, - self.isomeric, - self.kekulize, - self.min_radius, - self.length, - ) - - def _recreate_encoder(self): - self.mhfp_encoder = rdMHFPFingerprint.MHFPEncoder( - self._n_permutations, self._seed - ) - - @property - def seed(self): - return self._seed - - @seed.setter - def seed(self, seed): - self._seed = seed - # each time the seed parameter is modified refresh an instace of the encoder - self._recreate_encoder() - - @property - def n_permutations(self): - return self._n_permutations - - @n_permutations.setter - def n_permutations(self, n_permutations): - self._n_permutations = n_permutations - # each time the n_permutations parameter is modified refresh an instace of the encoder - self._recreate_encoder() - - @property - def nBits(self): - # to be compliant with the requirement of the base class - return self.length - - -class MorganFingerprintTransformer(FpsTransformer): - def __init__( - self, - nBits=2048, - radius=2, - useChirality=False, - useBondTypes=True, - useFeatures=False, - useCounts=False, - parallel: Union[bool, int] = False, - safe_inference_mode: bool = False, - dtype: np.dtype = np.int8, - ): - """Transform RDKit mols into Count or bit-based hashed MorganFingerprints - - Parameters - ---------- - nBits : int, optional - Size of the hashed fingerprint, by default 2048 - radius : int, optional - Radius of the fingerprint, by default 2 - useChirality : bool, optional - Include chirality in calculation of the fingerprint keys, by default False - useBondTypes : bool, optional - Include bondtypes in calculation of the fingerprint keys, by default True - useFeatures : bool, optional - use chemical features, rather than atom-type in calculation of the fingerprint keys, by default False - useCounts : bool, optional - If toggled will create the count and not bit-based fingerprint, by default False - """ - super().__init__( - parallel=parallel, safe_inference_mode=safe_inference_mode, dtype=dtype - ) - self.nBits = nBits - self.radius = radius - self.useChirality = useChirality - self.useBondTypes = useBondTypes - self.useFeatures = useFeatures - self.useCounts = useCounts - - def _mol2fp(self, mol): - if self.useCounts: - return rdMolDescriptors.GetHashedMorganFingerprint( - mol, - int(self.radius), - nBits=int(self.nBits), - useFeatures=bool(self.useFeatures), - useChirality=bool(self.useChirality), - useBondTypes=bool(self.useBondTypes), - ) - else: - return rdMolDescriptors.GetMorganFingerprintAsBitVect( - mol, - int(self.radius), - nBits=int(self.nBits), - useFeatures=bool(self.useFeatures), - useChirality=bool(self.useChirality), - useBondTypes=bool(self.useBondTypes), - ) - - -class AvalonFingerprintTransformer(FpsTransformer): - # Fingerprint from the Avalon toolkeit, https://doi.org/10.1021/ci050413p - def __init__( - self, - nBits: int = 512, - isQuery: bool = False, - resetVect: bool = False, - bitFlags: int = 15761407, - useCounts: bool = False, - parallel: Union[bool, int] = False, - safe_inference_mode: bool = False, - dtype: np.dtype = np.int8, - ): - """Transform RDKit mols into Count or bit-based Avalon Fingerprints - - Parameters - ---------- - nBits : int, optional - Size of the fingerprint, by default 512 - isQuery : bool, optional - use the fingerprint for a query structure, by default False - resetVect : bool, optional - reset vector, by default False NB: only used in GetAvalonFP (not for GetAvalonCountFP) - bitFlags : int, optional - Substructure fingerprint (32767) or similarity fingerprint (15761407) by default 15761407 - useCounts : bool, optional - If toggled will create the count and not bit-based fingerprint, by default False - """ - super().__init__( - parallel=parallel, safe_inference_mode=safe_inference_mode, dtype=dtype - ) - self.nBits = nBits - self.isQuery = isQuery - self.resetVect = resetVect - self.bitFlags = bitFlags - self.useCounts = useCounts - - def _mol2fp(self, mol): - if self.useCounts: - return pyAvalonTools.GetAvalonCountFP( - mol, - nBits=int(self.nBits), - isQuery=bool(self.isQuery), - bitFlags=int(self.bitFlags), - ) - else: - return pyAvalonTools.GetAvalonFP( - mol, - nBits=int(self.nBits), - isQuery=bool(self.isQuery), - resetVect=bool(self.resetVect), - bitFlags=int(self.bitFlags), - ) - - -def parallel_helper(args): - """Parallel_helper takes a tuple with classname, the objects parameters and the mols to process. - Then instantiates the class with the parameters and processes the mol. - Intention is to be able to do this in child processes as some classes can't be pickled""" - classname, parameters, X_mols = args - from scikit_mol import fingerprints - - transformer = getattr(fingerprints, classname)(**parameters) - return transformer._transform(X_mols) diff --git a/scikit_mol/fingerprints/__init__.py b/scikit_mol/fingerprints/__init__.py new file mode 100644 index 0000000..c0b4cb7 --- /dev/null +++ b/scikit_mol/fingerprints/__init__.py @@ -0,0 +1,14 @@ +from .baseclasses import ( + FpsTransformer, + FpsGeneratorTransformer, +) # TODO, for backwards compatibility with tests, needs to be removed + +from .atompair import AtomPairFingerprintTransformer +from .avalon import AvalonFingerprintTransformer +from .maccs import MACCSKeysFingerprintTransformer +from .minhash import MHFingerprintTransformer, SECFingerprintTransformer +from .morgan import MorganFingerprintTransformer +from .rdkitfp import RDKitFingerprintTransformer +from .topologicaltorsion import ( + TopologicalTorsionFingerprintTransformer, +) diff --git a/scikit_mol/fingerprints/atompair.py b/scikit_mol/fingerprints/atompair.py new file mode 100644 index 0000000..ded1f18 --- /dev/null +++ b/scikit_mol/fingerprints/atompair.py @@ -0,0 +1,76 @@ +from typing import Union + +import numpy as np + +from warnings import warn + +from .baseclasses import FpsTransformer, FpsGeneratorTransformer + +from rdkit.Chem.rdFingerprintGenerator import GetAtomPairGenerator +from rdkit.Chem import rdMolDescriptors + + +class AtomPairFingerprintTransformer(FpsGeneratorTransformer): + _regenerate_on_properties = ( + "fpSize", + "includeChirality", + "use2D", + "minLength", + "maxLength", + ) + + def __init__( + self, + minLength: int = 1, + maxLength: int = 30, + fromAtoms=None, + ignoreAtoms=None, + atomInvariants=None, + includeChirality: bool = False, + use2D: bool = True, + confId: int = -1, + fpSize: int = 2048, + useCounts: bool = False, + parallel: Union[bool, int] = False, + safe_inference_mode: bool = False, + ): + self._initializing = True + super().__init__(parallel=parallel, safe_inference_mode=safe_inference_mode) + self.fpSize = fpSize + self.use2D = use2D + self.includeChirality = includeChirality + self.minLength = minLength + self.maxLength = maxLength + + self.useCounts = useCounts + self.confId = confId + self.fromAtoms = fromAtoms + self.ignoreAtoms = ignoreAtoms + self.atomInvariants = atomInvariants + self._generate_fp_generator() + delattr(self, "_initializing") + + def _generate_fp_generator(self): + self._fpgen = GetAtomPairGenerator( + minDistance=int(self.minLength), + maxDistance=int(self.maxLength), + includeChirality=bool(self.includeChirality), + use2D=bool(self.use2D), + fpSize=int(self.fpSize), + ) + + def _transform_mol(self, mol) -> np.array: + if self.useCounts: + return self._fpgen.GetCountFingerprintAsNumPy( + mol, + fromAtoms=self.fromAtoms, + ignoreAtoms=self.ignoreAtoms, + customAtomInvariants=self.atomInvariants, + ) + else: + return self._fpgen.GetFingerprintAsNumPy( + mol, + fromAtoms=self.fromAtoms, + ignoreAtoms=self.ignoreAtoms, + customAtomInvariants=self.atomInvariants, + ) diff --git a/scikit_mol/fingerprints/avalon.py b/scikit_mol/fingerprints/avalon.py new file mode 100644 index 0000000..074632d --- /dev/null +++ b/scikit_mol/fingerprints/avalon.py @@ -0,0 +1,62 @@ +from typing import Union + +import numpy as np + +from .baseclasses import FpsTransformer + +from rdkit.Avalon import pyAvalonTools + + +class AvalonFingerprintTransformer(FpsTransformer): + # Fingerprint from the Avalon toolkeit, https://doi.org/10.1021/ci050413p + def __init__( + self, + fpSize: int = 512, + isQuery: bool = False, + resetVect: bool = False, + bitFlags: int = 15761407, + useCounts: bool = False, + parallel: Union[bool, int] = False, + safe_inference_mode: bool = False, + dtype: np.dtype = np.int8, + ): + """Transform RDKit mols into Count or bit-based Avalon Fingerprints + + Parameters + ---------- + fpSize : int, optional + Size of the fingerprint, by default 512 + isQuery : bool, optional + use the fingerprint for a query structure, by default False + resetVect : bool, optional + reset vector, by default False NB: only used in GetAvalonFP (not for GetAvalonCountFP) + bitFlags : int, optional + Substructure fingerprint (32767) or similarity fingerprint (15761407) by default 15761407 + useCounts : bool, optional + If toggled will create the count and not bit-based fingerprint, by default False + """ + super().__init__( + parallel=parallel, safe_inference_mode=safe_inference_mode, dtype=dtype + ) + self.fpSize = fpSize + self.isQuery = isQuery + self.resetVect = resetVect + self.bitFlags = bitFlags + self.useCounts = useCounts + + def _mol2fp(self, mol): + if self.useCounts: + return pyAvalonTools.GetAvalonCountFP( + mol, + nBits=int(self.fpSize), + isQuery=bool(self.isQuery), + bitFlags=int(self.bitFlags), + ) + else: + return pyAvalonTools.GetAvalonFP( + mol, + nBits=int(self.fpSize), + isQuery=bool(self.isQuery), + resetVect=bool(self.resetVect), + bitFlags=int(self.bitFlags), + ) diff --git a/scikit_mol/fingerprints/baseclasses.py b/scikit_mol/fingerprints/baseclasses.py new file mode 100644 index 0000000..e28fa07 --- /dev/null +++ b/scikit_mol/fingerprints/baseclasses.py @@ -0,0 +1,336 @@ +from multiprocessing import Pool, get_context +import multiprocessing +import re +import inspect +from warnings import warn, simplefilter + +from typing import Union +from rdkit import DataStructs + +# from rdkit.Chem.AllChem import GetMorganFingerprintAsBitVect +from rdkit.Chem import rdMolDescriptors +from rdkit.Chem import rdFingerprintGenerator +from rdkit.Chem import rdMHFPFingerprint + + +from rdkit.Chem.rdFingerprintGenerator import ( + GetMorganGenerator, + GetMorganFeatureAtomInvGen, + GetTopologicalTorsionGenerator, + GetAtomPairGenerator, + GetRDKitFPGenerator, +) + +import numpy as np +import pandas as pd +from scipy.sparse import lil_matrix +from scipy.sparse import vstack + +from sklearn.base import BaseEstimator, TransformerMixin +from scikit_mol.core import check_transform_input + +from abc import ABC, abstractmethod + +simplefilter("always", DeprecationWarning) + +_PATTERN_FINGERPRINT_TRANSFORMER = re.compile( + r"^(?P\w+)FingerprintTransformer$" +) + + +class BaseFpsTransformer(ABC, BaseEstimator, TransformerMixin): + def __init__( + self, + parallel: Union[bool, int] = False, + start_method: str = None, + safe_inference_mode: bool = False, + ): + self.parallel = parallel + self.start_method = start_method + self.safe_inference_mode = safe_inference_mode + + # TODO, remove when finally deprecating nBits and dtype + @property + def nBits(self): + warn( + "nBits will be replaced by fpSize, due to changes harmonization!", + DeprecationWarning, + stacklevel=2, + ) + return self.fpSize + + # TODO, remove when finally deprecating nBits and dtype + @nBits.setter + def nBits(self, nBits): + if nBits is not None: + warn( + "nBits will be replaced by fpSize, due to changes harmonization!", + DeprecationWarning, + stacklevel=3, + ) + self.fpSize = nBits + + def _get_column_prefix(self) -> str: + matched = _PATTERN_FINGERPRINT_TRANSFORMER.match(type(self).__name__) + if matched: + fingerprint_name = matched.group("fingerprint_name") + return f"fp_{fingerprint_name.lower()}" + else: + return "fp" + + def _get_n_digits_column_suffix(self) -> int: + return len(str(self.fpSize)) + + def get_display_feature_names_out(self, input_features=None): + """Get feature names for display purposes + + All feature names will have the same length, + since the different elements will be prefixed with zeros + depending on the number of bits. + """ + prefix = self._get_column_prefix() + n_digits = self._get_n_digits_column_suffix() + return np.array( + [f"{prefix}_{str(i).zfill(n_digits)}" for i in range(1, self.fpSize + 1)] + ) + + def get_feature_names_out(self, input_features=None): + """Get feature names for fingerprint transformers + + This method is used by the scikit-learn set_output API + to get the column names of the transformed dataframe. + """ + prefix = self._get_column_prefix() + return np.array([f"{prefix}_{i}" for i in range(1, self.fpSize + 1)]) + + def _safe_transform_mol(self, mol): + """Handle safe inference mode with masked arrays""" + if not mol and self.safe_inference_mode: + return np.ma.masked_all(self.fpSize) + + try: + result = self._transform_mol(mol) + return result + except Exception as e: + if self.safe_inference_mode: + return np.ma.masked_all(self.fpSize) + else: + raise e + + @abstractmethod + def _transform_mol(self, mol): + """Transform a single molecule to numpy array""" + raise NotImplementedError + + def fit(self, X, y=None): + """Included for scikit-learn compatibility + + Also sets the column prefix for use by the transform method with dataframe output. + """ + return self + + @check_transform_input + def _transform(self, X): + if self.safe_inference_mode: + arrays = [self._safe_transform_mol(mol) for mol in X] + return np.ma.stack(arrays) + else: + arrays = [self._transform_mol(mol) for mol in X] + return np.stack(arrays) + + def _transform_sparse(self, X): + arr = np.zeros((len(X), self.fpSize), dtype=self.dtype) + for i, mol in enumerate(X): + arr[i, :] = self._transform_mol(mol) + + return lil_matrix(arr) + + def transform(self, X, y=None): + """Transform a list of RDKit molecule objects into a fingerprint array + + Parameters + ---------- + X : (List, np.array, pd.Series) + A list of RDKit molecules + y : NoneType, optional + Target values for scikit-learn compatibility, not used, by default None + + Returns + ------- + np.array + Fingerprints, shape (samples, fingerprint size) + """ + if not self.parallel: + return self._transform(X) + + elif self.parallel: + n_processes = ( + self.parallel if self.parallel > 1 else None + ) # Pool(processes=None) autodetects + n_chunks = ( + n_processes if n_processes is not None else multiprocessing.cpu_count() + ) + + with get_context(self.start_method).Pool(processes=n_processes) as pool: + x_chunks = np.array_split(X, n_chunks) + # TODO check what is fastest, pickle or recreate and do this only for classes that need this + # arrays = pool.map(self._transform, x_chunks) + parameters = self.get_params() + # TODO: create "transform_parallel" function in the core module, + # and use it here and in the descriptors transformer + # x_chunks = [np.array(x).reshape(-1, 1) for x in x_chunks] + arrays = pool.map( + parallel_helper, + [ + (self.__class__.__name__, parameters, x_chunk) + for x_chunk in x_chunks + ], + ) + if self.safe_inference_mode: + arr = np.ma.concatenate(arrays) + else: + arr = np.concatenate(arrays) + return arr + + +class FpsTransformer(BaseFpsTransformer): + """Classic fingerprint transformer using mol2fp pattern""" + + def __init__( + self, + parallel: Union[bool, int] = False, + safe_inference_mode: bool = False, + dtype: np.dtype = np.int8, + ): + super().__init__(parallel=parallel, safe_inference_mode=safe_inference_mode) + self.dtype = dtype + + def _transform_mol(self, mol): + """Implements the mol -> rdkit fingerprint data structure -> numpy array pattern""" + fp = self._mol2fp(mol) + return self._fp2array(fp) + + @abstractmethod + def _mol2fp(self, mol): + """Generate fingerprint from mol + + MUST BE OVERWRITTEN + """ + raise NotImplementedError("_mol2fp not implemented") + + def _fp2array(self, fp): + """Convert RDKit fingerprint data structure to numpy array""" + if fp: + arr = np.zeros((self.fpSize,), dtype=self.dtype) + DataStructs.ConvertToNumpyArray(fp, arr) + return arr + else: + return np.ma.masked_all((self.fpSize,), dtype=self.dtype) + + @check_transform_input + def _transform(self, X): + if self.safe_inference_mode: + arrays = [self._safe_transform_mol(mol) for mol in X] + return np.ma.stack(arrays) + else: + arr = np.zeros((len(X), self.fpSize), dtype=self.dtype) + for i, mol in enumerate(X): + arr[i, :] = self._transform_mol(mol) + return arr + + # TODO, remove when finally deprecating nBits + def _get_param_names(self): + """Get parameter names excluding deprecated parameters""" + params = super()._get_param_names() + # Remove deprecated parameters before they're accessed + return [p for p in params if p not in ("nBits")] + + +class FpsGeneratorTransformer(BaseFpsTransformer): + """Abstract base class for fingerprint transformers based on (unpicklable)fingerprint generators""" + + _regenerate_on_properties = () + + def __getstate__(self): + # Get the state of the parent class + state = super().__getstate__() + state.update(self.get_params()) + # Remove the potentiallyunpicklable property from the state + state.pop("_fpgen", None) # fpgen is not picklable + return state + + def __setstate__(self, state): + # Restore the state of the parent class + super().__setstate__(state) + # Re-create the unpicklable property + generatort_keys = inspect.signature( + self._generate_fp_generator + ).parameters.keys() + params = [ + setattr(self, k, state["_" + k]) + if "_" + k in state + else setattr(self, k, state[k]) + for k in generatort_keys + ] + self._generate_fp_generator() + + # TODO: overload set_params in order to not make multiple calls to _generate_fp_generator + + def __setattr__(self, name: str, value): + super().__setattr__(name, value) + if ( + not hasattr(self, "_initializing") + and name in self._regenerate_on_properties + ): + self._generate_fp_generator() + + @abstractmethod + def _generate_fp_generator(self): + raise NotImplementedError("_generate_fp_generator not implemented") + + @abstractmethod + def _transform_mol(self, mol) -> np.array: + """Generate numpy array descriptor from RDKit molecule + + MUST BE OVERWRITTEN + """ + raise NotImplementedError("_transform_mol not implemented") + + # TODO, remove when finally deprecating nBits and dtype + @property + def dtype(self): + warn( + "dtype is no longer supported, due to move to generator based fingerprints", + DeprecationWarning, + stacklevel=2, + ) + return None + + # TODO, remove when finally deprecating nBits and dtype + @dtype.setter + def dtype(self, dtype): + if dtype is not None: + warn( + "dtype is no longer supported, due to move to generator based fingerprints", + DeprecationWarning, + stacklevel=3, + ) + pass + + # TODO, remove when finally deprecating nBits and dtype + def _get_param_names(self): + """Get parameter names excluding deprecated parameters""" + params = super()._get_param_names() + # Remove deprecated parameters before they're accessed + return [p for p in params if p not in ("dtype", "nBits")] + + +def parallel_helper(args): + """Parallel_helper takes a tuple with classname, the objects parameters and the mols to process. + Then instantiates the class with the parameters and processes the mol. + Intention is to be able to do this in child processes as some classes can't be pickled""" + classname, parameters, X_mols = args + from scikit_mol import fingerprints + + transformer = getattr(fingerprints, classname)(**parameters) + return transformer._transform(X_mols) diff --git a/scikit_mol/fingerprints/maccs.py b/scikit_mol/fingerprints/maccs.py new file mode 100644 index 0000000..ca38966 --- /dev/null +++ b/scikit_mol/fingerprints/maccs.py @@ -0,0 +1,41 @@ +from typing import Union +from rdkit.Chem import rdMolDescriptors +import numpy as np + +from .baseclasses import FpsTransformer + + +class MACCSKeysFingerprintTransformer(FpsTransformer): + def __init__( + self, + parallel: Union[bool, int] = False, + safe_inference_mode: bool = False, + dtype: np.dtype = np.int8, + fpSize=167, + ): + """MACCS keys fingerprinter + calculates the 167 fixed MACCS keys + """ + super().__init__( + parallel=parallel, safe_inference_mode=safe_inference_mode, dtype=dtype + ) + if fpSize != 167: + raise ValueError( + "fpSize can only be 167, matching the number of defined MACCS keys!" + ) + self._fpSize = fpSize + + @property + def fpSize(self): + return self._fpSize + + @fpSize.setter + def fpSize(self, fpSize): + if fpSize != 167: + raise ValueError( + "fpSize can only be 167, matching the number of defined MACCS keys!" + ) + self._fpSize = fpSize + + def _mol2fp(self, mol): + return rdMolDescriptors.GetMACCSKeysFingerprint(mol) diff --git a/scikit_mol/fingerprints/minhash.py b/scikit_mol/fingerprints/minhash.py new file mode 100644 index 0000000..e487739 --- /dev/null +++ b/scikit_mol/fingerprints/minhash.py @@ -0,0 +1,210 @@ +from typing import Union + +import numpy as np + +from warnings import warn + +from .baseclasses import FpsTransformer + +from rdkit.Chem import rdMHFPFingerprint + + +# TODO move to use FpsGeneratorTransformer +class MHFingerprintTransformer(FpsTransformer): + def __init__( + self, + radius: int = 3, + rings: bool = True, + isomeric: bool = False, + kekulize: bool = False, + min_radius: int = 1, + fpSize: int = 2048, + seed: int = 42, + parallel: Union[bool, int] = False, + safe_inference_mode: bool = False, + dtype: np.dtype = np.int32, + ): + """Transforms the RDKit mol into the MinHash fingerprint (MHFP) + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-018-0321-8 + + Args: + radius (int, optional): The MHFP radius. Defaults to 3. + rings (bool, optional): Whether or not to include rings in the shingling. Defaults to True. + isomeric (bool, optional): Whether the isomeric SMILES to be considered. Defaults to False. + kekulize (bool, optional): Whether or not to kekulize the extracted SMILES. Defaults to False. + min_radius (int, optional): The minimum radius that is used to extract n-gram. Defaults to 1. + fpSize (int, optional): The number of permutations used for hashing. Defaults to 2048, + this is effectively the length of the FP + seed (int, optional): The value used to seed numpy.random. Defaults to 0. + """ + super().__init__( + parallel=parallel, safe_inference_mode=safe_inference_mode, dtype=dtype + ) + self.radius = radius + self.rings = rings + self.isomeric = isomeric + self.kekulize = kekulize + self.min_radius = min_radius + # Set the .n_permutations and .seed without creating the encoder twice + self.fpSize = fpSize + self._seed = seed + # create the encoder instance + self._recreate_encoder() + + def __getstate__(self): + # Get the state of the parent class + state = super().__getstate__() + # Remove the unpicklable property from the state + state.pop("mhfp_encoder", None) # mhfp_encoder is not picklable + return state + + def __setstate__(self, state): + # Restore the state of the parent class + super().__setstate__(state) + # Re-create the unpicklable property + self._recreate_encoder() + + def _mol2fp(self, mol): + fp = self.mhfp_encoder.EncodeMol( + mol, self.radius, self.rings, self.isomeric, self.kekulize, self.min_radius + ) + return fp + + def _fp2array(self, fp): + return np.array(fp) + + def _recreate_encoder(self): + self.mhfp_encoder = rdMHFPFingerprint.MHFPEncoder( + int(self.fpSize), int(self._seed) + ) + + @property + def seed(self): + return self._seed + + @seed.setter + def seed(self, seed): + self._seed = seed + # each time the seed parameter is modified refresh an instance of the encoder + self._recreate_encoder() + + @property + def n_permutations(self): + warn( + "n_permutations will be replace by fpSize, due to changes harmonization!", + DeprecationWarning, + ) + return self.fpSize + + @n_permutations.setter + def n_permutations(self, n_permutations): + warn( + "n_permutations will be replace by fpSize, due to changes harmonization!", + DeprecationWarning, + ) + self.fpSize = n_permutations + # each time the n_permutations parameter is modified refresh an instance of the encoder + self._recreate_encoder() + + +# TODO use FpsGeneratorTransformer instead +class SECFingerprintTransformer(FpsTransformer): + # https://jcheminf.biomedcentral.com/articles/10.1186/s13321-018-0321-8 + def __init__( + self, + radius: int = 3, + rings: bool = True, + isomeric: bool = False, + kekulize: bool = False, + min_radius: int = 1, + fpSize: int = 2048, + n_permutations: int = 0, + seed: int = 0, + parallel: Union[bool, int] = False, + safe_inference_mode: bool = False, + dtype: np.dtype = np.int8, + ): + """Transforms the RDKit mol into the SMILES extended connectivity fingerprint (SECFP) + + Args: + radius (int, optional): The MHFP radius. Defaults to 3. + rings (bool, optional): Whether or not to include rings in the shingling. Defaults to True. + isomeric (bool, optional): Whether the isomeric SMILES to be considered. Defaults to False. + kekulize (bool, optional): Whether or not to kekulize the extracted SMILES. Defaults to False. + min_radius (int, optional): The minimum radius that is used to extract n-gram. Defaults to 1. + fpSize (int, optional): The length of the folded fingerprint. Defaults to 2048. + n_permutations (int, optional): The number of permutations used for hashing. Defaults to 0. + seed (int, optional): The value used to seed numpy.random. Defaults to 0. + """ + super().__init__( + parallel=parallel, safe_inference_mode=safe_inference_mode, dtype=dtype + ) + self.radius = radius + self.rings = rings + self.isomeric = isomeric + self.kekulize = kekulize + self.min_radius = min_radius + self.fpSize = fpSize + # Set the .n_permutations and seed without creating the encoder twice + self._n_permutations = n_permutations + self._seed = seed + # create the encoder instance + self._recreate_encoder() + + def __getstate__(self): + # Get the state of the parent class + state = super().__getstate__() + # Remove the unpicklable property from the state + state.pop("mhfp_encoder", None) # mhfp_encoder is not picklable + return state + + def __setstate__(self, state): + # Restore the state of the parent class + super().__setstate__(state) + # Re-create the unpicklable property + self._recreate_encoder() + + def _mol2fp(self, mol): + return self.mhfp_encoder.EncodeSECFPMol( + mol, + int(self.radius), + bool(self.rings), + bool(self.isomeric), + bool(self.kekulize), + int(self.min_radius), + int(self.fpSize), + ) + + def _recreate_encoder(self): + self.mhfp_encoder = rdMHFPFingerprint.MHFPEncoder( + self._n_permutations, self._seed + ) + + @property + def seed(self): + return self._seed + + @seed.setter + def seed(self, seed): + self._seed = seed + # each time the seed parameter is modified refresh an instace of the encoder + self._recreate_encoder() + + @property + def n_permutations(self): + return self._n_permutations + + @n_permutations.setter + def n_permutations(self, n_permutations): + self._n_permutations = n_permutations + # each time the n_permutations parameter is modified refresh an instace of the encoder + self._recreate_encoder() + + @property + def length(self): + warn( + "length will be replace by fpSize, due to changes harmonization!", + DeprecationWarning, + ) + return self.fpSize diff --git a/scikit_mol/fingerprints/morgan.py b/scikit_mol/fingerprints/morgan.py new file mode 100644 index 0000000..f2b1edf --- /dev/null +++ b/scikit_mol/fingerprints/morgan.py @@ -0,0 +1,93 @@ +from typing import Union + +from rdkit.Chem import rdMolDescriptors + +import numpy as np + +from warnings import warn + +from rdkit.Chem.rdFingerprintGenerator import ( + GetMorganGenerator, + GetMorganFeatureAtomInvGen, +) + +from .baseclasses import FpsTransformer, FpsGeneratorTransformer + + +class MorganFingerprintTransformer(FpsGeneratorTransformer): + _regenerate_on_properties = ( + "radius", + "fpSize", + "useChirality", + "useFeatures", + "useBondTypes", + ) + + def __init__( + self, + fpSize=2048, + radius=2, + useChirality=False, + useBondTypes=True, + useFeatures=False, + useCounts=False, + parallel: Union[bool, int] = False, + safe_inference_mode: bool = False, + dtype: np.dtype = None, + nBits: int = None, + ): + """Transform RDKit mols into Count or bit-based hashed MorganFingerprints + + Parameters + ---------- + fpsize : int, optional + Size of the hashed fingerprint, by default 2048 + radius : int, optional + Radius of the fingerprint, by default 2 + useChirality : bool, optional + Include chirality in calculation of the fingerprint keys, by default False + useBondTypes : bool, optional + Include bondtypes in calculation of the fingerprint keys, by default True + useFeatures : bool, optional + use chemical features, rather than atom-type in calculation of the fingerprint keys, by default False + useCounts : bool, optional + If toggled will create the count and not bit-based fingerprint, by default False + parallel : bool or int, optional + If True, will use all available cores, if int will use that many cores, by default False + safe_inference_mode : bool, optional + If True, will return masked arrays for invalid mols, by default False + """ + + self._initializing = True + super().__init__(parallel=parallel, safe_inference_mode=safe_inference_mode) + self.fpSize = fpSize + self.radius = radius + self.useChirality = useChirality + self.useFeatures = useFeatures + self.useCounts = useCounts + self.useBondTypes = useBondTypes + self.dtype = dtype + self.nBits = nBits + + self._generate_fp_generator() + delattr(self, "_initializing") + + def _generate_fp_generator(self): + if self.useFeatures: + atomInvariantsGenerator = GetMorganFeatureAtomInvGen() + else: + atomInvariantsGenerator = None + + self._fpgen = GetMorganGenerator( + radius=int(self.radius), + fpSize=int(self.fpSize), + includeChirality=bool(self.useChirality), + useBondTypes=bool(self.useBondTypes), + atomInvariantsGenerator=atomInvariantsGenerator, + ) + + def _transform_mol(self, mol) -> np.array: + if self.useCounts: + return self._fpgen.GetCountFingerprintAsNumPy(mol) + else: + return self._fpgen.GetFingerprintAsNumPy(mol) diff --git a/scikit_mol/fingerprints/rdkitfp.py b/scikit_mol/fingerprints/rdkitfp.py new file mode 100644 index 0000000..19a8d2e --- /dev/null +++ b/scikit_mol/fingerprints/rdkitfp.py @@ -0,0 +1,99 @@ +from typing import Union + +import numpy as np + +from warnings import warn + +from .baseclasses import FpsTransformer, FpsGeneratorTransformer + +from rdkit.Chem.rdFingerprintGenerator import GetRDKitFPGenerator + +from rdkit.Chem import rdFingerprintGenerator + + +class RDKitFingerprintTransformer(FpsGeneratorTransformer): + _regenerate_on_properties = ( + "minPath", + "maxPath", + "useHs", + "branchedPaths", + "useBondOrder", + "countSimulation", + "fpSize", + "countBounds", + "numBitsPerFeature", + ) + + def __init__( + self, + minPath: int = 1, + maxPath: int = 7, + useHs: bool = True, + branchedPaths: bool = True, + useBondOrder: bool = True, + countSimulation: bool = False, + countBounds=None, + fpSize: int = 2048, + numBitsPerFeature: int = 2, + useCounts: bool = False, + parallel: Union[bool, int] = False, + safe_inference_mode: bool = False, + ): + """Calculates the RDKit fingerprints + + Parameters + ---------- + minPath : int, optional + the minimum path length (in bonds) to be included, by default 1 + maxPath : int, optional + the maximum path length (in bonds) to be included, by default 7 + useHs : bool, optional + toggles inclusion of Hs in paths (if the molecule has explicit Hs), by default True + branchedPaths : bool, optional + toggles generation of branched subgraphs, not just linear paths, by default True + useBondOrder : bool, optional + toggles inclusion of bond orders in the path hashes, by default True + countSimulation : bool, optional + if set, use count simulation while generating the fingerprint, by default False + countBounds : _type_, optional + boundaries for count simulation, corresponding bit will be set if the count is higher than the number provided for that spot, by default None + fpSize : int, optional + size of the generated fingerprint, does not affect the sparse versions, by default 2048 + numBitsPerFeature : int, optional + the number of bits set per path/subgraph found, by default 2 + """ + self._initializing = True + super().__init__(parallel=parallel, safe_inference_mode=safe_inference_mode) + self.minPath = minPath + self.maxPath = maxPath + self.useHs = useHs + self.branchedPaths = branchedPaths + self.useBondOrder = useBondOrder + self.countSimulation = countSimulation + self.fpSize = fpSize + self.numBitsPerFeature = numBitsPerFeature + self.countBounds = countBounds + + self.useCounts = useCounts + + self._generate_fp_generator() + delattr(self, "_initializing") + + def _transform_mol(self, mol) -> np.array: + if self.useCounts: + return self._fpgen.GetCountFingerprintAsNumPy(mol) + else: + return self._fpgen.GetFingerprintAsNumPy(mol) + + def _generate_fp_generator(self): + self._fpgen = GetRDKitFPGenerator( + minPath=int(self.minPath), + maxPath=int(self.maxPath), + useHs=bool(self.useHs), + branchedPaths=bool(self.branchedPaths), + useBondOrder=bool(self.useBondOrder), + countSimulation=bool(self.countSimulation), + fpSize=int(self.fpSize), + countBounds=bool(self.countBounds), + numBitsPerFeature=int(self.numBitsPerFeature), + ) diff --git a/scikit_mol/fingerprints/topologicaltorsion.py b/scikit_mol/fingerprints/topologicaltorsion.py new file mode 100644 index 0000000..0cd5d9e --- /dev/null +++ b/scikit_mol/fingerprints/topologicaltorsion.py @@ -0,0 +1,65 @@ +from typing import Union + +import numpy as np + +from warnings import warn + +from .baseclasses import FpsTransformer, FpsGeneratorTransformer + +from rdkit.Chem import rdMolDescriptors +from rdkit.Chem.rdFingerprintGenerator import GetTopologicalTorsionGenerator + + +class TopologicalTorsionFingerprintTransformer(FpsGeneratorTransformer): + _regenerate_on_properties = ("fpSize", "includeChirality", "targetSize") + + def __init__( + self, + targetSize: int = 4, + fromAtoms=None, + ignoreAtoms=None, + atomInvariants=None, + confId=-1, + includeChirality: bool = False, + fpSize: int = 2048, + useCounts: bool = False, + parallel: Union[bool, int] = False, + safe_inference_mode: bool = False, + ): + self._initializing = True + super().__init__(parallel=parallel, safe_inference_mode=safe_inference_mode) + self.fpSize = fpSize + self.includeChirality = includeChirality + self.targetSize = targetSize + + self.fromAtoms = fromAtoms + self.ignoreAtoms = ignoreAtoms + self.atomInvariants = atomInvariants + self.confId = confId + self.useCounts = useCounts + + self._generate_fp_generator() + delattr(self, "_initializing") + + def _generate_fp_generator(self): + self._fpgen = GetTopologicalTorsionGenerator( + torsionAtomCount=int(self.targetSize), + includeChirality=bool(self.includeChirality), + fpSize=int(self.fpSize), + ) + + def _transform_mol(self, mol) -> np.array: + if self.useCounts: + return self._fpgen.GetCountFingerprintAsNumPy( + mol, + fromAtoms=self.fromAtoms, + ignoreAtoms=self.ignoreAtoms, + customAtomInvariants=self.atomInvariants, + ) + else: + return self._fpgen.GetFingerprintAsNumPy( + mol, + fromAtoms=self.fromAtoms, + ignoreAtoms=self.ignoreAtoms, + customAtomInvariants=self.atomInvariants, + ) diff --git a/tests/fixtures.py b/tests/fixtures.py index 2b5a2e6..1434307 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -197,3 +197,23 @@ def combined_transformer(featurizer): remainder="drop", ) return transformer + + +@pytest.fixture +def morgan_transformer(): + return MorganFingerprintTransformer() + + +@pytest.fixture +def rdkit_transformer(): + return RDKitFingerprintTransformer() + + +@pytest.fixture +def atompair_transformer(): + return AtomPairFingerprintTransformer() + + +@pytest.fixture +def topologicaltorsion_transformer(): + return TopologicalTorsionFingerprintTransformer() diff --git a/tests/test_fptransformers.py b/tests/test_fptransformers.py index 9a9c27a..aa3ae3d 100644 --- a/tests/test_fptransformers.py +++ b/tests/test_fptransformers.py @@ -18,37 +18,13 @@ from sklearn import clone from scikit_mol.fingerprints import ( - MorganFingerprintTransformer, MACCSKeysFingerprintTransformer, - RDKitFingerprintTransformer, - AtomPairFingerprintTransformer, - TopologicalTorsionFingerprintTransformer, SECFingerprintTransformer, MHFingerprintTransformer, AvalonFingerprintTransformer, ) -@pytest.fixture -def morgan_transformer(): - return MorganFingerprintTransformer() - - -@pytest.fixture -def rdkit_transformer(): - return RDKitFingerprintTransformer() - - -@pytest.fixture -def atompair_transformer(): - return AtomPairFingerprintTransformer() - - -@pytest.fixture -def topologicaltorsion_transformer(): - return TopologicalTorsionFingerprintTransformer() - - @pytest.fixture def maccs_transformer(): return MACCSKeysFingerprintTransformer() @@ -69,38 +45,14 @@ def avalon_transformer(): return AvalonFingerprintTransformer() -def test_fpstransformer_fp2array(morgan_transformer, fingerprint): - fp = morgan_transformer._fp2array(fingerprint) - # See that fp is the correct type, shape and bit count - assert type(fp) == type(np.array([0])) - assert fp.shape == (1000,) - assert fp.sum() == 25 - - -def test_fpstransformer_transform_mol(morgan_transformer, mols_list): - fp = morgan_transformer._transform_mol(mols_list[0]) - # See that fp is the correct type, shape and bit count - assert type(fp) == type(np.array([0])) - assert fp.shape == (2048,) - assert fp.sum() == 14 - - def test_clonability( maccs_transformer, - morgan_transformer, - rdkit_transformer, - atompair_transformer, - topologicaltorsion_transformer, secfp_transformer, mhfp_transformer, avalon_transformer, ): for t in [ maccs_transformer, - morgan_transformer, - rdkit_transformer, - atompair_transformer, - topologicaltorsion_transformer, secfp_transformer, mhfp_transformer, avalon_transformer, @@ -115,57 +67,30 @@ def test_clonability( def test_set_params( - morgan_transformer, - rdkit_transformer, - atompair_transformer, - topologicaltorsion_transformer, secfp_transformer, mhfp_transformer, avalon_transformer, ): - for t in [ - morgan_transformer, - atompair_transformer, - topologicaltorsion_transformer, - avalon_transformer, - ]: + for t in [avalon_transformer]: params = t.get_params() # change extracted dictionary - params["nBits"] = 4242 + params["fpSize"] = 4242 # change params in transformer - t.set_params(nBits=4242) + t.set_params(fpSize=4242) # get parameters as dictionary and assert that it is the same params_2 = t.get_params() assert all([params[key] == params_2[key] for key in params.keys()]) - for t in [rdkit_transformer]: + for t in [secfp_transformer, mhfp_transformer]: params = t.get_params() params["fpSize"] = 4242 t.set_params(fpSize=4242) params_2 = t.get_params() assert all([params[key] == params_2[key] for key in params.keys()]) - for t in [secfp_transformer]: - params = t.get_params() - params["length"] = 4242 - t.set_params(length=4242) - params_2 = t.get_params() - assert all([params[key] == params_2[key] for key in params.keys()]) - - for t in [mhfp_transformer]: - params = t.get_params() - params["n_permutations"] = 4242 - t.set_params(n_permutations=4242) - params_2 = t.get_params() - assert all([params[key] == params_2[key] for key in params.keys()]) - def test_transform( mols_container, - morgan_transformer, - rdkit_transformer, - atompair_transformer, - topologicaltorsion_transformer, maccs_transformer, secfp_transformer, mhfp_transformer, @@ -173,41 +98,25 @@ def test_transform( ): # Test the different transformers for t in [ - morgan_transformer, - atompair_transformer, - topologicaltorsion_transformer, maccs_transformer, - rdkit_transformer, secfp_transformer, mhfp_transformer, avalon_transformer, ]: params = t.get_params() + print(type(t), params) fps = t.transform(mols_container) # Assert that the same length of input and output assert len(fps) == len(mols_container) # assert that the size of the fingerprint is the expected size - if ( - type(t) == type(maccs_transformer) - or type(t) == type(secfp_transformer) - or type(t) == type(mhfp_transformer) - ): - fpsize = t.nBits - elif type(t) == type(rdkit_transformer): - fpsize = params["fpSize"] - else: - fpsize = params["nBits"] + fpsize = params["fpSize"] assert len(fps[0]) == fpsize def test_transform_parallel( mols_container, - morgan_transformer, - rdkit_transformer, - atompair_transformer, - topologicaltorsion_transformer, maccs_transformer, secfp_transformer, mhfp_transformer, @@ -215,11 +124,7 @@ def test_transform_parallel( ): # Test the different transformers for t in [ - morgan_transformer, - atompair_transformer, - topologicaltorsion_transformer, maccs_transformer, - rdkit_transformer, secfp_transformer, mhfp_transformer, avalon_transformer, @@ -231,36 +136,19 @@ def test_transform_parallel( assert len(fps) == len(mols_container) # assert that the size of the fingerprint is the expected size - if ( - type(t) == type(maccs_transformer) - or type(t) == type(secfp_transformer) - or type(t) == type(mhfp_transformer) - ): - fpsize = t.nBits - elif type(t) == type(rdkit_transformer): - fpsize = params["fpSize"] - else: - fpsize = params["nBits"] + fpsize = params["fpSize"] assert len(fps[0]) == fpsize def test_picklable( - morgan_transformer, - rdkit_transformer, - atompair_transformer, - topologicaltorsion_transformer, maccs_transformer, secfp_transformer, avalon_transformer, ): # Test the different transformers for t in [ - morgan_transformer, - atompair_transformer, - topologicaltorsion_transformer, maccs_transformer, - rdkit_transformer, secfp_transformer, avalon_transformer, ]: @@ -304,79 +192,11 @@ def assert_transformer_set_params(tr_class, new_params, mols_list): ), f"Assertation error, FP appears to be different, although the {key} should be changed back as well as initialized to {params[key]}" -def test_morgan_set_params(chiral_mols_list): - new_params = { - "nBits": 1024, - "radius": 1, - "useBondTypes": False, # TODO, why doesn't this change the FP? - "useChirality": True, - "useCounts": True, - "useFeatures": True, - } - - assert_transformer_set_params( - MorganFingerprintTransformer, new_params, chiral_mols_list - ) - - -def test_atompairs_set_params(chiral_mols_list): - new_params = { - #'atomInvariants': 1, - #'confId': -1, - #'fromAtoms': 1, - #'ignoreAtoms': 0, - "includeChirality": True, - "maxLength": 3, - "minLength": 3, - "nBits": 1024, - "nBitsPerEntry": 3, - #'use2D': True, #TODO, understand why this can't be set different - "useCounts": True, - } - - assert_transformer_set_params( - AtomPairFingerprintTransformer, new_params, chiral_mols_list - ) - - -def test_topologicaltorsion_set_params(chiral_mols_list): - new_params = { #'atomInvariants': 0, - #'fromAtoms': 0, - #'ignoreAtoms': 0, - #'includeChirality': True, #TODO, figure out why this setting seems to give same FP wheter toggled or not - "nBits": 1024, - "nBitsPerEntry": 3, - "targetSize": 5, - "useCounts": True, - } - - assert_transformer_set_params( - TopologicalTorsionFingerprintTransformer, new_params, chiral_mols_list - ) - - -def test_RDKitFPTransformer(chiral_mols_list): - new_params = { #'atomInvariantsGenerator': None, - #'branchedPaths': False, - #'countBounds': 0, #TODO: What does this do? - "countSimulation": True, - "fpSize": 1024, - "maxPath": 3, - "minPath": 2, - "numBitsPerFeature": 3, - "useBondOrder": False, # TODO, why doesn't this change the FP? - #'useHs': False, #TODO, why doesn't this change the FP? - } - assert_transformer_set_params( - RDKitFingerprintTransformer, new_params, chiral_mols_list - ) - - def test_SECFingerprintTransformer(chiral_mols_list): new_params = { "isomeric": True, "kekulize": True, - "length": 1048, + "fpSize": 1048, "min_radius": 2, #'n_permutations': 2, # The SECFp is not using this setting "radius": 2, @@ -395,7 +215,7 @@ def test_MHFingerprintTransformer(chiral_mols_list): "isomeric": True, "kekulize": True, "min_radius": 2, - "n_permutations": 4096, + "fpSize": 4096, "seed": 44, } assert_transformer_set_params( @@ -405,7 +225,7 @@ def test_MHFingerprintTransformer(chiral_mols_list): def test_AvalonFingerprintTransformer(chiral_mols_list): new_params = { - "nBits": 1024, + "fpSize": 1024, "isQuery": True, # 'resetVect': True, #TODO: this doesn't change the FP "bitFlags": 32767, @@ -417,20 +237,12 @@ def test_AvalonFingerprintTransformer(chiral_mols_list): def test_transform_with_safe_inference_mode( mols_with_invalid_container, - morgan_transformer, - rdkit_transformer, - atompair_transformer, - topologicaltorsion_transformer, maccs_transformer, secfp_transformer, avalon_transformer, ): for t in [ - morgan_transformer, - atompair_transformer, - topologicaltorsion_transformer, maccs_transformer, - rdkit_transformer, secfp_transformer, avalon_transformer, ]: @@ -449,21 +261,13 @@ def test_transform_with_safe_inference_mode( def test_transform_without_safe_inference_mode( mols_with_invalid_container, - morgan_transformer, - rdkit_transformer, - atompair_transformer, - topologicaltorsion_transformer, maccs_transformer, secfp_transformer, avalon_transformer, # MHFP seem to accept invalid mols and return 0,0,0,0's ): for t in [ - morgan_transformer, - atompair_transformer, - topologicaltorsion_transformer, maccs_transformer, - rdkit_transformer, secfp_transformer, avalon_transformer, ]: @@ -478,20 +282,12 @@ def test_transform_without_safe_inference_mode( # Add this test to check parallel processing with error handling def test_transform_parallel_with_safe_inference_mode( mols_with_invalid_container, - morgan_transformer, - rdkit_transformer, - atompair_transformer, - topologicaltorsion_transformer, maccs_transformer, secfp_transformer, avalon_transformer, ): for t in [ - morgan_transformer, - atompair_transformer, - topologicaltorsion_transformer, maccs_transformer, - rdkit_transformer, secfp_transformer, avalon_transformer, ]: diff --git a/tests/test_fptransformersgenerator.py b/tests/test_fptransformersgenerator.py new file mode 100644 index 0000000..aa7a426 --- /dev/null +++ b/tests/test_fptransformersgenerator.py @@ -0,0 +1,222 @@ +import pickle +import tempfile +import pytest +import numpy as np +from fixtures import ( + mols_list, + smiles_list, + mols_container, + smiles_container, + fingerprint, + chiral_smiles_list, + chiral_mols_list, +) +from sklearn import clone + +from scikit_mol.fingerprints import ( + AtomPairFingerprintTransformer, + MorganFingerprintTransformer, + RDKitFingerprintTransformer, + TopologicalTorsionFingerprintTransformer, +) + +test_transformers = [ + AtomPairFingerprintTransformer, + MorganFingerprintTransformer, + RDKitFingerprintTransformer, + TopologicalTorsionFingerprintTransformer, +] + + +@pytest.mark.parametrize("transformer_class", test_transformers) +def test_fpstransformer_transform_mol(transformer_class, mols_list): + transformer = transformer_class() + + fp = transformer._transform_mol(mols_list[0]) + # See that fp is the correct type, shape and bit count + assert type(fp) == type(np.array([0])) + assert fp.shape == (2048,) + + if isinstance(transformer, RDKitFingerprintTransformer): + assert fp.sum() == 104 + elif isinstance(transformer, AtomPairFingerprintTransformer): + assert fp.sum() == 32 + elif isinstance(transformer, TopologicalTorsionFingerprintTransformer): + assert fp.sum() == 12 + elif isinstance(transformer, MorganFingerprintTransformer): + assert fp.sum() == 14 + else: + raise NotImplementedError(f"missing Assert for {transformer_class}") + + +@pytest.mark.parametrize("transformer_class", test_transformers) +def test_clonability(transformer_class): + transformer = transformer_class() + + params = transformer.get_params() + t2 = clone(transformer) + params_2 = t2.get_params() + # Parameters of cloned transformers should be the same + assert all([params[key] == params_2[key] for key in params.keys()]) + # Cloned transformers should not be the same object + assert t2 != transformer + + +@pytest.mark.parametrize("transformer_class", test_transformers) +def test_set_params(transformer_class): + transformer = transformer_class() + params = transformer.get_params() + # change extracted dictionary + params["fpSize"] = 4242 + # change params in transformer + transformer.set_params(fpSize=4242) + # get parameters as dictionary and assert that it is the same + params_2 = transformer.get_params() + assert all([params[key] == params_2[key] for key in params.keys()]) + + +@pytest.mark.parametrize("transformer_class", test_transformers) +def test_transform(mols_container, transformer_class): + transformer = transformer_class() + # Test the different transformers + params = transformer.get_params() + fps = transformer.transform(mols_container) + # Assert that the same length of input and output + assert len(fps) == len(mols_container) + + fpsize = params["fpSize"] + + assert len(fps[0]) == fpsize + + +@pytest.mark.parametrize("transformer_class", test_transformers) +def test_transform_parallel(mols_container, transformer_class): + transformer = transformer_class() + # Test the different transformers + transformer.set_params(parallel=True) + params = transformer.get_params() + fps = transformer.transform(mols_container) + # Assert that the same length of input and output + assert len(fps) == len(mols_container) + + fpsize = params["fpSize"] + assert len(fps[0]) == fpsize + + +@pytest.mark.parametrize("transformer_class", test_transformers) +def test_picklable(transformer_class): + # Test the different transformers + transformer = transformer_class() + p = transformer.get_params() + + with tempfile.NamedTemporaryFile() as f: + pickle.dump(transformer, f) + f.seek(0) + t2 = pickle.load(f) + print(p) + print(vars(transformer)) + print(vars(t2)) + assert transformer.get_params() == t2.get_params() + + +@pytest.mark.parametrize("transfomer", test_transformers) +def assert_transformer_set_params(transfomer, new_params, mols_list): + default_params = transfomer().get_params() + + for key in new_params.keys(): + tr = transfomer() + params = tr.get_params() + params[key] = new_params[key] + + fps_default = tr.transform(mols_list) + + tr.set_params(**params) + new_tr = transfomer(**params) + fps_reset_params = tr.transform(mols_list) + fps_init_new_params = new_tr.transform(mols_list) + + # Now fp_default should not be the same as fp_reset_params + + assert ~np.all( + [ + np.array_equal(fp_default, fp_reset_params) + for fp_default, fp_reset_params in zip(fps_default, fps_reset_params) + ] + ), f"Assertation error, FP appears the same, although the {key} should be changed from {default_params[key]} to {params[key]}" + # fp_reset_params and fp_init_new_params should however be the same + assert np.all( + [ + np.array_equal(fp_init_new_params, fp_reset_params) + for fp_init_new_params, fp_reset_params in zip( + fps_init_new_params, fps_reset_params + ) + ] + ), f"Assertation error, FP appears to be different, although the {key} should be changed back as well as initialized to {params[key]}" + + +def test_morgan_set_params(chiral_mols_list): + new_params = { + "fpSize": 1024, + "radius": 1, + "useBondTypes": False, # TODO, why doesn't this change the FP? + "useChirality": True, + "useCounts": True, + "useFeatures": True, + } + + assert_transformer_set_params( + MorganFingerprintTransformer, new_params, chiral_mols_list + ) + + +def test_atompairs_set_params(chiral_mols_list): + new_params = { + #'atomInvariants': 1, + #'confId': -1, + #'fromAtoms': 1, + #'ignoreAtoms': 0, + "includeChirality": True, + "maxLength": 3, + "minLength": 3, + "fpSize": 1024, + #'nBitsPerEntry': 3, #TODO: seem deprecated with the generators? + #'use2D': True, #TODO, understand why this can't be set different + "useCounts": True, + } + + assert_transformer_set_params( + AtomPairFingerprintTransformer, new_params, chiral_mols_list + ) + + +def test_topologicaltorsion_set_params(chiral_mols_list): + new_params = { #'atomInvariants': 0, + #'fromAtoms': 0, + #'ignoreAtoms': 0, + #'includeChirality': True, #TODO, figure out why this setting seems to give same FP wheter toggled or not + "fpSize": 1024, + #'nBitsPerEntry': 3, #Todo: not setable with the generators? + "targetSize": 5, + "useCounts": True, + } + + assert_transformer_set_params( + TopologicalTorsionFingerprintTransformer, new_params, chiral_mols_list + ) + + +def test_RDKitFPTransformer(chiral_mols_list): + new_params = { #'atomInvariantsGenerator': None, + #'branchedPaths': False, + #'countBounds': 0, #TODO: What does this do? + "countSimulation": True, + "fpSize": 1024, + "maxPath": 3, + "minPath": 2, + "numBitsPerFeature": 3, + "useBondOrder": False, # TODO, why doesn't this change the FP? + #'useHs': False, #TODO, why doesn't this change the FP? + } + assert_transformer_set_params( + RDKitFingerprintTransformer, new_params, chiral_mols_list + ) diff --git a/tests/test_parameter_types.py b/tests/test_parameter_types.py index f175c87..4b73959 100644 --- a/tests/test_parameter_types.py +++ b/tests/test_parameter_types.py @@ -1,46 +1,64 @@ import pytest import numpy as np from rdkit import Chem -from fixtures import mols_list, smiles_list -from test_fptransformers import morgan_transformer, atompair_transformer, topologicaltorsion_transformer, rdkit_transformer, avalon_transformer +from fixtures import ( + mols_list, + smiles_list, + morgan_transformer, + atompair_transformer, + topologicaltorsion_transformer, + rdkit_transformer, +) +from test_fptransformers import ( + avalon_transformer, +) -def test_Transformer_exotic_types(mols_list, morgan_transformer,atompair_transformer, topologicaltorsion_transformer, avalon_transformer): - for transformer in [morgan_transformer, atompair_transformer, topologicaltorsion_transformer, avalon_transformer]: +def test_Transformer_exotic_types( + mols_list, + morgan_transformer, + atompair_transformer, + topologicaltorsion_transformer, + avalon_transformer, +): + for transformer in [ + morgan_transformer, + atompair_transformer, + topologicaltorsion_transformer, + avalon_transformer, + ]: params = transformer.get_params() for useCounts in [np.bool_(True), np.bool_(False)]: - for key, value in params.items(): if isinstance(value, int): exotic_type_value = np.int64(value) elif isinstance(value, bool): exotic_type_value = np.bool_(value) else: - print(f'{key}:{value}:{type(value)}') + print(f"{key}:{value}:{type(value)}") exotic_type_value = value - exotic_params = {key:exotic_type_value, 'useCounts':useCounts} - print(exotic_params) + exotic_params = {key: exotic_type_value, "useCounts": useCounts} + print(exotic_params) transformer.set_params(**exotic_params) transformer.transform(mols_list) def test_RDKFp_exotic_types(mols_list, rdkit_transformer): - transformer = rdkit_transformer - params = transformer.get_params() - - for key, value in params.items(): - if isinstance(value, int): - exotic_type_value = np.int64(value) - elif isinstance(value, bool): - exotic_type_value = np.bool_(value) - else: - print(f'{key}:{value}:{type(value)}') - exotic_type_value = value + transformer = rdkit_transformer + params = transformer.get_params() - exotic_params = {key:exotic_type_value} - print(exotic_params) - transformer.set_params(**exotic_params) - transformer.transform(mols_list) + for key, value in params.items(): + if isinstance(value, int): + exotic_type_value = np.int64(value) + elif isinstance(value, bool): + exotic_type_value = np.bool_(value) + else: + print(f"{key}:{value}:{type(value)}") + exotic_type_value = value + exotic_params = {key: exotic_type_value} + print(exotic_params) + transformer.set_params(**exotic_params) + transformer.transform(mols_list) diff --git a/tests/test_safeinferencemode.py b/tests/test_safeinferencemode.py index 921cc0f..c9b4ca1 100644 --- a/tests/test_safeinferencemode.py +++ b/tests/test_safeinferencemode.py @@ -104,12 +104,12 @@ def test_safeinference_wrapper_pandas_output( result = smiles_pipeline[:-1].fit_transform(X_smiles) assert isinstance(result, pd.DataFrame) assert result.shape[0] == len(X_smiles) - assert result.shape[1] == smiles_pipeline.named_steps["FP"].nBits + assert result.shape[1] == smiles_pipeline.named_steps["FP"].fpSize @skip_pandas_output_test def test_safeinference_wrapper_get_feature_names_out(smiles_pipeline): # Get feature names from the FP step feature_names = smiles_pipeline.named_steps["FP"].get_feature_names_out() - assert len(feature_names) == smiles_pipeline.named_steps["FP"].nBits + assert len(feature_names) == smiles_pipeline.named_steps["FP"].fpSize assert all(isinstance(name, str) for name in feature_names) diff --git a/tests/test_transformers.py b/tests/test_transformers.py index 143ecd3..a47b8bf 100644 --- a/tests/test_transformers.py +++ b/tests/test_transformers.py @@ -15,12 +15,29 @@ from sklearn.ensemble import RandomForestRegressor from scikit_mol.conversions import SmilesToMolTransformer from scikit_mol.core import SKLEARN_VERSION_PANDAS_OUT -from scikit_mol.fingerprints import FpsTransformer, MACCSKeysFingerprintTransformer, RDKitFingerprintTransformer, AtomPairFingerprintTransformer, \ - TopologicalTorsionFingerprintTransformer, MorganFingerprintTransformer, SECFingerprintTransformer, \ - MHFingerprintTransformer, AvalonFingerprintTransformer +from scikit_mol.fingerprints import ( + MACCSKeysFingerprintTransformer, + RDKitFingerprintTransformer, + AtomPairFingerprintTransformer, + TopologicalTorsionFingerprintTransformer, + MorganFingerprintTransformer, + SECFingerprintTransformer, + MHFingerprintTransformer, + AvalonFingerprintTransformer, +) +from scikit_mol.fingerprints.baseclasses import BaseFpsTransformer + from scikit_mol.descriptors import MolecularDescriptorTransformer -from fixtures import SLC6A4_subset, SLC6A4_subset_with_cddd, skip_pandas_output_test, mols_container, featurizer, combined_transformer +from fixtures import ( + SLC6A4_subset, + SLC6A4_subset_with_cddd, + skip_pandas_output_test, + mols_container, + featurizer, + combined_transformer, +) + def test_transformer(SLC6A4_subset): # load some toy data for quick testing on a small number of samples @@ -30,33 +47,62 @@ def test_transformer(SLC6A4_subset): Y_train, Y_test = Y[:128], Y[128:] # run FP with default parameters except when useCounts can be given as an argument - FP_dict = {"MACCSTransformer": [MACCSKeysFingerprintTransformer, None], - "RDKitFPTransformer": [RDKitFingerprintTransformer, None], - "AtomPairFingerprintTransformer": [AtomPairFingerprintTransformer, False], - "AtomPairFingerprintTransformer useCounts": [AtomPairFingerprintTransformer, True], - "TopologicalTorsionFingerprintTransformer": [TopologicalTorsionFingerprintTransformer, False], - "TopologicalTorsionFingerprintTransformer useCounts": [TopologicalTorsionFingerprintTransformer, True], - "MorganTransformer": [MorganFingerprintTransformer, False], - "MorganTransformer useCounts": [MorganFingerprintTransformer, True], - "SECFingerprintTransformer": [SECFingerprintTransformer, None], - "MHFingerprintTransformer": [MHFingerprintTransformer, None], - 'AvalonFingerprintTransformer': [AvalonFingerprintTransformer, None]} + FP_dict = { + "MACCSTransformer": [MACCSKeysFingerprintTransformer, None], + "RDKitFPTransformer": [RDKitFingerprintTransformer, None], + "AtomPairFingerprintTransformer": [AtomPairFingerprintTransformer, False], + "AtomPairFingerprintTransformer useCounts": [ + AtomPairFingerprintTransformer, + True, + ], + "TopologicalTorsionFingerprintTransformer": [ + TopologicalTorsionFingerprintTransformer, + False, + ], + "TopologicalTorsionFingerprintTransformer useCounts": [ + TopologicalTorsionFingerprintTransformer, + True, + ], + "MorganTransformer": [MorganFingerprintTransformer, False], + "MorganTransformer useCounts": [MorganFingerprintTransformer, True], + "SECFingerprintTransformer": [SECFingerprintTransformer, None], + "MHFingerprintTransformer": [MHFingerprintTransformer, None], + "AvalonFingerprintTransformer": [AvalonFingerprintTransformer, None], + } # fit on toy data and print train/test score if successful or collect the failed FP failed_FP = [] for FP_name, (FP, useCounts) in FP_dict.items(): try: - print(f"\nrunning pipeline fitting and scoring for {FP_name} with useCounts={useCounts}") + print( + f"\nrunning pipeline fitting and scoring for {FP_name} with useCounts={useCounts}" + ) if useCounts is None: - pipeline = Pipeline([("s2m", SmilesToMolTransformer()), ("FP", FP()), ("RF", RandomForestRegressor())]) + pipeline = Pipeline( + [ + ("s2m", SmilesToMolTransformer()), + ("FP", FP()), + ("RF", RandomForestRegressor()), + ] + ) else: - pipeline = Pipeline([("s2m", SmilesToMolTransformer()), ("FP", FP(useCounts=useCounts)), ("RF", RandomForestRegressor())]) + pipeline = Pipeline( + [ + ("s2m", SmilesToMolTransformer()), + ("FP", FP(useCounts=useCounts)), + ("RF", RandomForestRegressor()), + ] + ) pipeline.fit(X_train, Y_train) train_score = pipeline.score(X_train, Y_train) test_score = pipeline.score(X_test, Y_test) - print(f"\nfitting and scoring completed train_score={train_score}, test_score={test_score}") + print( + f"\nfitting and scoring completed train_score={train_score}, test_score={test_score}" + ) except: - print(f"\n!!!! FAILED pipeline fitting and scoring for {FP_name} with useCounts={useCounts}") + print( + f"\n!!!! FAILED pipeline fitting and scoring for {FP_name} with useCounts={useCounts}" + ) failed_FP.append(FP_name) pass @@ -71,41 +117,68 @@ def test_transformer_pandas_output(SLC6A4_subset, pandas_output): X_smiles = X_smiles.to_frame() # run FP with default parameters except when useCounts can be given as an argument - FP_dict = {"MACCSTransformer": [MACCSKeysFingerprintTransformer, None], - "RDKitFPTransformer": [RDKitFingerprintTransformer, None], - "AtomPairFingerprintTransformer": [AtomPairFingerprintTransformer, False], - "AtomPairFingerprintTransformer useCounts": [AtomPairFingerprintTransformer, True], - "TopologicalTorsionFingerprintTransformer": [TopologicalTorsionFingerprintTransformer, False], - "TopologicalTorsionFingerprintTransformer useCounts": [TopologicalTorsionFingerprintTransformer, True], - "MorganTransformer": [MorganFingerprintTransformer, False], - "MorganTransformer useCounts": [MorganFingerprintTransformer, True], - "SECFingerprintTransformer": [SECFingerprintTransformer, None], - "MHFingerprintTransformer": [MHFingerprintTransformer, None], - 'AvalonFingerprintTransformer': [AvalonFingerprintTransformer, None]} + FP_dict = { + "MACCSTransformer": [MACCSKeysFingerprintTransformer, None], + "RDKitFPTransformer": [RDKitFingerprintTransformer, None], + "AtomPairFingerprintTransformer": [AtomPairFingerprintTransformer, False], + "AtomPairFingerprintTransformer useCounts": [ + AtomPairFingerprintTransformer, + True, + ], + "TopologicalTorsionFingerprintTransformer": [ + TopologicalTorsionFingerprintTransformer, + False, + ], + "TopologicalTorsionFingerprintTransformer useCounts": [ + TopologicalTorsionFingerprintTransformer, + True, + ], + "MorganTransformer": [MorganFingerprintTransformer, False], + "MorganTransformer useCounts": [MorganFingerprintTransformer, True], + "SECFingerprintTransformer": [SECFingerprintTransformer, None], + "MHFingerprintTransformer": [MHFingerprintTransformer, None], + "AvalonFingerprintTransformer": [AvalonFingerprintTransformer, None], + } # fit on toy data and check that the output is a pandas dataframe failed_FP = [] for FP_name, (FP, useCounts) in FP_dict.items(): try: - print(f"\nrunning pipeline fitting and scoring for {FP_name} with useCounts={useCounts}") + print( + f"\nrunning pipeline fitting and scoring for {FP_name} with useCounts={useCounts}" + ) if useCounts is None: pipeline = Pipeline([("s2m", SmilesToMolTransformer()), ("FP", FP())]) else: - pipeline = Pipeline([("s2m", SmilesToMolTransformer()), ("FP", FP(useCounts=useCounts))]) + pipeline = Pipeline( + [("s2m", SmilesToMolTransformer()), ("FP", FP(useCounts=useCounts))] + ) pipeline.fit(X_smiles) X_transformed = pipeline.transform(X_smiles) - assert isinstance(X_transformed, pd.DataFrame), f"the output of {FP_name} is not a pandas dataframe" - assert X_transformed.shape[0] == len(X_smiles), f"the number of rows in the output of {FP_name} is not equal to the number of samples" - assert len(X_transformed.columns) == pipeline.named_steps["FP"].nBits, f"the number of columns in the output of {FP_name} is not equal to the number of bits" + assert isinstance( + X_transformed, pd.DataFrame + ), f"the output of {FP_name} is not a pandas dataframe" + assert ( + X_transformed.shape[0] == len(X_smiles) + ), f"the number of rows in the output of {FP_name} is not equal to the number of samples" + assert ( + len(X_transformed.columns) == pipeline.named_steps["FP"].fpSize + ), f"the number of columns in the output of {FP_name} is not equal to the number of bits" print(f"\nfitting and transforming completed") - except: - print(f"\n!!!! FAILED pipeline fitting and transforming for {FP_name} with useCounts={useCounts}") + except Exception as err: + print( + f"\n!!!! FAILED pipeline fitting and transforming for {FP_name} with useCounts={useCounts}" + ) + print("\n".join(err.args)) failed_FP.append(FP_name) pass # overall result - assert len(failed_FP) == 0, f"the following FP have failed pandas transformation {failed_FP}" + assert ( + len(failed_FP) == 0 + ), f"the following FP have failed pandas transformation {failed_FP}" + @skip_pandas_output_test def test_pandas_out_same_values(featurizer, mols_container): @@ -120,29 +193,33 @@ def test_pandas_out_same_values(featurizer, mols_container): assert result_default.shape == result_pandas.shape featurizer_class_with_nan = MolecularDescriptorTransformer if isinstance(featurizer, featurizer_class_with_nan): - assert (pd.isna(result_default) == pd.isna(result_pandas.values)).all(), "NaN values are not in the same positions in the default and pandas output" - nan_replacement = 0. + assert ( + pd.isna(result_default) == pd.isna(result_pandas.values) + ).all(), ( + "NaN values are not in the same positions in the default and pandas output" + ) + nan_replacement = 0.0 result_default = np.nan_to_num(result_default, nan=nan_replacement) result_pandas = result_pandas.fillna(nan_replacement) else: assert (result_default == result_pandas.values).all() + @skip_pandas_output_test -def test_combined_transformer_pandas_out(combined_transformer, SLC6A4_subset_with_cddd, pandas_output): +def test_combined_transformer_pandas_out( + combined_transformer, SLC6A4_subset_with_cddd, pandas_output +): result = combined_transformer.fit_transform(SLC6A4_subset_with_cddd) assert isinstance(result, pd.DataFrame) assert result.shape[0] == SLC6A4_subset_with_cddd.shape[0] n_cddd_features = SLC6A4_subset_with_cddd.columns.str.match(r"^cddd_\d+$").sum() pipeline_skmol = combined_transformer.named_transformers_["pipeline-1"] featurizer_skmol = pipeline_skmol[-1] - if isinstance(featurizer_skmol, FpsTransformer): - n_skmol_features = featurizer_skmol.nBits + if isinstance(featurizer_skmol, BaseFpsTransformer): + n_skmol_features = featurizer_skmol.fpSize elif isinstance(featurizer_skmol, MolecularDescriptorTransformer): n_skmol_features = len(featurizer_skmol.desc_list) else: raise ValueError(f"Unexpected featurizer type {type(featurizer_skmol)}") expected_n_features = n_cddd_features + n_skmol_features assert result.shape[1] == expected_n_features - - -