{ "cells": [ { "cell_type": "markdown", "id": "d0c5f0f3", "metadata": {}, "source": [ "This post looks at two things:\n", "\n", "1. Supplying your own parameters when normalizing molecules using the RDKit's `MolStandardize`\n", "2. Capturing and parsig the RDKit's C++ logs from within Python\n", "\n", "The RDKit's `MolStandardize` module includes functionality for \"normalizing\" input molecules: applying a set of chemical transformations expressed as reactions to standardize the representation of particular functional groups or substructures of the input molecule. This kind of normalization is a common step in preparing molecules for a compound registration system. `MolStandardize` has a collection of default transformations adapted from Matt Swain's [MolVS](https://molvs.readthedocs.io/en/latest/) (`MolStandardize` itself started as a C++ port of MolVS) which cover standardizing a variety of common functional groups. The full list is in the [RDKit source](https://github.com/rdkit/rdkit/blob/master/Code/GraphMol/MolStandardize/TransformCatalog/normalizations.in).\n", "\n", "Though we have tried to provide a broad and useful set of transformations, we know that they won't fit everybody's needs, so the `MolStandardize` allows the user to provide their own transformations. The first part of this post demonstrates how to do that.\n", "\n", "The normalization funcationality in `MolStandarize` sends information about what transformations have been applied to the console using the RDKit's logging functionality. This can be useful when working with small numbers of molecules in the shell or a notebook, and when debugging new transformations, but quickly becomes irritating when working with larger sets of molecules. In the second part of the post I'll show how to disable this logging information as well as how to capture it and parse the logs to find out which transformations were applied to each molecule.\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "id": "a6ccbee4", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T04:54:00.013416Z", "start_time": "2024-02-23T04:53:58.694409Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2023.09.5\n" ] } ], "source": [ "from rdkit import Chem\n", "from rdkit.Chem.MolStandardize import rdMolStandardize\n", "from rdkit.Chem import Draw\n", "from rdkit.Chem.Draw import IPythonConsole\n", "\n", "import rdkit\n", "print(rdkit.__version__)" ] }, { "cell_type": "markdown", "id": "1db0c5ad", "metadata": {}, "source": [ "# Providing your own normalization transformations" ] }, { "cell_type": "markdown", "id": "9a236c0c", "metadata": {}, "source": [ "Let's start with a simple molecule to demonstrate the default behavor of the normalization code.\n", "\n", "The easiest way to apply the defaults to a molecule is to use the function `rdMolStandardize.Normalize()`:" ] }, { "cell_type": "code", "execution_count": 2, "id": "00fee046", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T04:54:00.107390Z", "start_time": "2024-02-23T04:54:00.061640Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[05:54:00] Initializing Normalizer\n", "[05:54:00] Running Normalizer\n", "[05:54:00] Rule applied: Recombine 1,3-separated charges\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlgAAADICAIAAAC7/QjhAAAABmJLR0QA/wD/AP+gvaeTAAAbD0lEQVR4nO3deWxU59UG8DPj3TjeMJh9x8assTEGEhLWis30Uxb3S9o4VVPFFYo0tFKJE9JqyMZnEqka2iiRk6jVtAUlDknTKYSoY0jYl5gtGBsMNmYn8QY2GLzMnO+POxlPbGPfWe/yPj+hKOC542M4c5+Z9957roGZCQAAQFRGpQsAAABQEoIQAACEhiAEAAChIQgBAEBoCEIAABAaghAAAISGIAQAAKEhCAEAQGgIQgAAEBqCEAAAhIYgBAAAoSEIAQBAaAhCAAAQGoIQAACEhiAEAAChIQgBAEBoCEIAABAaghAAAISGIAQAAKEhCAEAQGgIQgAAEBqCEAAAhIYgBAAAoSEIAQBAaAhCAAAQGoIQAACEhiAEAACh+RiE169f37hx47179wJbjcisVuvMmTOzs7OPHj2qdC2KQV8F3Pvvv4++AugH++SXv/wlEY0cOdJqtfr2DOB29erV/Px8g8Hg/kdZtGhRU1OT0nUpAH0VQFJfeb7Yhe0rgL75GIS7du2aPn269OpasGDBiRMnAluWIFpbW4uKih544AEiiomJWbZs2ciRI6W/1eHDh1utVqfTqXSNIYW+CohufZWTkyN4XwH0zccgZGaHw2G1WgcPHkxERqMxPz//u+++C2Blumez2caOHSvtnnJzc2tqaqQ//9Of/jR+/Hjpz+fPn3/8+HFl6wwx9JWf0FcA3vI9CCVNTU2FhYWRkZFElJiYWFRU1NbWFpDKdOzYsWOPPvqotEt68MEHd+/e3e0BPcPgxo0bipSqFPSVD9BXAL7xNwglZ8+eXblypfQKTEtL27ZtW0CeVn/q6+tNJlNYWBgRJScnWyyWzs7O+z1YCoOoqCh3GNy7dy+U1SoOfSUT+grAH4EJQondbp88ebK021qyZMnp06cD+ORa197ebrFYEhISiCgiIsJkMsk8beHs2bO5ubnS3+rEiRP/85//BLtUtUFf9QF9BeC/QAYh9/ayvHnzZmC/hRbZ7fYpU6a4d+Xl5eWhfwZNQ1/1Cn0FEBABDkKJ50LNwIED+16o0TfP991paWn+vO+WwiAxMdHb9/66gb5yQ18BBFBQglBy7NixRx55RHqtZmZm9jx0r29BOhLT0NAg/2iQLqGv0FcAgRXEIJTYbLYxY8a4T+a+cOFCsL+j4kJwAcDx48fd5wdmZGR8+eWXgX1+9UNfBeOcT/QViCnoQcg/XN4bFxcnXd5bWFjY3Nwcgu+riK++4szMzokTp0lXa3l7Sfj169flP/h+V4wJQrC++mrGjBnuqwDRVwABFIoglFy5csU9SEyX4y1qaviJJ5iIiXjp0j2ffPKJ989QExMTk5eXd/HiRZmbtLW1WSwWaYZIZGSkyWTScRj0Svd9dfnyZfcPOGLECB9+QPQVQN9CF4SSw4cPz5kzR3qzOWvWrAMHDoS4gGC4c4fNZo6OZiKOjWWzme/e9eV5tmzZEh0dTURxcXEbNmy4K/tZrl69WlBQYDQaiWjYsGHFxcUOh8OXCjRLp311x2w2Sy0RGxtrNptbW1t9eB70FUDfQh2EzOxwOD788MPU1FQimjZt7q9/zd4s26iL08klJTxqFBOxwcB5eVxb69cTXrp0yT0o2dvZ00eOHHnooYekbbOzs/fv3+9XKVqjs776xz945cqPichgMDzzzDNXrlzx5wnRVwB9UCAIJbdu3Vq7du2DDx4i4vh4fust1twIrbIyfvhh11rozJm8b1/AnnnXrl3uA0JezZ52Op0lJSXShGWDweDVapg+6KCvDh/mOXOkt1bOJ59cffDgwUA9M/oKoFeKBaHk3DnOy3NlyYQJXFKibDlyXbvGBQVsNDIRDx3KxcUc8BUjf049vX37tntJbcCAAWazWf5qmD6gr+4HfQXQk8JBKNm5k6dNc+22Fi3ib79VuqD7a2tji4Xj45mIIyPZZOJbt4L47fyZPe3Papg+oK/uB30F4EkVQcjMHR1cXMyDBjERh4dzQQF//73SNfVgs/G4ca4da24uV1eH6Pv6M3va8w5/CxcuPHnyZPDqVCH0VR/QVwAStQShpLGRTSYOD2ciTkpii4U7OpSuiZmZKyt52TLXrmrSJN6xQ4Eaus2elj8WEnf4Q1/1AX0FoK4glFRW8vLlrr1Dejp/8YWSxTQ0dO1Dk5MV3of6M3u6sbHRvRqWlJQk4B3+0Ff3g74CwakxCCU2G48f37VedP68AjV89hknJTERR0SwycSNjQrU0JM/s6fPnDmzYsUK6e1/enq6gHf4U7yvpNXalJSu1dq6ulDX0Cv0FQhLvUHIzO3tXWcQSFEU1DMIeiov5/BwXryYT50K6feVw/N25N7Onhb8Dn8K9lVpKU+d6oph9BWASqg6CCXSOeVhYUzEKSlssXAox+Kr+VRD9mMsJO7wF+K+qqrquqJj4kS1X9GBvgKhaCAIJWVlPG+eaz+SlcV79/bymPp6LivjsjLu42VbXc1lZVxR0cuXLl1im43b2wNWc2hIs6elsZDezp7GHf5C0FctLWw2c1QUE/GAAWw2cyDumxR06CsQh2aCkH+YZzZ6dNcBnm7zzKxW15cSEvjatd6fRJqLnZXVy5c+/JCJuL4+8JWHgD+zp48ePep5h789e/YEtVS1CV5fORxstXJqKhOx0cj5+Rzo+yYFHfoKRKClIJTcucNFRRwX55pwXVjILS2uL7l3WET8zDO9b67XIJQcOXJk7ty50q7H29nTAt7hz1PA++rQIZ4927VVTg4HblCaAtBXoG/aC0JJbW3XEZfRo1m65ZHnDouI7fZeNtR3EDKz0+m0Wq1DhgyRxkLm5+fLvxddzzv8tbjTQAwB6atLl/hnP3M9eNQo/ugj1sGNodBXoGNaDUKJ+033c88xe+yw5s9nIk5L6+VgTM8gNJk4I4MzMnjoUNdW0m//9reQ/RyB589YSN3f4a9ffvbVsWMcFtb9Y6U+oK9Al7QdhMzc2cnvv+86cuPeYR044DobcP367o/vGYQ7dvA77/A77/AvfsFEvHGj67fHj4fupwiSc+fO5eXlSatSEyZMKPHmVEXPO/zl5OTo4w5/8vnZVx98wJcvh7TgUEJfgc5oPgg9uXdYN2/y6tVMxFFRXFn5o8fofmm0p507d06bNk3a9SxatEj+WEh/VsP0xM++0iv0FeiGboOwoYEHDnQtZ3kuwAgYhMzc0dFRXFw8aNAgIgoPDy8oKPhe9vBpaTUsKipKWg0zmUzyT6PXBz/7SsfQV6APug1CZv7LX1y/3by56zF97LC2bOEhQ9QyRy0YGhsbTSZTeHi4D2MhPVfDIiIifve73wW1VFXxs690D30FWqfnIOzs5MxMJuLU1K54E3mHJTlz5szy5cvdYyG3b98uf9u///3v0lt4Ilq5cmXwilQV9JUc6CvQLj0HITMfPOi63/fq1a4/wQ5LYrPZxo8f7x4LWdHrTJTe3L179/HHH5c2DGqF6oG+kg99BVpkJF2bM4eee46IqLiYjh5Vuho1WbVqVWVlpcViiY+PLy0tnTFjxpo1a5qbm/vdMDo6+tNPPw1BhWqGvrof9BVokc6DkIg2bqRBg8jppDVriFnpatQkIiJizZo11dXVJpPJ6XT++c9/Hj9+/KZNmxwOh9KlaQD66n7QV6A5+g/C5GT6v/8jItq/nz77TOlq1CclJWXTpk1HjhyZN29efX39b3/725ycnL179ypdl9qhr/qGvgIN0X8QEtGvfkXSoMQXX6S2NqWrUaWsrKy9e/fabLbRo0dLd6RbtWpVbW2t0nWpGvqqX+gr0AQhgtBopHffpbAwqqkhu13palRs1apVFRUV0ljIbdu2nTp1SumKVA19JRP6ClROiCAkogcfpBdeICK8c+9HbGxsYWFheXn5G2+8sWrVKqXLUTv0lUzoK1AzUYKQiF5/nYYNU7oIjRg9evQrr7yidBXagL6SD30F6iRQEMbH09tvK10E6A76CkDrwpUuIJCysqioiIgoOrr3B/z859TURLdvU2pqKOsCbUNfAeibgXENFHhPuqscmgcCC30FitD50uiNG/Txx7RnT+9fvXCBPv6YvvkmtDWB9vXdVwCgLToPwhMn6KmnaMOG3r/61Vf01FP03nuhrQm0r+++AgBt0XkQAgAA9A1BCAAAQkMQAgCA0BCEAAAgNAQhAAAIDUEIAABCQxACAIDQEIQAACA0BCEAAAgNQQgAAEJDEAIAgNAQhAAAIDQEIQAACA1BCAAAQkMQAgCA0BCEAAAgNAQhAAAIDUEIAABCQxACAIDQEIQAACA0BCEAAAgNQQgAAEJDEAIAgNCEDkKj8R/R0cnh4S8oXQgAAChG6CB0Ojvu3Wvq7LyrdCEAAKAYnQdhWFjHkCGO+Pg2pQsBXUFfAeiJzoPQ4dh540Z4c/P/KF0I6Ar6CkBPdB6EAAAAfUMQAgCA0BCEAAAgNAQhAAAIDUEIAABCQxACAIDQEIQAACA0BCEAAAgNQQgAAEJDEAIAgNAQhAAAIDQEIQAACA1BCAAAQkMQAgCA0BCEAAAgNAQhAAAIDUEIAABCQxACAIDQEIQAACA0BCH0wuFw7Nu3T+kq1KuxsVHpEjQJfQXqJHQQPvzww++9996zzz6rdCHqsnv37uzs7AULFpw6dUrpWlSno6Nj06ZNzz//vNKFaA/6ClQrXOkClJSenp6enq50FSpSW1u7du3arVu3EtGYMWPwuaebzz///Pe//311dbX0287OTmXr0Qr0Faic0J8Iwa21tXX9+vWTJ0/eunVrbGys2WyuqKiYP3++0nWpxZkzZ1asWPHYY49VV1dPmjTp9ddfJ6LwcKHfR8qBvgJNwCtZdMy8devWtWvXXrx40WAw5OXlvf3226NHj1a6LrVoampav379u+++29nZmZSUZDabX3jhhdLSUqXrUjv0FWgIglBoR48eXbNmzf79+4lo5syZFotl3rx5ShelFp2dnX/961//8Ic/1NXVhYeHFxQUvPHGG4MGDSKi5uZm93+hJ/QVaAzr2iuvvEJEY8eOra+vV7oWdbl27VpBQYHRaCSioUOHFhcXOxwOmdt+8sknum+enTt3Tps2TfoxFy1a9O2333p+VVoajYyMrKqqUqpCdUJfgRbptucqKiqWLl1KRHFxcUSUlJRUVFTU1tamdF3Ka2trs1gs8fHxRBQREWEymW7duiVz2/Pnz7vjIS0tLah1KuXcuXN5eXnSzzhhwoSSkpKej6mpqYmIiCAig8Hw05/+9O7du6GvU23QV6BdOgzChoYGk8kUFhZGRMnJyevWrVu+fLn0GktPT9+2bZvSBSrJZrONGzdO+tvIzc09f/68zA07OjqKi4sHDhwobZuRkXH27Nmglhp6t2/fNpvNUVFRRDRgwACz2dxHwu3YsUNaJkVfMfoKNE5XQdje3m6xWBITE6X3pAUFBXV1ddKX7Hb75MmTpRfbkiVLTp8+rWypoVdZWbls2TLpb2DSpElffPGF/G1LS0unTp0qbTtjxox///vfwatTEU6n02q1DhkyRPqQl5+ff/36dTkbvvbaa+4AQF+hr0Cj9BOEdrt9ypQp7l1SeXl5twdIMZmQkOBeurl586YipYaY9BFZOtc/OTnZYrF0dHTI3Laqqsq9Tjhx4sRe1wm17vDhw3PmzJF+xlmzZh04cEDmhk6nc8uWLSNGjJDiE32FvgKN0kMQnj17Njc3V+aLqr6+3r1wOnDgQIvF0tnZGbJSQ0xad0pJSSEi6bzH77//Xua2LS0t7nXCuLg4s9l87969oFYbeleuXMnPz5cybPjw4Var1el0ytz26NGjjzzyiNR1WVlZ27ZtQ1/JIUJfgeZoOwibmpoKCwulF1ViYmJRUZHMF5XnXiwzM3PPnj3BLjX0SktL3ScgLF68uNt5j31wOBxWqzU1NZWIjEZjfn7+jRs3glpq6LW2thYVFUknUsXExBQWFra0tMjctq6u7n6Zh77qgwh9BRql1SAMyIvKZrONGTPGfYT/woULQahUAXLOe7yfQ4cOzZ49W9p29uzZBw8eDF6dSvH5311aXfc8MbLXVVD0VU8i9BVolyaD8Ouvv54xY4b0opo/f/7x48d9fip/PhmoUM/zHuWvO12+fNm9TjhixAiv1gm1ovn4cfeV3VlZWV59YrPb7RkZGTLPi0FfuYnQV6B1GgvCIL2o/DlWpBKeH5G9Ou+Rme/cuePea8fGxmp9r927+no2mTgsbHl2trfH8KRBo1IEpqenb9++XeaG6Cv99xXogmaC8M6dO2azOTo6WnpRmc3m1tbWwH4Ln88eVJxn5Tk5OfLXnZxOZ0lJiXsCZG5ubm1tbVBLVUBbG7/1FsfHMxFHRl559VX5Z3U2NjYWFhZGRkaSHzMZ0Ff67CvQEQ0EoeeLSpreG7wXlc/XkynFn88cZWVlnuuEe/fuDWqpyrDbefJkJmIiXrKEZV/nJ50YKV0yLx2Eln9iZE/oKwA1U30QHj78vz9cGuHVe1J/eDVhRCme607eHoWSBkJK5z2mpKTo81z/M2d4xQpXBKalsTeTX3bu3Dl9+nSp6xYuXHjy5MmAVIS+AlAnFQfhtWtcUMBG49Y5c7yd3hsQ/pwjF2wBPO9R/kBIzWhs5MJCjoxkIk5M5KIilr2e6fmPPmrUKKvVGvDq0FcAaqPKILx7lzds4Lg4JuKoKH755dvKHWPv+y4EodftOm6vznu02Wzjx4937+bkD4TUDIeDrVYePJiJ2Gjk/Hz+7juZm0of16SD0CH4uIa+AlAP9QWhzcbjxrlWtHJzubpa6YJ+dLjI2zkaAeTPTJzKykrPyeNeDYTUjF27ePp0V+csXMiy1zOVOoCHvgJQCTUFYWUlL1vm2pFNmsQ7dihd0I80Nja6JysmJSV5NVnRT/5MSVWw7NC5dInz812dM3Ike7OeeeTIkblz5yp4Sif6CkBx6gjChgY2mTg8nIk4OZktFlbriyr0b4G9uo7bk0o+cATX7dtsNnN0NBPxgAFsNrP89czLl+uefz4mJoaIRowYsXnzZgUv8kNfAShI6SDs6ODiYk5JYSIOD+eCAv7hxklqFpqDIj5fx83qOwQVeE4nl5TwqFFMxAYD5+XxxYtyt21t5Vdf5dhYJnp9yZI//vGPt2/fDmatcqGvABShaBCWlvLUqa4VrcWL+dQpJYvxUlBPk/PnOm41n5QYMEeO8EMPuTonO5v37/diW5uNx47tOghdUxO0Kn2BvgIIPYWCsKqK8/JcO6MJE1izL6qAXzglTbTy7TpuTVym5q+rV6WLapiIhw3j4mKWf1HNsWP86KOursvM5N27g1moX9BXAKEU8iBsaWGzmaOiug7qaP9uZIEapbF//373DbsXL158SvZHZM0NLvFFWxtbLPzAA9KkNDaZuLlZ7rY/DBplIh44kC0W1sKF3ugrgNAIYRBK13ilpnZd46Wju5EFZLjivn37DAbDyJEjvbqOW7ujLL1QWspjxrg+zD35JMu/sVF7O1ssnJDARBwRwSYTa+r28egrgBAIVRAeOsRz5rh2ZDk5rNO7kfk/bv/TTz+Vf4MbHdzcQK6yMjYaOSODv/zSi63sdp4ypWvQaHl50OoLLvQVQFB5H4Tnz/NXX/HWrVxayhUV3O8rxOnkp5927YxGjeKPPup/E40LwQ3YdHa7O2YZfbVzpxfrmWfP8sqVvg0aVS30FUCQyA7ClhZ+7bWu5Sn3r9RUXrOmn0FWq1dzbCwXFrJIL6rg3ZJbVzdA96evetXU5POgUU1AXwEEnLwgrKzs2lUZDDxuHM+cyWlprrMPpD3O11/fd/P6er50KVAVa4jnTU2lU/Vu+HdY1HMgZGZmplcDIdXIz77qxo9Bo9qCvgIILBlBeO2aa+cSHs5r1/LVq11fqqvjN9/kmBgm4uhoPnas60vNzbx9e/dfmjpPIVBaWlrcZ5/HxcWZzWb5R2vc/BkIqVK+9dX97NrFM2a44nPBAj5xIniFqwT6CiBQZAThqlWuN+z3u9rv669dl0NMmdJ1FOfEie6LXUR8+HDACteaqqoq9/XIEydOlH89sj8DIVXNt77qyY9BozqAvgLwX39BWF7OBgMT8XPP9fWw9etde6J//cv1Jx0dfOVK91/t7YGpWrNKS0u9uqLLbrdPnjxZerxXAyHVzue+8uQ5aDQ21rtBo/qCvgLwR39BuG6da0/U901t6upcb97z8gJYnC5JM4tTUlLoh5nFdb2NV+02EHKbLs577OJnX/kzaFSn0FcAPusvCOfPZyIePLj/Z3r4YdfUK5ChoaHBfWwmOTm5sLDQfYCnurp69erVvg2E1Aw/+2rDBleOzp7Nhw4FqUYtEr2vAHzSXxAOG8ZEvGhR/8/0m9+49k0iXSPhp4qKimXLlklvz6Oiot58881nn33WaDS6zwb8TqfnPfrbVw0NPHWqd4NGRSJuXwH4pL8gjI1lIn7iif6fyb3YdflyQCoTx8aNG6UbnLolJSUF8PowNfK/r/Q+lsF/IvYVgE+M1LfOTiKiH7+ceud+THt7/w8GDy+++GJdXd1PfvKTiIgIaZxHY2Oje8yjPvnfVwZDoGvSGxH7CsAn/e2JEhKoro6am/t/plu3XP+TlORvUeJJTEz873//q3QVIYS+Cgnh+grAJ/19Ihw6lIiotrb/Z6qpISIaMIASEvwtCnQPfQUAqtFfEObkEBFVVdHNm309zOmkb74hIsrOJmN/zwmAvgIA1ehv57J0KRGRw0EffdTXw+x2unGDiGj58gAVBrqGvgIA1TAwc19f7+igsWPp6lUaNoxOn6bExN4fM2sWnTxJMTF06RKlpASpVtAP9BUAqEZ/nwgjIshiISK6do2WLqWrV7s/4OZNevxxOnmSiOi117C3AlnQVwCgGv19IpS89BJt3EhEFBdHTz9N8+ZRaio1NNA339DmzVRXR0T09NP0z3/iQA54AX0FACogLwiJ6IMPaN06qq/v5UtxcfTyy/TSS9hbgdfQVwCgNNlBSETNzfT552S308WL1NRE8fE0fDgtXkyPPUaDBwezSNA19BUAKMqbIAQAANAdLDoBAIDQEIQAACA0BCEAAAgNQQgAAEJDEAIAgNAQhAAAIDQEIQAACA1BCAAAQkMQAgCA0BCEAAAgNAQhAAAIDUEIAABCQxACAIDQEIQAACA0BCEAAAgNQQgAAEJDEAIAgNAQhAAAIDQEIQAACA1BCAAAQkMQAgCA0BCEAAAgNAQhAAAIDUEIAABCQxACAIDQEIQAACA0BCEAAAgNQQgAAEL7f36oH0NpDbtXAAAAqnpUWHRyZGtpdFBLTCByZGtpdCAyMDIzLjA5LjUAAHice79v7T0GIOBnQAAOKG5g5FDQAtL/mRnZHDSADGYW9gSQACMzCxtDApjB5pABkgCpwMngZmBUYGTKYGJiZmBiSWBhzWBiZUtgY89gYmdMEGEEqmFjZGdjZWESzwIZCXdFUNbP/QwMB/aDOA/d1IC0AzLbHsSGqrGHitvD2EBxeyQ19kh67WFmigEAvgslB25fsNwAAAD+elRYdE1PTCByZGtpdCAyMDIzLjA5LjUAAHicfVLLjsMgDLzzFfMDiUxiknDoIY+qu2pLpN20/9B7/19rb5dAV1FsRjJobMYGA7Wv6fx4YrVqMgagneW9x70mInOFBhiOp8+AcemHeDLOt7B8oxMn9Xdmv8zXeGIxo7Cl5865ViNHaqCS/gKMH6dDYXHvLwcb0yqMKKhs2DvrNWrdv7TIrBEy5gbxt/6rPMck1vKrqg1RkeiEuBbf4TXCW+vtqG1z3l5bXX7x1tgi8Rimt4G/nmCYw5SeQL1Ko2VBneZnBdlkWLYu9c+CJrXJgjZ1w4IuaWZBlSvLdeg+fiKJzQ9rNH8ag9h2PgAAAGl6VFh0U01JTEVTIHJka2l0IDIwMjMuMDkuNQAAeJxzjs7TjjVM1oj2143VTAYCQ4UaDV1DPUsTC1MzHUM9Ux1rXQM9MxNLU0NLHQM9cxS+LlQAplwXrB4hDebCJSGKYVwID64WpFSzBgDgNR5NRpHWEQAAAKN6VFh0cmRraXRQS0wxIHJka2l0IDIwMjMuMDkuNQAAeJx7v2/tPQYg4GdAAA4obmDkUNAA0sxMbA5gmoU9AUwzszlkgGlGfAyGBCCDkZmbgVGDiZEpgZkxgYU5g4mVJYGNNYOJiS2BiZ1BhBGohI2RmYWVjUk8C6Qc7oagrJ/7GRgO7AdxHrqpAWkHZLY9lG0PUwNUbw9TA2Ujq7GHiu+HscUA2Qgj+/KwQd4AAADmelRYdE1PTDEgcmRraXQgMjAyMy4wOS41AAB4nH1SUQ6DIAz95xS9wEzVIvKpYpZlEZLN7Q773/2zNpsWP0aB5NE82r4XDEjcwvX1hj2aYAwAFrb3Hp4tIpoFBMA4ny8RpnUYt8yUHnG9Q88LZR2Zw5qWLVNDglNdeeqtdYIsSgBW+AMbs4EJTlh15G3tBTn7h9lCzJgFInFJrVjobZmoQxYqdjmxwHN550LjXkTvBQvEOYaDr1+nxxSDOt3IUTuJT6uekSTUGWLRpPqJpVlVSaygUzHE753OXPO1zyfL55D79lcYmw9ZtHlFd3Z0jQAAALx6VFh0U01JTEVTMSByZGtpdCAyMDIzLjA5LjUAAHicXY1BDsIgEEWv4lITmDAtUMG48gB6A0JaFyZSmlqjJj28tNqGDLv3/gtzarGeHh7Pm3HLEYzcK80QFDtwAVoahYYJqBKvOK9L+tsW4iTl5Kf/vh6a9x3zQwyXPnZWQH/19eAm4W7NG0qLEO+NC75r40wkKJJ6+YdrniF8AG1BA2lLqpSVVGmrqKqszk4XiUiASeWnqyyfiOQiqSwfv352coU/zyIaAAAAAElFTkSuQmCC", "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m = Chem.MolFromSmiles('[O-]c1[n+](C)cccc1')\n", "m2 = rdMolStandardize.Normalize(m)\n", "Draw.MolsToGridImage([m,m2])" ] }, { "cell_type": "markdown", "id": "d279fa3b", "metadata": {}, "source": [ "An aside: as was mentioned in [another recent blog post](https://greglandrum.github.io/rdkit-blog/posts/2024-02-11-more-multithreading.html), it's possible to call `NormalizeInPlace()` to modify the molecule in place instead of making a copy and working on it. This will be a bit faster and can be used with mulitiple threads when working with more than one molecule." ] }, { "cell_type": "markdown", "id": "4869bd72", "metadata": {}, "source": [ "We can accomplish the same thing by creating a `Normalizer` object and using it to normalize the molecule:" ] }, { "cell_type": "code", "execution_count": 3, "id": "6978c1f3", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T04:54:01.777584Z", "start_time": "2024-02-23T04:54:01.768867Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[05:54:01] Initializing Normalizer\n", "[05:54:01] Running Normalizer\n", "[05:54:01] Rule applied: Recombine 1,3-separated charges\n" ] }, { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nrm = rdMolStandardize.Normalizer()\n", "m2 = nrm.normalize(m)\n", "Draw.MolsToGridImage([m,m2])" ] }, { "cell_type": "markdown", "id": "77833cba", "metadata": {}, "source": [ "Now let's look at another molecule where the normalization doesn't do anything:" ] }, { "cell_type": "code", "execution_count": 4, "id": "1c22d99a", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T04:54:02.873397Z", "start_time": "2024-02-23T04:54:02.862326Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[05:54:02] Running Normalizer\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlgAAADICAIAAAC7/QjhAAAABmJLR0QA/wD/AP+gvaeTAAAVRUlEQVR4nO3de3CU1f3H8e8mi4mhuQARqcotoVzkUigod4tIQWsmKDWMoDVMgagMjbFQk6HOEGinBqmj2GJnUUB/rZ2q1cFBRGukREIIRRvCxRQziohCCglJCIEkm83398dmkoiQZDfPZi/n/Rr+2Fx2z4l+9nxOnufZjU1VBQAAU4X5ewIAAPgTRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkUIADAaRQgAMBpFCAAwGkV4uU2bWm9//LEUFflvKggh5AoIWBTh5VaubL29c6d88IH/poIQQq6AgEURAgCMZvf3BAJOQ4OsX998e+9emTnTr7PpfufPy6pV8vHHYrPJrFny5JMSEeHvOYUCckWuELD4jfByYWEyaFDzv7g4f8+m+z3wgAwYIAUF8tFHUl4uv/61vycUIsgVuULAsqmqv+cQWGJi5Pz55tu//a1ERMgTT/h1Qt3pm29kyhT58kux2URELlyQG2+UykoJY8PUVeSKXCFgeRPE6upqy+cBP3O5REROnJCEhObVSkS+9z2Ji5Oysu6ZArkKQQGQK6BDHhfha6+9lpiYuH37dl/MJhAsX956e9IkueUW/02le9TVSVaWzJkjqhIfL+fOtX5JVaqrpXfvbpgFuQo1gZEroDM8LsKysrKKioqHH364srLSFxPyu88+k7ffbr79xRfidHb3BOrq6ubNmzd16tSMjIympibfDrZ3r4wdK+vWye7dsn+/JCRIfX3ra9zeektuuUUiI307BxEhV75nZq6ATlEPuVyu6dOni8iiRYs8vW9QuP56HTVKq6pUVVes0K1bu3X0I0eOjB8/vuX/TkJCgsPhaGxstH6kixc1M1PDw1VER47U/fubP5+Xp4mJunixPvCAjhunx45ZP/SVkCufMjZXQGd4XISqeuzYsWuvvVZE3n33Xcsn1OzLL7WkRJ1OXz3+1fXrp889p8uXq3bvguV0OnNyciIiIkSkT58+kydPHjhwoHvZGjFixKuvvupyuSwbLD9fhw5VEbXbNTNT6+q0qUkdDk1O1qYmra/X4mItKVFfLJRXR658gVwBHfKmCFV1/fr1InLDDTdUVlZaOyE9cUInTtR779UHH9Thw3XXLosfvyP9+mlDg44ZowcOdN+CdejQoQkTJoiIzWZLS0s7f/68qjY0NLzyyis/+MEPrNzF19ZqZqaGhamIjh6tBw6oqh47ptOmqYiK6IcfWvEDeYlcWYtcAZ3hZRG6XK6pU6eKyNKlS62dkN5zj27e3Hz76FEdOFAvXrR4iHb166equmePTpigGRm6daseParV1b4arqGhIScn55prrhGRQYMG5ebmfvcbrFq2vtq9WwcNUhG95hrNztaGBnW51OHQnj1VRPv107fesuJn8h65sgq5AjrPyyJU1ZKSksjISJvN9t5771k2naYmjY7+1pGr6dNbTzP40v/+p8uXa01N84Klqg89pIMG6ZYt+sMfanS0Zmaq5b+lFBcX/+hHP2rZsNfU1FztO10u1+uvv+71slVdXZ2enh7Zo8eFm2/WMWP0k09UVUtL9bbbmjfsKSlaXm7JD9VF5KrryBXgEe+LUFV///vfi8jAgQPdh1wsUFurcXHf+szcubpjhzUPfnV//7ted52KaEZG64JVVqa9eukf/6i33978pO7VS9eutWYX33bDnpCQsKtzR+q8W7Z27tzZv39/EYmIiPj7s8+q06lOp+bkaGSkiuj3v6/btlnwI1mHXHmNXAFe6FIROp3OW265RUSWLVtm1YS0b189e7b1w5tv1pIS3blTS0stG6KNsjL92c+a16PbbtPSUi0ubv3q5583b2fz8zUpqfnbur6LLywsvPnmm0UkLCwsLS3twoULHt39isuW80oXgFRVVaWlpdlsNhEZO3ZsUVGRqp47ckQnTFARtdl0yZLmCxkDCbny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", "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m = Chem.MolFromSmiles('CC(C)(C)OC(=O)NCCC(=O)O[Na]')\n", "m2 = nrm.normalize(m)\n", "Draw.MolsToGridImage([m,m2])" ] }, { "cell_type": "markdown", "id": "503eae34", "metadata": {}, "source": [ "As a demonstration, let's construct a normalizer which will break the bond to the alkali metal and remove the Boc protecting group. This is, of course, an artificial example, but it shows how to provide new transformations to `MolStandardize`" ] }, { "cell_type": "code", "execution_count": 5, "id": "d1e6c4dc", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T04:54:08.449768Z", "start_time": "2024-02-23T04:54:08.440610Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[05:54:08] Initializing Normalizer\n", "[05:54:08] Running Normalizer\n", "[05:54:08] Rule applied: remove_Boc\n", "[05:54:08] Rule applied: disconnect_alkali_metals\n" ] }, { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# we provide the transformations in a string with one line per transformation.\n", "# Lines starting with // are comments and are ignored. Each line contains the\n", "# name of the transformation, a tab character, and then the reaction SMARTS for\n", "# the transformation itself. It's also possible to skip the names; in that case\n", "# just provide the reaction SMARTS (the tab is not needed)\n", "tfs = '''\n", "// this is from Deprotect.cpp:\n", "remove_Boc\\t[C;R0][C;R0]([C;R0])([O;R0][C;R0](=[O;R0])[NX3;H0,H1:1])C>>[N:1]\n", "// this should go last, because later transformations will\n", "// lose the alkali metal\n", "disconnect_alkali_metals\\t[Li,Na,K,Rb:1]-[A:2]>>([*+:1].[*-:2])\n", "'''\n", "# create the new Normalizer:\n", "cps = rdMolStandardize.CleanupParameters()\n", "nrm2 = rdMolStandardize.NormalizerFromData(tfs,cps)\n", "\n", "# and apply it:\n", "m2 = nrm2.normalize(m)\n", "Draw.MolsToGridImage([m,m2])" ] }, { "cell_type": "markdown", "id": "4e7cf098", "metadata": {}, "source": [ "If you're processing a lot of molecules, you probably don't want those log messages filling your console or notebook. It's possible to disable the logging:" ] }, { "cell_type": "code", "execution_count": 7, "id": "6caa1f97", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T04:55:18.810931Z", "start_time": "2024-02-23T04:55:18.808343Z" } }, "outputs": [], "source": [ "from rdkit import RDLogger\n", "RDLogger.DisableLog('rdApp.info')\n", "m2 = nrm2.normalize(m)\n" ] }, { "cell_type": "markdown", "id": "b058feb5", "metadata": {}, "source": [ "# Connecting the RDKit logs to the Python logger" ] }, { "cell_type": "markdown", "id": "f14a635b", "metadata": {}, "source": [ "It's also possible to have the logging the RDKit's C++ backend does sent to Python's built-in logging facilities. This has been available since the 2022.03.1 release of the RDKit.\n", "\n", "I won't do a complete introduction to Python's logging capabilities here (I'm not an expert!), but here's a quick demonstration of what we might do:" ] }, { "cell_type": "code", "execution_count": null, "id": "f9a78506", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 19, "id": "d06c5bd9", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T05:18:04.143889Z", "start_time": "2024-02-23T05:18:04.141575Z" } }, "outputs": [], "source": [ "import logging\n", "\n", "logger = logging.getLogger('rdkit')\n", "# set the log level for the default log handler (the one which sense output to the console/notebook):\n", "logger.handlers[0].setLevel(logging.WARN)\n", "# format the messages so that it's clear they come from the RDKit:\n", "logger.handlers[0].setFormatter(logging.Formatter('[RDKit] %(levelname)s:%(message)s'))\n", "\n", "# Tell the RDKit's C++ backend to log to use the python logger:\n", "from rdkit import rdBase\n", "rdBase.LogToPythonLogger()\n" ] }, { "cell_type": "markdown", "id": "07a634a0", "metadata": {}, "source": [ "Now do something which generates an error message:" ] }, { "cell_type": "code", "execution_count": 20, "id": "2a683682", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T05:18:05.440976Z", "start_time": "2024-02-23T05:18:05.433570Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[RDKit] ERROR:[06:18:05] SMILES Parse Error: unclosed ring for input: 'C1C'\n" ] } ], "source": [ "Chem.MolFromSmiles('C1C')" ] }, { "cell_type": "markdown", "id": "14b60a95", "metadata": {}, "source": [ "You can tell that this went through the Python logger because it has the prefix we set up above." ] }, { "cell_type": "markdown", "id": "21f37a19", "metadata": {}, "source": [ "Since we're only logging at the WARN (and above) level, the INFO messages from doing normalizations don't appear:" ] }, { "cell_type": "code", "execution_count": 21, "id": "02b60d99", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T05:18:07.039594Z", "start_time": "2024-02-23T05:18:07.037451Z" } }, "outputs": [], "source": [ "m2 = nrm2.normalize(m)" ] }, { "cell_type": "markdown", "id": "36581e55", "metadata": {}, "source": [ "Let's create an additional log message handler that catches INFO messages too but that saves them in a `StringIO` object instead of outputting them to the console:" ] }, { "cell_type": "code", "execution_count": 38, "id": "bb1924f7", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T05:20:43.872130Z", "start_time": "2024-02-23T05:20:43.866249Z" } }, "outputs": [], "source": [ "from io import StringIO\n", "\n", "logger_sio = StringIO()\n", "# create a handler that uses the StringIO and set its log level:\n", "handler = logging.StreamHandler(logger_sio)\n", "handler.setLevel(logging.INFO)\n", "\n", "# add the handler to the Python logger:\n", "logger.addHandler(handler)\n", "\n", "# we also need to change the level of the main logger so that the INFO messages get sent to the handlers:\n", "logger.setLevel(logging.INFO)" ] }, { "cell_type": "markdown", "id": "4366b070", "metadata": {}, "source": [ "Now normalize a molecule:" ] }, { "cell_type": "code", "execution_count": 39, "id": "5de7716e", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T05:20:44.775548Z", "start_time": "2024-02-23T05:20:44.353105Z" } }, "outputs": [], "source": [ "m2 = nrm2.normalize(m)" ] }, { "cell_type": "markdown", "id": "15644286", "metadata": {}, "source": [ "We don't see anything in the notebook because the main handler (the one which goes to the console/notebook) is still set to only show WARN and above, but `logger_sio` has the message:" ] }, { "cell_type": "code", "execution_count": 40, "id": "777aeb44", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T05:20:44.900994Z", "start_time": "2024-02-23T05:20:44.898027Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[06:20:44] Running Normalizer\n", "[06:20:44] Rule applied: remove_Boc\n", "[06:20:44] Rule applied: disconnect_alkali_metals\n", "\n" ] } ], "source": [ "text = logger_sio.getvalue()\n", "print(text)" ] }, { "cell_type": "markdown", "id": "c62efa41", "metadata": {}, "source": [ "We can use a regular expression to extract the rules that were applied to the molecule from this output:" ] }, { "cell_type": "code", "execution_count": 41, "id": "62d1f102", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T05:20:45.801092Z", "start_time": "2024-02-23T05:20:45.798300Z" } }, "outputs": [ { "data": { "text/plain": [ "['remove_Boc', 'disconnect_alkali_metals']" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import re\n", "rules = re.findall(r'Rule applied: (.*?)\\n',text)\n", "rules" ] }, { "cell_type": "markdown", "id": "faaff85f", "metadata": {}, "source": [ "If we now sanitize another molecule (or, in this case, the same one again), the log messages are appended to `logger_sio`:" ] }, { "cell_type": "code", "execution_count": 42, "id": "a4db1213", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T14:22:05.051809Z", "start_time": "2024-02-23T14:22:05.048739Z" } }, "outputs": [], "source": [ "m2 = nrm2.normalize(m)" ] }, { "cell_type": "code", "execution_count": 43, "id": "5721e131", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T14:22:12.047720Z", "start_time": "2024-02-23T14:22:12.040701Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[06:20:44] Running Normalizer\n", "[06:20:44] Rule applied: remove_Boc\n", "[06:20:44] Rule applied: disconnect_alkali_metals\n", "[15:22:05] Running Normalizer\n", "[15:22:05] Rule applied: remove_Boc\n", "[15:22:05] Rule applied: disconnect_alkali_metals\n", "\n" ] } ], "source": [ "text = logger_sio.getvalue()\n", "print(text)" ] }, { "cell_type": "markdown", "id": "cf5f6fa0", "metadata": {}, "source": [ "But we can reset the StringIO object:" ] }, { "cell_type": "code", "execution_count": 45, "id": "74d6d1e8", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T14:23:19.703702Z", "start_time": "2024-02-23T14:23:19.700393Z" } }, "outputs": [ { "data": { "text/plain": [ "['disconnect_alkali_metals']" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "logger_sio.truncate(0)\n", "logger_sio.seek(0)\n", "\n", "# Create and normalize a new molecule:\n", "new_m = Chem.MolFromSmiles('CCCO[Na]')\n", "new_m2 = nrm2.normalize(new_m)\n", "\n", "# show the normalizations that were applied:\n", "re.findall(r'Rule applied: (.*?)\\n',logger_sio.getvalue())" ] }, { "cell_type": "markdown", "id": "b687b38c", "metadata": {}, "source": [ "We can now combine everything to write a function which applies a collection of custom transformations to a list of molecules and returns the transformed molecules along with which transformations were applied to each molecule:" ] }, { "cell_type": "code", "execution_count": 46, "id": "80d8aa63", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T14:30:51.403809Z", "start_time": "2024-02-23T14:30:51.400558Z" } }, "outputs": [], "source": [ "import logging\n", "from io import StringIO\n", "from rdkit import rdBase\n", "import re\n", "\n", "def normalize_molecules(mols,standardization_rules):\n", " # Tell the RDKit's C++ backend to log to use the python logger:\n", " rdBase.LogToPythonLogger()\n", "\n", " logger = logging.getLogger('rdkit')\n", " # set the log level for the default log handler (the one which sense output to the console/notebook):\n", " logger.handlers[0].setLevel(logging.WARN)\n", "\n", " logger_sio = StringIO()\n", " # create a handler that uses the StringIO and set its log level:\n", " handler = logging.StreamHandler(logger_sio)\n", " handler.setLevel(logging.INFO)\n", " # add the handler to the Python logger:\n", " logger.addHandler(handler)\n", "\n", " \n", " # create the new Normalizer:\n", " cps = rdMolStandardize.CleanupParameters()\n", " nrm = rdMolStandardize.NormalizerFromData(standardization_rules,cps)\n", "\n", " match_expr = re.compile(r'Rule applied: (.*?)\\n')\n", " \n", " res_mols = []\n", " tfs_applied = []\n", " for mol in mols:\n", " mol = nrm.normalize(mol)\n", " res_mols.append(mol)\n", " \n", " text = logger_sio.getvalue()\n", " tfs_applied.append(match_expr.findall(text))\n", " \n", " logger_sio.truncate(0)\n", " logger_sio.seek(0)\n", "\n", " return res_mols,tfs_applied\n", "\n", " \n", " " ] }, { "cell_type": "code", "execution_count": 49, "id": "f35be9dd", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T14:32:48.724955Z", "start_time": "2024-02-23T14:32:48.718344Z" } }, "outputs": [], "source": [ "tfs = '''\n", "// this is from Deprotect.cpp:\n", "remove_Boc\\t[C;R0][C;R0]([C;R0])([O;R0][C;R0](=[O;R0])[NX3;H0,H1:1])C>>[N:1]\n", "// this should go last, because later transformations will\n", "// lose the alkali metal\n", "disconnect_alkali_metals\\t[Li,Na,K,Rb:1]-[A:2]>>([*+:1].[*-:2])\n", "'''\n", "\n", "mols = [Chem.MolFromSmiles(smi) for smi in \n", " ('CC(C)(C)OC(=O)NCCC(=O)O[Na]','CCCO[Na]','CC(C)(C)OC(=O)NCCC','c1ccccc1')]\n", "tmols,tapplied = normalize_molecules(mols,tfs)" ] }, { "cell_type": "code", "execution_count": 53, "id": "7026d378", "metadata": { "ExecuteTime": { "end_time": "2024-02-23T14:33:30.949806Z", "start_time": "2024-02-23T14:33:30.937640Z" } }, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Draw.MolsToGridImage(tmols,legends=['\\n'.join(x) for x in tapplied])" ] }, { "cell_type": "code", "execution_count": null, "id": "17aa6dd3", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.1" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 5 }