{ "cells": [ { "cell_type": "markdown", "id": "3254cd8a", "metadata": {}, "source": [ "## Ugropy power users\n", "\n", "In this final section of the tutorial, we will explore some advanced features of\n", "`ugropy` that were not covered in the previous sections. These features are\n", "intended for users who want to customize the behavior of the already\n", "implemented models in `ugropy` or who want to implement their own models." ] }, { "cell_type": "markdown", "id": "e3ee57b7", "metadata": {}, "source": [ "### Non-optimal solutions" ] }, { "cell_type": "markdown", "id": "c4e755ad", "metadata": {}, "source": [ "As explained in previous sections, `ugropy` allows you to search for multiple\n", "solutions for the models, but all these solutions are optimal (they use the same\n", "number of groups to represent the molecule). However, it is possible to search for\n", "non-optimal solutions along with the optimal ones. This is useful when you want \n", "to find all possible combinations of fragments that cover the molecule.\n", "Please note that this feature is intended for research purposes and is not \n", "recommended for actually modeling molecules.\n", "\n", "We can enable this for all `ugropy` models using the `search_nonoptimal`\n", "parameter:" ] }, { "cell_type": "code", "execution_count": 51, "id": "41aa9988", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[,\n", " ,\n", " ]" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from ugropy import unifac\n", "\n", "solutions = unifac.get_groups(\n", " \"9,10-dihydroanthracene\",\n", " search_multiple_solutions=True, # If this is False, search_nonoptimal is ignored\n", " search_nonoptimal=True,\n", ")\n", "\n", "# Three solutions were found:\n", "solutions" ] }, { "cell_type": "markdown", "id": "4d641286", "metadata": {}, "source": [ "We can visualize all the obtained solutions:" ] }, { "cell_type": "code", "execution_count": 52, "id": "3c08ee26", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "ACH: 8AC: 2ACCH2: 2" ], "text/plain": [ "" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "solutions[0].draw(width=600)" ] }, { "cell_type": "code", "execution_count": 53, "id": "6bb3498f", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "CH2: 1ACH: 8AC: 3ACCH2: 1" ], "text/plain": [ "" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "solutions[1].draw(width=600)" ] }, { "cell_type": "code", "execution_count": 54, "id": "9c613d5d", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "CH2: 2ACH: 8AC: 4" ], "text/plain": [ "" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "solutions[2].draw(width=600)" ] }, { "cell_type": "markdown", "id": "3eaedf79", "metadata": {}, "source": [ "If you are an experienced user of UNIFAC-like models, you may notice that the\n", "only \"correct\" solution is the first one. When non-optimal solutions are\n", "enabled, the algorithm will always find the optimal solutions first, and then\n", "it will search for non-optimal solutions in a \"non-optimal\" order." ] }, { "cell_type": "markdown", "id": "15d71dd6", "metadata": {}, "source": [ "### Changing the default ILP solver" ] }, { "cell_type": "markdown", "id": "267c509c", "metadata": {}, "source": [ "By default, `ugropy` uses the standard CBC solver from the `PuLP` library.\n", "However, `PuLP` supports a wide variety of solvers. Changing the ILP solver can\n", "significantly impact the library's execution time. A great alternative is the\n", "`XPRESS_PY` solver.\n", "\n", "First, you must install `XPRESS`:\n", "\n", "```shell\n", "pip install xpress\n", "```\n", "\n", "Then, you can change the default solver by passing it as an argument:" ] }, { "cell_type": "code", "execution_count": 55, "id": "4ca0c9bb", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/salvador/.virtualenvs/ugropy/lib/python3.12/site-packages/pulp/apis/xpress_api.py:774: DeprecationWarning: Deprecated in Xpress 9.8: use problem.addCols instead.\n", " model.addcols(obj, [0] * (len(obj) + 1), [], [], lb, ub, names, ctype)\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "ACH: 5ACCH3: 1" ], "text/plain": [ "" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from ugropy import unifac\n", "\n", "\n", "unifac.get_groups(\"toluene\", solver_arguments={\"solver\": \"XPRESS_PY\"}).draw(width=600)" ] }, { "cell_type": "markdown", "id": "2f240db7", "metadata": {}, "source": [ "### Understanding model instances and their configuration" ] }, { "cell_type": "markdown", "id": "136c6d32", "metadata": {}, "source": [ "`ugropy` is designed using the singleton pattern; therefore, all the models we\n", "have been using throughout this tutorial are instances of the `FragmentationModel` \n", "class. This class possesses several attributes that can be used to inspect \n", "the models' information and definitions.\n", "\n", "Each model in `ugropy` is composed of two distinct classes:\n", "`FragmentationModel` and `FragmentationResult`.\n", "\n", "The `FragmentationModel` class contains all the fundamental information \n", "about a model, such as its fragment definitions. It serves as the base class \n", "required to define a minimal model and implements the `get_groups` method. \n", "The specific models in `ugropy` are not direct instances of this base class, \n", "but rather instances of subclasses that inherit from it. For example, the \n", "UNIFAC model is an instance of the `GibbsModel` class (a subclass of \n", "`FragmentationModel`). The advantage of these subclasses is that they provide \n", "additional methods (such as multiple-solution filtering). Furthermore, a \n", "`GibbsModel` requires more detailed fragment information to be instantiated, \n", "such as the $R$ and $Q$ parameters.\n", "\n", "Finally, each `FragmentationModel` returns an instance of its specific \n", "`FragmentationResult` subclass when the `get_groups` method is called. In the \n", "case of a `GibbsModel`, the `get_groups` method returns a \n", "`GibbsFragmentationResult` instance (which inherits from `FragmentationResult`). \n", "This architectural design allows different models to perform specific \n", "post-processing tasks after fragment detection. For instance, the \n", "`GibbsFragmentationResult` class automatically calculates the $R$ and $Q$ values \n", "of the solution, while the `JobackFragmentationResult` class computes the \n", "Joback group-contribution properties.\n", "\n", "Understanding this architecture is important because it guarantees that while \n", "all models share the core attributes and methods required by the \n", "`FragmentationModel` base class, they also offer specialized features \n", "depending on their specific subclass.\n", "\n", "Let's examine the documentation of a base `FragmentationModel` class (you can \n", "always check the API documentation for the complete list of methods and attributes)." ] }, { "cell_type": "code", "execution_count": 56, "id": "f72db64e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on class FragmentationModel in module ugropy.core.frag_classes.base.fragmentation_model:\n", "\n", "class FragmentationModel(builtins.object)\n", " | FragmentationModel(subgroups: pandas.DataFrame, allow_overlapping: bool = False, allow_free_atoms: bool = False, fragmentation_result: ugropy.core.frag_classes.base.fragmentation_result.FragmentationResult = ) -> None\n", " |\n", " | FragmentationModel class.\n", " |\n", " | All ugropy supported models are an instance of this class. This class must\n", " | be inherited to create a new type of FragmentationModel.\n", " |\n", " | Parameters\n", " | ----------\n", " | subgroups : pd.DataFrame\n", " | Model's subgroups. Index: 'group' (subgroups names). Mandatory columns:\n", " | 'smarts' (SMARTS representations of the group to detect its presense in\n", " | the molecule).\n", " | allow_overlapping : bool, optional\n", " | Whether allow overlapping or not, by default False\n", " | allow_free_atoms : bool, optional\n", " | Whether allow free atoms or not, by default False\n", " | fragmentation_result : FragmentationResult, optional\n", " | Fragmentation result class, by default FragmentationResult\n", " |\n", " | Attributes\n", " | ----------\n", " | subgroups : pd.DataFrame\n", " | Model's subgroups. Index: 'group' (subgroups names). Mandatory columns:\n", " | 'smarts' (SMARTS representations of the group to detect its presense in\n", " | the molecule).\n", " | detection_mols : dict\n", " | Dictionary containing all the rdkit Mol object from the\n", " | detection_smarts subgroups column.\n", " |\n", " | Methods defined here:\n", " |\n", " | __init__(self, subgroups: pandas.DataFrame, allow_overlapping: bool = False, allow_free_atoms: bool = False, fragmentation_result: ugropy.core.frag_classes.base.fragmentation_result.FragmentationResult = ) -> None\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " |\n", " | detect_fragments(self, molecule: rdkit.Chem.rdchem.Mol) -> dict\n", " | Detect all the fragments in the molecule.\n", " |\n", " | Return a dictionary with the detected fragments as keys and a tuple\n", " | with the atoms indexes of the fragment as values. For example, n-hexane\n", " | for the UNIFAC model will return:\n", " |\n", " | .. code-block:: python\n", " |\n", " | {\n", " | 'CH3_0': (0,),\n", " | 'CH3_1': (5,),\n", " | 'CH2_0': (1,),\n", " | 'CH2_1': (2,),\n", " | 'CH2_2': (3,),\n", " | 'CH2_3': (4,)\n", " | }\n", " |\n", " | You may note that multiple occurrence of a fragment name will be\n", " | indexed. The convention is always: _i where `i` is the\n", " | index of the occurrence.\n", " |\n", " | Parameters\n", " | ----------\n", " | mol : Chem.rdchem.Mol\n", " | Molecule to detect the fragments.\n", " |\n", " | Returns\n", " | -------\n", " | dict\n", " | Detected fragments in the molecule.\n", " |\n", " | filter_mostly_polarity(self, solutions: List[ugropy.core.frag_classes.base.fragmentation_result.FragmentationResult], polarity: str = 'polar') -> List[ugropy.core.frag_classes.base.fragmentation_result.FragmentationResult]\n", " | Filter the solutions with most atoms occupied by \"polarity\" groups.\n", " |\n", " | Return the solutions with the largest number of atoms belonging to\n", " | polar or apolar groups (specified by the user). The method inspects all\n", " | the provided solutions and counts how many total atoms are occupied by\n", " | the specified polarity groups. The solutions with the highest number of\n", " | atoms belonging to the specified polarity groups are returned\n", " | (hydrogens doesn't count). A group is considered polar if its SMARTS\n", " | pattern contains at least one of the following atoms: {\"O\", \"N\", \"S\",\n", " | \"P\", \"F\", \"Cl\", \"Br\", \"I\"}.\n", " |\n", " | Parameters\n", " | ----------\n", " | solutions : List[FragmentationResult]\n", " | List of fragmentation results to filter.\n", " | polarity : {\"polar\", \"nonpolar\"}, optional\n", " | The type of polarity groups to consider (\"polar\" or \"apolar\"). by\n", " | default, \"polar\"\n", " |\n", " | Returns\n", " | -------\n", " | List[FragmentationResult]\n", " | Filtered list of fragmentation results.\n", " |\n", " | filter_mostly_polyatomic(self, solutions: List[ugropy.core.frag_classes.base.fragmentation_result.FragmentationResult]) -> List[ugropy.core.frag_classes.base.fragmentation_result.FragmentationResult]\n", " | Filter the solutions with most atoms occupied by polyatomic groups.\n", " |\n", " | Return the solutions with the largest number of atoms belonging to\n", " | polyatomic groups. The method inspects all the provided solutions and\n", " | counts how many total atoms are occupied by polyatomic groups. The\n", " | solutions with the highest number of atoms belonging to polyatomic\n", " | groups are returned (hydrogens doesn't count).\n", " |\n", " | Parameters\n", " | ----------\n", " | solutions : List[FragmentationResult]\n", " | List of fragmentation results to filter.\n", " |\n", " | Returns\n", " | -------\n", " | List[FragmentationResult]\n", " | Filtered list of fragmentation results.\n", " |\n", " | get_groups(self, identifier: Union[str, rdkit.Chem.rdchem.Mol], identifier_type: str = 'name', solver: ugropy.core.ilp_solvers.ilp_solver.ILPSolver = , search_multiple_solutions: bool = False, search_nonoptimal: bool = False, solver_arguments: dict = {}, **kwargs) -> Union[ugropy.core.frag_classes.base.fragmentation_result.FragmentationResult, List[ugropy.core.frag_classes.base.fragmentation_result.FragmentationResult]]\n", " | Get the groups of a molecule.\n", " |\n", " | Parameters\n", " | ----------\n", " | identifier : Union[str, Chem.rdchem.Mol]\n", " | Identifier of the molecule. You can use either the name of the\n", " | molecule, the SMILEs of the molecule or a rdkit Mol object.\n", " | identifier_type : str, optional\n", " | Identifier type of the molecule. Use \"name\" if you are providing\n", " | the molecules' name, \"smiles\" if you are providing the SMILES or\n", " | \"mol\" if you are providing a rdkir mol object, by default \"name\"\n", " | solver : ILPSolver, optional\n", " | ILP solver class, by default DefaultSolver\n", " | search_multiple_solutions : bool, optional\n", " | Whether search for multiple solutions or not, by default False If\n", " | False the return will be a FragmentationResult object, if True the\n", " | return will be a list of FragmentationResult objects.\n", " | search_nonoptimal : bool, optional\n", " | If True, the solver will search for non-optimal solutions along\n", " | with the optimal ones. This is useful when the user wants to find\n", " | all possible combinations of fragments that cover the universe. By\n", " | default False. If `search_multiple_solutions` is False, this\n", " | parameter will be ignored.\n", " | solver_arguments : dict, optional\n", " | Dictionary with the arguments to be passed to the solver. For the\n", " | DefaultSolver of ugropy you can change de PulP solver passing a\n", " | dictionary like {\"solver\": \"PULP_CBC_CMD\"} and change the PulP\n", " | solver. If empty it will use the default solver arguments, by\n", " | default {}.\n", " |\n", " | Returns\n", " | -------\n", " | Union[FragmentationResult, List[FragmentationResult]]\n", " | Fragmentation result. If search_multiple_solutions is False the\n", " | return will be a FragmentationResult object, if True the return\n", " | will be a list of FragmentationResult objects.\n", " |\n", " | mol_preprocess(self, mol: rdkit.Chem.rdchem.Mol) -> rdkit.Chem.rdchem.Mol\n", " | Preprocess the molecule.\n", " |\n", " | This method is called before the detection of the fragments. It can be\n", " | used to preprocess the molecule before the detection of the fragments.\n", " | This allow to use RDKit functions to preprocess the molecule and make\n", " | your SMARTS detection easier. The default implementation does nothing\n", " | and leave the mol object as it is. You can inherit this class and\n", " | override this method to preprocess the molecule.\n", " |\n", " | Parameters\n", " | ----------\n", " | mol : Chem.rdchem.Mol\n", " | Molecule to preprocess.\n", " |\n", " | Returns\n", " | -------\n", " | Chem.rdchem.Mol\n", " | Preprocessed molecule.\n", " |\n", " | set_fragmentation_result(self, molecule: rdkit.Chem.rdchem.Mol, solutions_fragments: List[dict], search_multiple_solutions: bool = False, **kwargs) -> Union[ugropy.core.frag_classes.base.fragmentation_result.FragmentationResult, List[ugropy.core.frag_classes.base.fragmentation_result.FragmentationResult]]\n", " | Process the solutions and return the FragmentationResult objects.\n", " |\n", " | Parameters\n", " | ----------\n", " | molecule : Chem.rdchem.Mol\n", " | Rdkit mol object.\n", " | solutions_fragments : List[dict]\n", " | Fragments detected in the molecule.\n", " | search_multiple_solutions : bool, optional\n", " | Whether search for multiple solutions or not, by default False\n", " |\n", " | Returns\n", " | -------\n", " | Union[FragmentationResult, List[FragmentationResult]]\n", " | List of FragmentationResult objects.\n", " |\n", " | ----------------------------------------------------------------------\n", " | Data descriptors defined here:\n", " |\n", " | __dict__\n", " | dictionary for instance variables\n", " |\n", " | __weakref__\n", " | list of weak references to the object\n", "\n" ] } ], "source": [ "from ugropy import FragmentationModel\n", "\n", "help(FragmentationModel)" ] }, { "cell_type": "markdown", "id": "f33b42dc", "metadata": {}, "source": [ "You can instantiate a base `FragmentationModel` class with the minimum\n", "required information.\n", "\n", "This class expects a pandas DataFrame (`subgroups` parameter) that contains a \n", "specific index and a mandatory column. The index, named `group`, contains the \n", "names of the fragments, and the column, named `smarts`, contains the SMARTS \n", "patterns of the fragments. \n", "\n", "The class also accepts a boolean parameter called `allow_overlapping`, which \n", "indicates whether the model allows the detected fragments within the molecule \n", "to overlap. Similarly, the `allow_free_atoms` argument indicates whether the \n", "model allows free atoms (atoms not occupied by any group). Finally, it requires \n", "a `FragmentationResult` class; by default, the base `FragmentationResult` \n", "class is used.\n", "\n", "In the \"Getting Started - About the Algorithm\" section of the tutorial, we\n", "defined some models by identifying the fragments directly with the RDKit library. \n", "Now, let's achieve the same result using the `FragmentationModel` class.\n", "\n", "The fragments that we previously defined were:\n", "\n", "```python\n", "# Definition of the fragments of our model\n", "\n", "# Aliphatic CH2\n", "ch2 = Chem.MolFromSmarts(\"[CX4H2]\")\n", "\n", "# Aromatic CH\n", "ach = Chem.MolFromSmarts(\"[cH]\")\n", "\n", "# Aromatic C without H\n", "ac = Chem.MolFromSmarts(\"[cH0]\")\n", "\n", "# Aromatic C bonded with aliphatic CH2\n", "acch2 = Chem.MolFromSmarts(\"[cH0][CX4H2]\")\n", "\n", "# List of fragments of our model\n", "fragments = [ch2, ach, ac, acch2]\n", "fragments_names = [\"CH2\", \"ACH\", \"AC\", \"ACCH2\"]\n", "```\n", "\n", "Let's build a DataFrame with this information (later, you can store it as a\n", ".csv file and load it with pandas to reinstantiate the model):" ] }, { "cell_type": "code", "execution_count": 57, "id": "a6038596", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
smarts
group
CH2[CX4H2]
ACH[cH]
AC[cH0]
ACCH2[cH0][CX4H2]
\n", "
" ], "text/plain": [ " smarts\n", "group \n", "CH2 [CX4H2]\n", "ACH [cH]\n", "AC [cH0]\n", "ACCH2 [cH0][CX4H2]" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "\n", "from ugropy import FragmentationModel, FragmentationResult\n", "\n", "\n", "subgroups = pd.DataFrame(\n", " {\n", " \"group\": [\"CH2\", \"ACH\", \"AC\", \"ACCH2\"],\n", " \"smarts\": [\"[CX4H2]\", \"[cH]\", \"[cH0]\", \"[cH0][CX4H2]\"],\n", " },\n", ")\n", "\n", "subgroups.set_index(\"group\", inplace=True)\n", "\n", "subgroups" ] }, { "cell_type": "markdown", "id": "545ad6d7", "metadata": {}, "source": [ "Now, let's instantiate our model:" ] }, { "cell_type": "code", "execution_count": 58, "id": "e7fb4202", "metadata": {}, "outputs": [], "source": [ "our_model = FragmentationModel(\n", " subgroups=subgroups,\n", " allow_overlapping=False,\n", " allow_free_atoms=False,\n", " fragmentation_result=FragmentationResult\n", ")" ] }, { "cell_type": "markdown", "id": "2c71d0c6", "metadata": {}, "source": [ "We can use this model to fragment a molecule in the same way we used the other\n", "`ugropy` models. The result will be a FragmentationResult instance (you can\n", "check the API documentation for more details on this class). Let's test it with\n", "the same molecule we used in the \"About the Algorithm\" section of the tutorial." ] }, { "cell_type": "code", "execution_count": 59, "id": "49e98e67", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "ACH: 10AC: 1ACCH2: 1" ], "text/plain": [ "" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result = our_model.get_groups(\"c1ccccc1Cc2ccccc2\", \"smiles\")\n", "\n", "result.draw(width=600)" ] }, { "cell_type": "markdown", "id": "f2344341", "metadata": {}, "source": [ "This returns the result as a dictionary of group occurrences, using the names \n", "we defined in our DataFrame as keys:" ] }, { "cell_type": "code", "execution_count": 60, "id": "454e95f0", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'ACH': 10, 'AC': 1, 'ACCH2': 1}" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result.subgroups" ] }, { "cell_type": "markdown", "id": "e4084a46", "metadata": {}, "source": [ "The specific molecule atoms covered by each fragment can be accessed via the \n", "`subgroups_atoms` attribute of the `FragmentationResult` instance. This \n", "attribute is a dictionary where the keys are the fragment names, and the values \n", "are lists of lists containing the atom indices covered by each occurrence. \n", "Consequently, the number of nested lists matches the total occurrences of \n", "that fragment in the molecule." ] }, { "cell_type": "code", "execution_count": 61, "id": "fde814c2", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'ACH': [(0,), (1,), (2,), (3,), (4,), (8,), (9,), (10,), (11,), (12,)],\n", " 'AC': [(5,)],\n", " 'ACCH2': [(7, 6)]}" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result.subgroups_atoms" ] }, { "cell_type": "code", "execution_count": 62, "id": "66331c0a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "ugropy.core.frag_classes.base.fragmentation_result.FragmentationResult" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(result)" ] }, { "cell_type": "markdown", "id": "a91665f9", "metadata": {}, "source": [ "Since we did not allow overlapping in the previous example, the algorithm found\n", "the optimal solution, ensuring that each atom of the molecule was covered by\n", "only one fragment (while using the minimum number of groups).\n", "\n", "Let's see what happens if we allow overlapping:" ] }, { "cell_type": "code", "execution_count": 63, "id": "77da9d26", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'CH2': 1, 'ACH': 10, 'AC': 2, 'ACCH2': 2}\n", "{'CH2': [(6,)], 'ACH': [(0,), (1,), (2,), (3,), (4,), (8,), (9,), (10,), (11,), (12,)], 'AC': [(5,), (7,)], 'ACCH2': [(5, 6), (7, 6)]}\n" ] } ], "source": [ "our_model_olap = FragmentationModel(\n", " subgroups=subgroups,\n", " allow_overlapping=True,\n", " allow_free_atoms=False,\n", " fragmentation_result=FragmentationResult\n", ")\n", "\n", "result_overlapping = our_model_olap.get_groups(\"c1ccccc1Cc2ccccc2\", \"smiles\")\n", "\n", "print(result_overlapping.subgroups)\n", "print(result_overlapping.subgroups_atoms)" ] }, { "cell_type": "markdown", "id": "e867ce27", "metadata": {}, "source": [ "As you can see, because overlapping was enabled, the algorithm directly\n", "returned all detected fragments in the molecule without searching for an\n", "optimal selection. Consequently, some atoms are now covered by multiple\n", "fragments.\n", "\n", "Let's inspect the internal attributes of our `our_model` instance. First, we\n", "can access the same parameters we specified during instantiation. Since these\n", "are attributes of the base class, they are available across all models in\n", "`ugropy`." ] }, { "cell_type": "code", "execution_count": 64, "id": "91349718", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Fragments of the model:\n", " smarts\n", "group \n", "CH2 [CX4H2]\n", "ACH [cH]\n", "AC [cH0]\n", "ACCH2 [cH0][CX4H2]\n", "Allow overlapping: False\n", "Allow free atoms: False\n", "Fragmentation result class: \n" ] } ], "source": [ "print(\"Fragments of the model:\")\n", "print(our_model.subgroups)\n", "print(\"Allow overlapping:\", our_model.allow_overlapping)\n", "print(\"Allow free atoms:\", our_model.allow_free_atoms)\n", "print(\"Fragmentation result class:\", our_model.fragmentation_result)" ] }, { "cell_type": "markdown", "id": "1acd97cf", "metadata": {}, "source": [ "We have an additional, and important, attribute called `detection_mols`:" ] }, { "cell_type": "code", "execution_count": 65, "id": "4edc8a8b", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'CH2': ,\n", " 'ACH': ,\n", " 'AC': ,\n", " 'ACCH2': }" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "our_model.detection_mols" ] }, { "cell_type": "markdown", "id": "8faa5ab9", "metadata": {}, "source": [ "When you instantiate a model, during initialization, all the fragments defined\n", "in the DataFrame are used to create a dictionary. This dictionary contains the\n", "fragment names as keys, and the corresponding RDKit Mol objects as values,\n", "which are created internally as:\n", "\n", "```python\n", "from rdkit import Chem\n", "\n", "mol = Chem.MolFromSmarts(smarts)\n", "```\n", "\n", "For this reason, all the SMARTS patterns we define must be compatible with the\n", "`RDKit` library. This attribute is used internally by the `get_groups` method\n", "to search for fragments within the molecule. Pre-building these objects avoids\n", "recreating the `RDKit` `Mol` instances every time `get_groups` is called,\n", "significantly optimizing execution time.\n", "\n", "As mentioned before, these are the attributes common to any\n", "`FragmentationModel` subclass, but specific subclasses can implement additional\n", "attributes. For example, an instance of the `GibbsModel` class possesses all\n", "the core attributes we just explored, plus several others:" ] }, { "cell_type": "code", "execution_count": 66, "id": "d44d345a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Allow overlapping: False\n", "Allow free atoms: False\n", "Fragmentation result class: \n", "Detection mol objects: {'CH3': , 'CH2': , 'CH': , 'C': , 'CH2=CH': , 'CH=CH': , 'CH2=C': , 'CH=C': , 'ACH': , 'AC': , 'ACCH3': , 'ACCH2': , 'ACCH': , 'OH': , 'CH3OH': , 'H2O': , 'ACOH': , 'CH3CO': , 'CH2CO': , 'HCO': , 'CH3COO': , 'CH2COO': , 'HCOO': , 'CH3O': , 'CH2O': , 'CHO': , 'THF': , 'CH3NH2': , 'CH2NH2': , 'CHNH2': , 'CH3NH': , 'CH2NH': , 'CHNH': , 'CH3N': , 'CH2N': , 'ACNH2': , 'C5H5N': , 'C5H4N': , 'C5H3N': , 'CH3CN': , 'CH2CN': , 'COOH': , 'HCOOH': , 'CH2CL': , 'CHCL': , 'CCL': , 'CH2CL2': , 'CHCL2': , 'CCL2': , 'CHCL3': , 'CCL3': , 'CCL4': , 'ACCL': , 'CH3NO2': , 'CH2NO2': , 'CHNO2': , 'ACNO2': , 'CS2': , 'CH3SH': , 'CH2SH': , 'FURFURAL': , 'DOH': , 'I': , 'BR': , 'CH=-C': , 'C=-C': , 'DMSO': , 'ACRY': , 'CL-(C=C)': , 'C=C': , 'ACF': , 'DMF': , 'HCON(CH2)2': , 'CF3': , 'CF2': , 'CF': , 'COO': , 'SIH3': , 'SIH2': , 'SIH': , 'SI': , 'SIH2O': , 'SIHO': , 'SIO': , 'NMP': , 'CCL3F': , 'CCL2F': , 'HCCL2F': , 'HCCLF': , 'CCLF2': , 'HCCLF2': , 'CCLF3': , 'CCL2F2': , 'AMH2': , 'AMHCH3': , 'AMHCH2': , 'AM(CH3)2': , 'AMCH3CH2': , 'AM(CH2)2': , 'C2H5O2': , 'C2H4O2': , 'CH3S': , 'CH2S': , 'CHS': , 'MORPH': , 'C4H4S': , 'C4H3S': , 'C4H2S': , 'NCO': , '(CH2)2SU': , 'CH2CHSU': , 'IMIDAZOL': , 'BTI': }\n" ] } ], "source": [ "from ugropy import unifac\n", "\n", "# Commented out to avoid printing a large DataFrame\n", "# print(\"Fragments of the model:\", unifac.subgroups)\n", "\n", "print(\"Allow overlapping:\", unifac.allow_overlapping)\n", "print(\"Allow free atoms:\", unifac.allow_free_atoms)\n", "print(\"Fragmentation result class:\", unifac.fragmentation_result)\n", "print(\"Detection mol objects:\", unifac.detection_mols)" ] }, { "cell_type": "markdown", "id": "5a565e89", "metadata": {}, "source": [ "Another example is the `JobackModel` class, which shares the same attributes \n", "as the base class but also includes an additional attribute called \n", "`properties_contributions`. This attribute contains the contribution of each \n", "fragment to the various Joback properties." ] }, { "cell_type": "code", "execution_count": 67, "id": "9661ee78", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Allow overlapping: False\n", "Allow free atoms: False\n", "Fragmentation result class: \n", "Detection mol objects: {'-CH3': , '-CH2-': , '>CH-': , '>C<': , '=CH2': , '=CH-': , '=C<': , '=C=': , 'CH': , 'C': , 'ring-CH2-': , 'ring>CH-': , 'ring>C<': , 'ring=CH-': , 'ring=C<': , '-F': , '-Cl': , '-Br': , '-I': , '-OH (alcohol)': , '-OH (phenol)': , '-O- (non-ring)': , '-O- (ring)': , '>C=O (non-ring)': , '>C=O (ring)': , 'O=CH- (aldehyde)': , '-COOH (acid)': , '-COO- (ester)': , '=O (other than above)': , '-NH2': , '>NH (non-ring)': , '>NH (ring)': , '>N- (non-ring)': , '-N= (non-ring)': , '-N= (ring)': , '=NH': , '-CN': , '-NO2': , '-SH': , '-S- (non-ring)': , '-S- (ring)': }\n" ] } ], "source": [ "from ugropy import joback\n", "\n", "# Commented out to avoid printing a large DataFrame\n", "# print(\"Fragments of the model:\", joback.subgroups)\n", "\n", "print(\"Allow overlapping:\", joback.allow_overlapping)\n", "print(\"Allow free atoms:\", joback.allow_free_atoms)\n", "print(\"Fragmentation result class:\", joback.fragmentation_result)\n", "print(\"Detection mol objects:\", joback.detection_mols)\n", "\n", "# Commented out to avoid printing a large DataFrame\n", "# print(\"Properties contributions:\", joback.properties_contributions)" ] }, { "cell_type": "markdown", "id": "c7ea99c5", "metadata": {}, "source": [ "Please refer to the API documentation of each model for more information about\n", "the parameters, attributes, and methods available for each specific class." ] }, { "cell_type": "markdown", "id": "1992a4a2", "metadata": {}, "source": [ "### Changing the behavior of an existing model" ] }, { "cell_type": "markdown", "id": "6ea2ac55", "metadata": {}, "source": [ "In certain situations, you might want to alter the behavior of one or a few \n", "fragments within an existing `ugropy` model. Naturally, modifying the behavior \n", "of those specific fragments does not justify creating an entirely new model \n", "from scratch.\n", "\n", "This section is inspired by the following `ugropy` GitHub issue:\n", "\n", "[https://github.com/ipqa-research/ugropy/issues/41](https://github.com/ipqa-research/ugropy/issues/41)\n", "\n", "Although the built-in models in `ugropy` are not intended to be directly mutated \n", "by the user, we can easily leverage the data inside the model's attributes \n", "to instantiate a new one with the desired modifications.\n", "\n", "In that GitHub issue, the user wanted to modify the behavior of the `ACNH2`\n", "fragment within the UNIFAC model. Specifically, they wanted to enable the \n", "`ACNH2` fragment to match both `ACNH2` and `ACNH` structures. First, let's \n", "inspect how the SMARTS pattern for `ACNH2` is originally defined in the UNIFAC \n", "model:" ] }, { "cell_type": "code", "execution_count": 68, "id": "f9825d13", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'[cH0][NH2]'" ] }, "execution_count": 68, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from ugropy import unifac\n", "\n", "unifac.subgroups.loc[\"ACNH2\", \"smarts\"]" ] }, { "cell_type": "markdown", "id": "d4155e8f", "metadata": {}, "source": [ "As you can observe, the SMARTS pattern for `ACNH2` is defined as `[cH0][NH2]`\n", "(an aromatic carbon without hydrogen bonded to a nitrogen with two hydrogens).\n", "The molecule provided by the user in the GitHub issue was:\n", "\n", "SMILES: CC(=O)NC1=CC=C(O)C=C1\n", "\n", "As currently defined in the library, the UNIFAC model will not detect the\n", "`ACNH2` fragment in this molecule because the actual structure present is an\n", "`ACNH` group (an aromatic carbon without hydrogen bonded to a nitrogen with\n", "only one hydrogen). Furthermore, the standard UNIFAC model does not provide an\n", "`ACNH` fragment in its original literature. Let's check what happens:" ] }, { "cell_type": "code", "execution_count": 69, "id": "fe0c39c3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{}\n" ] } ], "source": [ "result = unifac.get_groups(\"CC(=O)NC1=CC=C(O)C=C1\", \"smiles\")\n", "\n", "print(result.subgroups)" ] }, { "cell_type": "code", "execution_count": 70, "id": "23efe947", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result.draw(width=600)" ] }, { "cell_type": "markdown", "id": "19031b39", "metadata": {}, "source": [ "As expected, `ugropy` fails to obtain the fragmentation of the molecule because \n", "the `NH` group is not covered by any available fragment, leaving free atoms \n", "unaccounted for.\n", "\n", "First, let's leverage our knowledge from the previous section to retrieve the \n", "complete data from the UNIFAC model's attributes.\n", "\n", "First, the SMARTS DataFrame:" ] }, { "cell_type": "code", "execution_count": 71, "id": "13105a81", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
smartsmolecular_weight
group
CH3[CX4H3]15.03500
CH2[CX4H2]14.02700
CH[CX4H]13.01900
C[CX4H0]12.01100
CH2=CH[CH2]=[CH]27.04600
.........
NCO[NX2H0]=[CX2H0]=[OX1H0]42.01700
(CH2)2SU[CH2]S(=O)(=O)[CH2]92.11620
CH2CHSU[CH2]S(=O)(=O)[CH]91.10840
IMIDAZOL[c]1:[c]:[n]:[c]:[n]:168.07820
BTIC(F)(F)(F)S(=O)(=O)[N-]S(=O)(=O)C(F)(F)F279.91784
\n", "

113 rows × 2 columns

\n", "
" ], "text/plain": [ " smarts molecular_weight\n", "group \n", "CH3 [CX4H3] 15.03500\n", "CH2 [CX4H2] 14.02700\n", "CH [CX4H] 13.01900\n", "C [CX4H0] 12.01100\n", "CH2=CH [CH2]=[CH] 27.04600\n", "... ... ...\n", "NCO [NX2H0]=[CX2H0]=[OX1H0] 42.01700\n", "(CH2)2SU [CH2]S(=O)(=O)[CH2] 92.11620\n", "CH2CHSU [CH2]S(=O)(=O)[CH] 91.10840\n", "IMIDAZOL [c]1:[c]:[n]:[c]:[n]:1 68.07820\n", "BTI C(F)(F)(F)S(=O)(=O)[N-]S(=O)(=O)C(F)(F)F 279.91784\n", "\n", "[113 rows x 2 columns]" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "subgroups = unifac.subgroups.copy()\n", "\n", "subgroups" ] }, { "cell_type": "markdown", "id": "73918bb7", "metadata": {}, "source": [ "Since UNIFAC is a `GibbsModel`, we also need to retrieve the fragments\n", "information to instantiate a new model:" ] }, { "cell_type": "code", "execution_count": 72, "id": "a6f62062", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
subgroup_numbermain_groupRQ
group
CH3110.90110.848
CH2210.67440.540
CH310.44690.228
C410.21950.000
CH2=CH521.34541.176
...............
NCO109511.05670.732
(CH2)2SU118552.68692.120
CH2CHSU119552.45951.808
IMIDAZOL178842.02600.868
BTI179855.77404.932
\n", "

113 rows × 4 columns

\n", "
" ], "text/plain": [ " subgroup_number main_group R Q\n", "group \n", "CH3 1 1 0.9011 0.848\n", "CH2 2 1 0.6744 0.540\n", "CH 3 1 0.4469 0.228\n", "C 4 1 0.2195 0.000\n", "CH2=CH 5 2 1.3454 1.176\n", "... ... ... ... ...\n", "NCO 109 51 1.0567 0.732\n", "(CH2)2SU 118 55 2.6869 2.120\n", "CH2CHSU 119 55 2.4595 1.808\n", "IMIDAZOL 178 84 2.0260 0.868\n", "BTI 179 85 5.7740 4.932\n", "\n", "[113 rows x 4 columns]" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "subgroups_info = unifac.subgroups_info.copy()\n", "\n", "subgroups_info" ] }, { "cell_type": "markdown", "id": "1edc502a", "metadata": {}, "source": [ "Now, lets modify the SMARTS pattern of the `ACNH2` fragment to match both\n", "`ACNH2` and `ACNH` structures and instantiate a new model with the modified\n", "SMARTS pattern:" ] }, { "cell_type": "code", "execution_count": 73, "id": "6bca132e", "metadata": {}, "outputs": [], "source": [ "from ugropy import GibbsModel\n", "\n", "# Change directly the SMARTS column for the ACNH2 fragment\n", "# now the aromatic carbon could be bonded to either NH2 or NH.\n", "subgroups.loc[\"ACNH2\", \"smarts\"] = \"[cH0][NH2,NH]\"\n", "\n", "new_unifac = GibbsModel(\n", " subgroups=subgroups,\n", " subgroups_info=subgroups_info,\n", " calculate_r_q=True\n", ")" ] }, { "cell_type": "markdown", "id": "bce617ef", "metadata": {}, "source": [ "Now, lets try to fragment the same molecule with our modified UNIFAC model:" ] }, { "cell_type": "code", "execution_count": 74, "id": "9ec07b44", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'ACH': 4, 'ACOH': 1, 'CH3CO': 1, 'ACNH2': 1}\n" ] } ], "source": [ "result = new_unifac.get_groups(\"CC(=O)NC1=CC=C(O)C=C1\", \"smiles\")\n", "\n", "print(result.subgroups)" ] }, { "cell_type": "code", "execution_count": 75, "id": "882156ee", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "ACH: 4ACOH: 1CH3CO: 1ACNH2: 1" ], "text/plain": [ "" ] }, "execution_count": 75, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result.draw(width=600)" ] }, { "cell_type": "markdown", "id": "428fe821", "metadata": {}, "source": [ "Success! Now, the `ACNH` structure present in the molecule is successfully\n", "detected under the `ACNH2` fragment definition." ] }, { "cell_type": "markdown", "id": "3b356aa7", "metadata": {}, "source": [ "### Understanding which fragment is not being detected" ] }, { "cell_type": "markdown", "id": "eaae747c", "metadata": {}, "source": [ "There is an additional technique available for all models that helps you \n", "determine whether a specific fragment is being successfully detected within a \n", "molecule. This short section serves as a diagnostic bridge between modifying an \n", "existing model and creating your own from scratch.\n", "\n", "To explore this, we can use the `instantiate_mol_object` function from\n", "`ugropy`. This function processes any of the molecular identifiers supported by\n", "the `get_groups` method to return an RDKit Mol object.\n", "\n", "Additionally, all `FragmentationModel` instances implement the\n", "`detect_fragments` method. While this method is typically executed internally\n", "during the `get_groups` call, we can call it explicitly to inspect which\n", "fragments are captured during the initial direct detection step of the\n", "algorithm.\n", "\n", "Let's check the `instantiate_mol_object` docstring:" ] }, { "cell_type": "code", "execution_count": 76, "id": "41a1563a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on function instantiate_mol_object in module ugropy.core.get_rdkit_object:\n", "\n", "instantiate_mol_object(identifier: Union[str, rdkit.Chem.rdchem.Mol], identifier_type: str = 'name') -> rdkit.Chem.rdchem.Mol\n", " Instantiate a RDKit Mol object from molecule's name, SMILES or mol.\n", "\n", " In case that the input its already a RDKit Mol object, the function will\n", " return the input object.\n", "\n", " Parameters\n", " ----------\n", " identifier : str or rdkit.Chem.rdchem.Mol\n", " Identifier of a molecule (name, SMILES or rdkit.Chem.rdchem.Mol).\n", " Example: hexane or CCCCCC for name or SMILES respectively.\n", " identifier_type : str, optional\n", " Use 'name' to search a molecule by name, 'smiles' to provide the\n", " molecule SMILES representation or 'mol' to provide a\n", " rdkit.Chem.rdchem.Mol object, by default \"name\".\n", "\n", " Returns\n", " -------\n", " rdkit.Chem.rdchem.Mol\n", " RDKit Mol object.\n", "\n" ] } ], "source": [ "from ugropy import instantiate_mol_object\n", "\n", "help(instantiate_mol_object)" ] }, { "cell_type": "markdown", "id": "0d651346", "metadata": {}, "source": [ "Now, let's test this with the molecule from the previous example, comparing the\n", "original UNIFAC model against our modified version (`new_unifac`). First, using\n", "the original model:" ] }, { "cell_type": "code", "execution_count": 77, "id": "363db743", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'CH3_0': (0,),\n", " 'ACH_0': (5,),\n", " 'ACH_1': (6,),\n", " 'ACH_2': (9,),\n", " 'ACH_3': (10,),\n", " 'AC_0': (4,),\n", " 'AC_1': (7,),\n", " 'OH_0': (8,),\n", " 'ACOH_0': (7, 8),\n", " 'CH3CO_0': (0, 1, 2)}" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mol = instantiate_mol_object(\"CC(=O)NC1=CC=C(O)C=C1\", \"smiles\")\n", "\n", "unifac.detect_fragments(mol)" ] }, { "cell_type": "markdown", "id": "d5f5b3b2", "metadata": {}, "source": [ "As you can observe, the `ACNH2` fragment is missing from the detections. Now, \n", "let's run the same check using our modified UNIFAC instance:" ] }, { "cell_type": "code", "execution_count": 78, "id": "2f9164bd", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'CH3_0': (0,),\n", " 'ACH_0': (5,),\n", " 'ACH_1': (6,),\n", " 'ACH_2': (9,),\n", " 'ACH_3': (10,),\n", " 'AC_0': (4,),\n", " 'AC_1': (7,),\n", " 'OH_0': (8,),\n", " 'ACOH_0': (7, 8),\n", " 'CH3CO_0': (0, 1, 2),\n", " 'ACNH2_0': (4, 3)}" ] }, "execution_count": 78, "metadata": {}, "output_type": "execute_result" } ], "source": [ "new_unifac.detect_fragments(mol)" ] }, { "cell_type": "markdown", "id": "7d9709d7", "metadata": {}, "source": [ "Now, the `ACNH2` fragment is successfully detected. \n", "\n", "The numbers inside each tuple represent the atom indices occupied by that specific \n", "detection. The numeric suffix of each fragment key indicates the distinct occurrences \n", "of that fragment type. For example:\n", "\n", "- ACH_**0**: (5,)\n", "\n", "- ACH_**1**: (6,)\n", "\n", "- ACH_**2**: (9,)\n", "\n", "- ACH_**3**: (10,)\n", "\n", "This indicates that our molecule contains four total `ACH` fragments, each \n", "occupying different atoms (note that implicit hydrogens are never counted as independent \n", "atoms in the RDKit library)." ] }, { "cell_type": "markdown", "id": "1319da4b", "metadata": {}, "source": [ "### User defined fragmentation models" ] }, { "cell_type": "markdown", "id": "96cc84d6", "metadata": {}, "source": [ "This section will be brief, as it involves advanced Python concepts that are \n", "beyond the scope of this tutorial and will not be explained from scratch.\n", "\n", "If you want to create your own specialized category of `FragmentationModel`, \n", "you need to master two key elements. First, you must learn the SMARTS notation \n", "to define your fragments (covered as a brief introduction in the next section). \n", "Second, you need to understand how to extend the behavior of the base \n", "`FragmentationModel` and `FragmentationResult` classes via inheritance:\n", "\n", "```python\n", "from ugropy import FragmentationModel, FragmentationResult\n", "\n", "\n", "class MyFragModel(FragmentationModel):\n", " ...\n", "\n", "\n", "class MyFragModelResult(FragmentationResult):\n", " ...\n", "```\n", "\n", "Maybe you want to create a model that only fragments the molecules without\n", "doing anything else. In that case, you can simply instantiate the base\n", "`FragmentationModel` class with the required information as we have seen in the\n", "previous section: \"Understanding model instances and their configuration\".\n", "\n", "On the other hand, maybe you want to create a model that, after detecting the\n", "fragments, performs additional operations with them, such as property\n", "estimations. The best approach at this point is to check the `ugropy` source\n", "code and learn from it directly (it is not that much code, I promise!).\n", "\n", "First, explore the two base classes to understand their core architecture:\n", "\n", "- [FragmentationModel](https://github.com/ipqa-research/ugropy/blob/main/ugropy/core/frag_classes/base/fragmentation_model.py)\n", "- [FragmentationResult](https://github.com/ipqa-research/ugropy/blob/main/ugropy/core/frag_classes/base/fragmentation_result.py)\n", "\n", "Then, you can look at a straightforward extension of the base class, the\n", "`GibbsModel` and its corresponding result class:\n", "\n", "- [GibbsModel](https://github.com/ipqa-research/ugropy/blob/main/ugropy/core/frag_classes/gibbs_model/gibbs_model.py)\n", "- [GibbsResult](https://github.com/ipqa-research/ugropy/blob/main/ugropy/core/frag_classes/gibbs_model/gibbs_result.py)\n", "\n", "In the `GibbsModel` definition, you will see how the `__init__` method is\n", "**overridden** to customize its docstring and incorporate new parameters.\n", "Moreover, additional validation filters are implemented in this subclass (while\n", "those already present in `FragmentationModel` are automatically inherited). In\n", "`GibbsResult`, you can check how the calculation of the $R$ and $Q$ values is\n", "triggered once the fragmentation result is received.\n", "\n", "Finally, you can inspect a more complex implementation, specifically its result\n", "class, `JobackResult`. While the underlying logic remains the same, it serves\n", "as a more advanced example that demonstrates how `ugropy` internally integrates\n", "the `Pint` library for unit management:\n", "\n", "- [JobackFragmentationResult](https://github.com/ipqa-research/ugropy/blob/main/ugropy/core/frag_classes/joback/joback_result.py)\n", "\n", "Every class definition is available in the repository, providing a clear\n", "blueprint to build your own custom models.\n", "\n", "Finally, there is an optional method in the `FragmentationModel` base class \n", "that we haven't discussed yet: `mol_preprocess`.\n", "\n", "This method is executed internally during the `get_groups` call. The algorithm\n", "first creates the RDKit Mol object via `instantiate_mol_object` and then passes\n", "that object directly to `mol_preprocess`. By default, this method returns the\n", "molecule unchanged. However, if you inherit from the base class, you can\n", "**override** it to leverage RDKit's full capabilities to modify the nature of\n", "the molecule before any fragment detection takes place. For instance, you could\n", "force specific rings to be considered aromatic (or non-aromatic), sanitize\n", "functional groups, or perform advanced structural manipulations tailored to\n", "your needs.\n", "\n", "That being said, for the majority of use cases, you won't need to touch this\n", "method. Most fragmentation challenges can be resolved simply by defining your\n", "SMARTS patterns correctly!" ] }, { "cell_type": "markdown", "id": "88b58144", "metadata": {}, "source": [ "### SMARTS tutorial" ] }, { "cell_type": "markdown", "id": "78b73f7b", "metadata": {}, "source": [ "This is the final piece of the puzzle you need to master to define your own \n", "fragmentation models. Before diving in, a quick word of caution: this is not a \n", "trivial task. It requires not only a solid grasp of the SMARTS syntax but also \n", "an understanding of how fragment definitions can be deeply dependent on the \n", "thermodynamic model itself (we will explore some examples of this later).\n", "\n", "This brief tutorial is based on the official Daylight documentation, where you \n", "can find all the fundamental directives of the SMARTS syntax:\n", "\n", "- [Daylight SMARTS Theory](https://www.daylight.com/dayhtml/doc/theory/theory.smarts.html)\n", "\n", "Additionally, RDKit supports certain extended SMARTS features, such as Chemaxon\n", "extended SMARTS link nodes, which can be incredibly useful for complex\n", "macro-structures:\n", "\n", "- [Chemaxon Extended SMARTS](https://docs.chemaxon.com/latest/formats_chemaxon-extended-smiles-and-smarts-cxsmiles-and-cxsmarts.html)\n", "\n", "The first golden rule is: **you must strictly follow the SMARTS syntax that\n", "RDKit understands**. Furthermore, you can inspect the production-ready SMARTS\n", "definitions for all built-in models directly in the `ugropy` repository. While\n", "perhaps not exhaustive, they serve as a learning resource:\n", "\n", "- [Groups CSV in Repository](https://github.com/ipqa-research/ugropy/tree/main/ugropy/groupscsv)\n", "\n", "If you want to open them on excel/LibreOffice, you can download the CSV files\n", "directly from the repository and open them with your preferred spreadsheet\n", "software. The column separator is the character `|` (sorry, I didn't like\n", "spaces and all other characters are already used in the SMARTS syntax). Also,\n", "you may find the character `?` at the beginning of some SMARTS patterns. This\n", "character is used to indicate commented lines, which are ignored.\n", "\n", "Ultimately, the performance of your custom model will be strictly dictated by\n", "how precisely you define your fragments, defining \"performance\" here as: the\n", "model detects the exact fragments I want it to detect for this molecule. For\n", "that, testing is crucial (refer to the test book to find some examples of\n", "molecules with their SMILES representations)." ] }, { "cell_type": "markdown", "id": "9699554f", "metadata": {}, "source": [ "#### The basics\n", "\n", "In SMARTS (as in SMILES notation), we define chemical structures using specific \n", "structural or logical patterns. These structures are read and evaluated from \n", "left to right. For example, consider the n-hexane molecule:" ] }, { "cell_type": "code", "execution_count": 79, "id": "76472d49", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from rdkit import Chem\n", "\n", "smt = Chem.MolFromSmarts(\"CCCCCC\")\n", "\n", "smt" ] }, { "cell_type": "markdown", "id": "fd2aefb3", "metadata": {}, "source": [ "Here, we are defining six aliphatic carbons \"bonded\" one after the other. I\n", "emphasize \"bonded\" because we are not explicitly specifying the type of bond\n", "yet. Let's explicitly define that these connections are single bonds:" ] }, { "cell_type": "code", "execution_count": 80, "id": "cd595aef", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 80, "metadata": {}, "output_type": "execute_result" } ], "source": [ "smt = Chem.MolFromSmarts(\"C-C-C-C-C-C\")\n", "\n", "smt" ] }, { "cell_type": "markdown", "id": "a7410438", "metadata": {}, "source": [ "See how the drawing changes? Now we have explicitly defined six aliphatic\n", "carbons connected by single bonds.\n", "\n", "Let's add a double bond in the middle:" ] }, { "cell_type": "code", "execution_count": 81, "id": "d6c88f65", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" } ], "source": [ "smt = Chem.MolFromSmarts(\"C-C-C=C-C-C\")\n", "\n", "smt" ] }, { "cell_type": "markdown", "id": "6fb3c5c8", "metadata": {}, "source": [ "Now, a double bond is specified between positions 3 and 4. As a side note,\n", "implicit hydrohens are automatically accounted for in this simplified notation\n", "until the standard valence of the atom is satisfied.\n", "\n", "This approach feels very similar to writing standard SMILES. However, when\n", "defining robust SMARTS patterns for group contribution models, we usually\n", "need to enforce the exact connectivity of an atom and specify precisely how\n", "many hydrogens are bonded to it. Let's completely and explicitly define the\n", "n-hexane molecule using strict SMARTS syntax:" ] }, { "cell_type": "code", "execution_count": 82, "id": "fe6bc4cf", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 82, "metadata": {}, "output_type": "execute_result" } ], "source": [ "smt = Chem.MolFromSmarts(\"[CX4H3]-[CX4H2]-[CX4H2]-[CX4H2]-[CX4H2]-[CX4H3]\")\n", "\n", "smt" ] }, { "cell_type": "markdown", "id": "c997d8b4", "metadata": {}, "source": [ "Nothing seems to change in the visual representation, but we have introduced a\n", "lot of new notation. Let's break it down step by step. \n", "\n", "First, the brackets: in SMARTS notation, brackets `[]` indicate that an atom is\n", "being defined by specific logical properties or constraints. The structure\n", "`[CX4H3]` is telling the engine: \"This is an aliphatic carbon (`C`) bonded to\n", "four total atoms (`X4`), and exactly three of those four connections are\n", "hydrogens (`H3`, which sets the explicit hydrogen count).\"\n", "\n", "Similarly, with `[CX4H2]`, we are specifying an aliphatic carbon bonded to four\n", "total atoms, two of which must be hydrogens.\n", "\n", "Therefore, when we write `[CX4H3]-[CX4H2]`, we are saying—and pardon the\n", "redundancy: *\"An aliphatic carbon with a total connectivity of 4 and three\n", "hydrogens is bonded via a single covalent bond to an aliphatic carbon with a\n", "total connectivity of 4 and two hydrogens.\"*\n", "\n", "Let's define this small substructure (`[CX4H3]-[CX4H2]`) and search for it\n", "within the n-hexane molecule. Naturally, we should find exactly two\n", "occurrences:\n" ] }, { "cell_type": "code", "execution_count": 83, "id": "45c5e218", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Matches: ((0, 1), (5, 4))\n", "Number of matches: 2\n" ] } ], "source": [ "hexane = Chem.MolFromSmiles(\"CCCCCC\") # n-hexane\n", "\n", "smt = Chem.MolFromSmarts(\"[CX4H3]-[CX4H2]\")\n", "\n", "matches = hexane.GetSubstructMatches(smt)\n", "\n", "print(\"Matches:\", matches)\n", "print(\"Number of matches:\", len(matches))" ] }, { "cell_type": "markdown", "id": "b7127a83", "metadata": {}, "source": [ "As expected, we found two of these substructures at atom indices (0, 1) and (5,\n", "4). \n", "\n", "At this point, an attentive reader might think:\n", "\n", "\"Well, if I am already enforcing the connectivity of the carbons (`X4`) and\n", "the exact number of hydrogens, explicitly defining the single bond in this\n", "particular case seems redundant.\"\n", "\n", "And you would be absolutely right! In logical terms, these two definitions are\n", "completely equivalent:\n", "\n", "* `[CX4H3]-[CX4H2]`\n", "* `[CX4H3][CX4H2]`\n", "\n", "But be careful: if you don't restrict the total connectivity of an atom, it can\n", "lead to unexpected false positives. Let's analyze the pattern `[CH2]`. Here, we\n", "are enforcing the hydrogen count but leaving the total connectivity open. It\n", "works perfectly fine for n-hexane:" ] }, { "cell_type": "code", "execution_count": 84, "id": "593fb0fe", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "((1,), (2,), (3,), (4,))" ] }, "execution_count": 84, "metadata": {}, "output_type": "execute_result" } ], "source": [ "smt = Chem.MolFromSmarts(\"[CH2]\")\n", "\n", "hexane = Chem.MolFromSmiles(\"CCCCCC\") # n-hexane\n", "\n", "matches = hexane.GetSubstructMatches(smt)\n", "\n", "matches" ] }, { "cell_type": "markdown", "id": "04bfe5d3", "metadata": {}, "source": [ "However, let's see what happens when we test this exact same pattern against\n", "the propene molecule:" ] }, { "cell_type": "code", "execution_count": 85, "id": "9f99b016", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "((0,),)\n" ] }, { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "propene = Chem.MolFromSmiles(\"C=CC\") # propene\n", "\n", "smt = Chem.MolFromSmarts(\"[CH2]\")\n", "\n", "matches = propene.GetSubstructMatches(smt)\n", "\n", "print(matches)\n", "\n", "propene" ] }, { "cell_type": "markdown", "id": "399f352e", "metadata": {}, "source": [ "We found a detection! And of course we did: the `[CH2]` pattern simply asks for\n", "*any aliphatic carbon with exactly two hydrogens*. In propene, the terminal\n", "alkene carbon (position 2 or 0 depending on RDKit indexing) satisfies this\n", "exact condition. \n", "\n", "If your thermodynamic model needs to distinguish between an unreactive\n", "aliphatic alkane group and an olefinic group, a generic pattern like `[CH2]`\n", "will ruin your fragmentation parameters. This is precisely where the **SMARTS\n", "craftsmanship** comes into play. \n", "\n", "Let's design two distinct patterns to cleanly separate both cases:" ] }, { "cell_type": "code", "execution_count": 86, "id": "6092e06b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hexane alkane CH2 matches: ((1,), (2,), (3,), (4,))\n", "Hexane alkene CH2 matches: ()\n", "Propene alkane CH2 matches: ()\n", "Propene alkene CH2 matches: ((0,),)\n" ] } ], "source": [ "# Alkane CH2 (sp3 carbon bonded to 4 atoms total)\n", "alkane_ch2 = Chem.MolFromSmarts(\"[CX4H2]\")\n", "\n", "# Alkene CH2 (sp2 carbon bonded to 3 atoms total)\n", "alkene_ch2 = Chem.MolFromSmarts(\"[CX3H2]\") \n", "\n", "print(\"Hexane alkane CH2 matches:\", hexane.GetSubstructMatches(alkane_ch2))\n", "print(\"Hexane alkene CH2 matches:\", hexane.GetSubstructMatches(alkene_ch2))\n", "\n", "print(\"Propene alkane CH2 matches:\", propene.GetSubstructMatches(alkane_ch2))\n", "print(\"Propene alkene CH2 matches:\", propene.GetSubstructMatches(alkene_ch2))" ] }, { "cell_type": "markdown", "id": "88b1f6aa", "metadata": {}, "source": [ "While evaluating structures from left to right works perfectly for linear\n", "chains, chemistry is full of branched architectures. Using purely linear logic\n", "makes it impossible to define non-linear molecules. To solve this, SMARTS\n", "introduces **parentheses**.\n", "\n", "Consider the following pattern:\n", "\n", "`[CX4H3][CX4H2]([OH])[CX4H3]`\n", "\n", "In chemical terms, we are defining:\n", "\n", "* `[CX4H3]`: An aliphatic carbon with four connections and three hydrogens ($\\text{-CH}_3$).\n", "* `[CX4H2]`: An aliphatic carbon with four connections and two hydrogens ($\\text{-CH}_2\\text{-}$ before branching).\n", "* `[OH]`: A hydroxyl group.\n", "\n", "The structure can be read as follows: We have a $\\text{-CH}_3$ group bonded to\n", "a carbon, which is simultaneously bonded to both an $\\text{-OH}$ group and\n", "another $\\text{-CH}_3$ group. Let's build and render this structure in RDKit:" ] }, { "cell_type": "code", "execution_count": 87, "id": "ac55589f", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 87, "metadata": {}, "output_type": "execute_result" } ], "source": [ "smt = Chem.MolFromSmarts('[CX4H3][CX4H2]([OH])[CX4H3]')\n", "\n", "smt" ] }, { "cell_type": "markdown", "id": "905c389e", "metadata": {}, "source": [ "The golden rule for branching is: **any atom or chain written inside\n", "parentheses is always bonded to the atom immediately to its left** (in this\n", "case, the `[CX4H2]` carbon).\n", "\n", "If we want to explicitly specify every single bond in this branched structure,\n", "notice carefully where the bond dashes `-` must be placed:" ] }, { "cell_type": "code", "execution_count": 88, "id": "1b609ef1", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 88, "metadata": {}, "output_type": "execute_result" } ], "source": [ "smt = Chem.MolFromSmarts('[CX4H3]-[CX4H2](-[OH])-[CX4H3]')\n", "\n", "smt" ] }, { "cell_type": "markdown", "id": "b55918f3", "metadata": {}, "source": [ "What happens if we have multiple branches bonded to the same central atom? In\n", "that case, we simply append another set of parentheses consecutive to the first\n", "one:" ] }, { "cell_type": "code", "execution_count": 89, "id": "93e7ff05", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 89, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# A central CH2 bonded to an -OH branch and a -CH2-CH3 branch\n", "molecule = Chem.MolFromSmarts(\"[CH3]-[CH2](-[OH])(-[CH2]-[CH3])-[CH3]\")\n", "\n", "molecule" ] }, { "cell_type": "markdown", "id": "9b524f10", "metadata": {}, "source": [ "Now, the central `[CX4H2]` carbon is simultaneously bonded to two distinct\n", "branches: one containing a hydroxyl group (`-[OH]`) and another containing an\n", "ethyl chain (`-[CX4H2]-[CX4H3]`). \n", "\n", "The rule remains unshakable: **all parentheses are attached directly to the atom immediately to their left**.\n", "Furthermore, this logic is perfectly scalable, meaning you can nest parentheses\n", "inside other parentheses to build as many complex sub-branches as your\n", "thermodynamic model requires!" ] }, { "cell_type": "markdown", "id": "e24c6330", "metadata": {}, "source": [ "Finally, to conclude the core basics of SMARTS syntax, we have **rings**. This is \n", "incredibly useful for defining specific aromatic or aliphatic cyclic fragments. \n", "\n", "How do we define a ring? We use numbers. By labeling two separate atoms with the \n", "same digit, we instruct the engine to form a bond between them, effectively \n", "bridging the gap and bypassing the strict left-to-right progression. For example, \n", "a cyclohexane ring can be defined as follows:" ] }, { "cell_type": "code", "execution_count": 90, "id": "9b7da38e", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 90, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Check the first and the last [CX4H2] have a 1, they are going to be bonded\n", "smt = Chem.MolFromSmarts(\"[CX4H2]1[CX4H2][CX4H2][CX4H2][CX4H2][CX4H2]1\")\n", "\n", "smt" ] }, { "cell_type": "markdown", "id": "937e17e7", "metadata": {}, "source": [ "If your molecule contains multiple rings, you can use different numbers to \n", "define each individual cycle. For example, consider this bicyclic system:" ] }, { "cell_type": "code", "execution_count": 91, "id": "bb466a33", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAcIAAACWCAIAAADCEh9HAAAABmJLR0QA/wD/AP+gvaeTAAAb8UlEQVR4nO3d+1NT+fkH8E8SQgAJBAguJCiCXAQEFy+IiIAEk8O6Fx2t093a3dbVqTNq2z+gM+0P/QM61Z2xo9vtbu3u1kuh7mJCSBAoIAKCiwJLQJBLACGES4Dcz/n+cFqHr3bTQ05Ozkl4Xj844wwHHiK++Zwnz+dzeARBIAAAAN7is10AAAAENohRAACgBWIUAABogRgFAABaIEYBAIAWiNGNZWpqqq6ubnR0lO1CgtPo6GhdXd3U1BTbhQC/4sHA0wbhdrvr6+tbW1vJv2ZlZb333nsikYjdqoKG0+msqan57rvvyL/u2bMHw7CQkBB2qwL+ATG6IfT392u12oWFBYSQQCBwu90IocjIyIqKiry8PB6Px3aBAYwgiJ6eHp1Ot7y8jNa8vBKJRKlUZmVlsV0gYBzEaJAzmUy1tbVDQ0MIIalUqlAoduzYMTY2ptPpxsfHEUKJiYkYhm3dupXtSgPS5OSkRqMhX0mZTKZQKFJTU4eGhnQ63YsXLxBC27ZtwzDsjTfeYLtSwCCI0aBltVobGxs7OjpwHA8PDy8tLd23bx+f/+9uOEEQ5BJ1cXERIZSdna1UKqOjo1ktOZBYLJbGxsauri6CIMRicWlp6e7du1+u68klal1d3crKCo/Hy83NVSqVmzZtYrdmwBCI0SCE43h3d3d9ff3q6iqfz8/Pzy8vL4+IiHj9I51OZ0tLS0tLi8vlEgqFRUVFxcXF0NHzzO12d3Z21tfXOxwOgUCwd+/e8vLy0NDQ1z/SZrM1Nze3tbW53e6wsLDi4uLCwkKBQOD/mgGjIEaDzcjIiEajmZmZQQilpKRgGLZ582bPlywtLen1+p6eHoRQVFRUeXk5NEx/iMFgUKvVZJc5IyMDw7CYmBjPl8zNzdXW1g4ODiKE4uLiVCpVenq6P2oF/gIxGjzMZrNer+/r60MIxcbGKhSK7Oxs6pePjo5qNJrp6WmEUHJyMoZhCQkJTNUagEwmk0ajefbsGUJIKpViGLZ9+3bqlw8PD2s0mtnZWYRQamoqhmHx8fFM1Qr8C2I0GDgcjtbW1ubmZrfbTd6bHzp0yIubR+jo/Vdkl7m9vZ0gCLLLXFBQ4MVqHcfxjo6O+/fv2+12Pp+/b9++w4cPw8xZEIAYDWxMBN/ajl5oaOiBAwe8C+UgQAZfQ0ODzWbz3GWmzlehDLgDYjSAGY1GjUYzMTGBEJLL5RiGJSUl+eqTm83m2tpag8GAvGoRBAFGb8Onp6c1Gg25nSwhIQHDsOTkZF99cuBnEKMBae2bQmKxWKFQMPSm0CtRolKp/ucbVkFgbm5Oq9X64VfIK29YVVZWSiQSJr4QYBTEaIBxOp3t7e1NTU0Oh0MoFBYUFJSUlPzXaZvXEQThXUeP4vhUEKAzouTdy+tyuR4+fEj+g4aEhOzfv5/6PyjgCIjRQEJz8VJVVbVz507vpm2CvqNHv8v8t7/97fDhwzKZzIuvbrFYdDqdH24vABMgRgPD1NSURqMZGxtDXm3f1Gq1eXl5y8vLLS0tH330kddl0Bz64azR0VG1Wk1u3/Ri2Ovu3bulpaUjIyNDQ0MnT570uozJyUm1Wk02u2UyWWVlpQ+b3YA5EKNct7q62tTU5PUysK2tLScnx2Aw9Pf3nz592uVy0d+k5MUIOmfR3HrQ1NS0f//+hw8fzs3NHTt2zO1203x5XznoJC8v78iRI5GRkXQ+J2AaxCh30RwzHBgYSElJaW5uXlxcPHbs2OLiog/fvqC+IZKz6GyEJU8k2LFjR01NTVhY2OHDh61Wq1gs5kJtwP8gRjnKYDBotdq5uTmEUGZmplKpjI2NpXjt7OysVCqtrq6Ojo4uLi6enJzctm0bE0VaLJa6uronT54ghMRisUqlys7O5n5HjyCIvr6+2tpai8WCEMrNzT1y5Aj1EJyZmdm8efONGzcyMjJycnIWFhbkcjkTdZrNZq1WOzAwgBCKi4tTKpUZGRlMfCFAE8Qo57zcgr1169aVlZV1bcG22+0ikeiLL77IycnJyMgYGhrKz89ntFr0n8PicBw3Go0ymQzDsC1btjD9Rb02NTWlVqvHx8flcjmO4+vqMtvt9tDQ0KtXrx4+fDguLm52dtYPs7QjIyO1tbUikWhsbCwlJUWlUsGxe1wDMcohVqu1oaGhs7OTPNpOoVDk5+e/PNrOM3La5tNPPy0tLRWLxf39/WVlZQzX+/+++tOnT7VaLdnR27Vrl0Kh8OFNrk9YLBa9Xk8eUB8ZGalUKnfu3Elx7Uz+N7ly5cqJEyfsdvvs7GxBQQGz5a5Bzpzp9Xqr1crn8/fu3VtWVhYeHu63AoBnEKOcsHY2k5y2UalU65rN/PzzzzEMW1paGhwcfOutt5gr1QPOdvTITq7XXWaCIK5fv37q1KmRkZGFhQV//n5ay2azNTQ0kAfIwrF7nAIxyr5XjrZb711bVVVVRUXFwMDAxMTEsWPHGCuTqtff+961axeL9RgMBo1GMz8/j9Y/V4Dj+J07d9599922tjan01lRUcFkpZTAsXscBDHKprVH28XExFRUVFDvtREE0dTUVFRU1NTUtLq6+vbbb+M4zp21yfPnzzUaDbsP0njlASoqlSotLY3itW63+1//+ldJScm3334rFotLSkr4fD533j0bHh5Wq9UmkwkhlJqaWllZKZVK2S5q44IYZQfNaZu+vr7s7OyqqqqYmJiDBw86nU4OHmfH4rF7nh+g4hmO499//312dvZf//rXzMzM3NxcHo8XFhbGdM3rBcfucQfEqL/RnK8mp23+8pe/5OXlpaenLy8vJyYmMlkvXX5+kAbNEwBmZmakUunVq1crKiqkUimO4xxf5dHcnQF8AmLUr+js9iOnbT755JPKysrIyMiFhYXMzEwmi/Ul/3T0vHiAykvkmu6Pf/zjBx984HQ6cRxnaNiWCTT3CgOaIEb9hObZEziOX758+f33319aWlpcXNyzZw+TxVLicrmam5tLS0upfxfMneBJ8wEqDofj8uXL586dGx0dFQgEXDhZ1Wq1Pnr0qLi4mPolcOweWyBGGeerk9A6OzvtdvvBgweZKNILjY2Ns7OzJ06cIBu1FMPU5x09sstM/wEqjY2NUVFRftitQNG9e/d4PJ5SqTQYDFlZWRSvonOOIvAaxCizgniBMD09HRERMTw83NXV9fOf/3x2dpb6HbRPjt1b+xYWCrpTPMbHx6VSaVdX18TExKlTp9b18sKxe34GMcqUDfKUCIPBIBaLbTbbN998c/HiRafTSX1pSeclYvQBKtzx5MmTpKQko9HY1tZ29uxZcrMvxWs3yEvEBRCjvhf0Jxy/rru7e9OmTbGxsTdu3Lh06dK6RizXu2DfgEut1tbWLVu2EARRU1Nz/vx5hBD1PayvzJwF04KdOyBGfWmDj/I9ePCAz+fv3Lnzxo0bH3/8MfVtoBTbxxu88afT6RISEmQyWVVV1ZkzZ6j/5vBV+xj8EIhRn2H0QZIBpKmpyWazlZeXV1VVHT9+nHqYel5mBnGXeV3UanV0dHR+fn5NTc2JEyeohynNYQbgAcSoDwwNDT148GB4eBjBNmeECIJwu93t7e1Go/HkyZPkjlWhUEjx8tdHawUCAQxFvoTjOEJIp9O53W6lUknuWKW4QQv9/9Ha5OTkoqIiOMOUPohRuqqrq8mz18LCwsrKyqhvOgxuDofD6XQODQ11dnaeOXOmv78/MzOT+iM2Hz9+XF9fv7y8TK62CIKIjIwsLy9/8803g7sNSpHVauXxeF1dXaOjoz/+8Y+9mDlraGiw2WwIoV27dnHhRJuABjFK1+9//3u32x0bG3vmzBkObmxn1/z8vMvlWllZ+ec//3nhwgWz2Ux9aofs6D148AAhlJ+fv6G6zBTNzMyEhoZOTEy0traeO3duvTNnn3322ezsrEAg+M1vfsNonUEP1k10kTdZ77//PmTo62JiYuLj40NCQt55552FhYUvvvjCZrPZ7XYq1wqFwrKyMofD4XA4MAyDDH3d5s2bJRJJeHj40aNHJyYmvvzyS7fbTfHlDQ8PP3XqFPrPDzCgA2KULvIQcjiK3IOkpKTU1NT5+fny8nIcx69cubK6ugq3Qb6yfft2uVy+sLCgUqmWlpY++eQTl8tF5eWFH11fgRgFfpKenr579+6RkZG8vLzQ0NBr166RZ1wBn8jNzc3KyhoaGtq/f7/T6fzTn/7kdDrZLmqjgBgFfpWTk3PkyJG+vj6JRLJp06bq6mry8ZzAJ/bt23fw4MHHjx9v3bqVz+ffvn2b4j0+oIP95+SADSgvLy87O7u/v99kMsGmGp8rLCx0u92PHj1yOBzQU/YDiFHAjpCQkMzMzKSkJBhg8jkejxcSEpKfnw8D9v4BMcosvV5vNpsVCkVsbCzbtXCOQCCIiopiu4qgJRQKqe96AHRAjDIrNTU1MTFxXY9KBgAEFniLCQAAaIHVKLOGh4fNZnNCQgIHHy0JAPAJiFFmKRQKtksAADALYpRZ165dm5ycPHv2rFwuZ7sWAAAjIEaZde7cObZLAAAwC95iYpZer79165bZbGa7EAAAU2A1yiwYeAIg6MFqFAAAaIHVKLNg4AmAoAcxyiwYeAIg6EGMMgsGngAIehCjzIKBJwCCHrzFxCwYeAIg6MFqlFkw8ARA0IPVKAAA0AKrUWbBwBMAQQ9ilFkw8ARA0IMYZRYMPAEQ9CBGmQUDTwAEPXiLiVkw8ARA0IPVKLNg4AmAoAerUQAAoAVWo8yCgScAgh7EKLNg4AmAoAcxyiwYeAIg6EGMMgsGnhj1hz/8YXFx8Ve/+pVEImG7Fi4yGo3Xr1+XyWTwc8goiFEQwH7961+zXQKnyeXy3/72t2xXEfzgnXoQwO7du3fr1q3V1VW2C+Eos9l869YtvV7PdiFBDlajIIClp6c7nU6hUMh2IRwVERGRk5MTHh7OdiFBDlajAABAC8QoCGCDg4O9vb1Op5PtQjhqdXW1t7d3eHiY7UKCHNzUgwD21ltvsV0Cp8XGxv7oRz9iu4rgBzEKAhgMPHkGA0/+ATEKAhgMPHkGA0/+Ab1REMBg4MkzGHjyD1iNggAGA0+ewcCTf8BqFAAAaIEYBQEMBp48g4En/4CbehDAYODJMxh48g+IURDAYODJMxh48g+IURDAYODJMxh48g/ojYIABgNPnsHAk3/AahQEMBh48gwGnvwDVqMAAEALxCgIYDDw5BkMPPkH3NSDAAYDT57BwJN/QIyCAAYDT57BwJN/QIyCAAYDT57BwJN/QG8UBDAYePIMBp78A1ajIIDBwJNnMPDkH7AaBQAAWiBGQQCDgSfPYODJP+Cm3h+Wl5dFIhHce/ocOfC0tLTkdrsFAgHb5XAODDz5B6xG/eHu3bvd3d0ul4sgCLZrCTYEQdy8eXNgYMDlcrFdC9igIEYZZ7fbQ0ND9+zZo9Vq29ra2C4n2CwvL0ul0qysrH/84x89PT1slwM2IohRxolEopMnT+I4PjY29uabb7a0tHR0dLBdVPAQi8XHjh1bWVlZWFjIzs6uq6vr7e1luyiwsUCM+olQKPzFL34hFAofPnyYlpbW39//5MkTtosKHpGRkefOnXM4HD09PSkpKV1dXYODg2wXBTYKiFG6rFbryz894/F4ISEhFy5ciIqKqq2tlUgkRqPx2bNnzNe4IfB4vIiIiIsXL/L5/Pr6+piYmOHh4YmJCbbr4i7qP7rAM4hRuvh8PkLoq6++WllZofLxIpFIIBB88MEHSUlJNTU1Vqt1YWFhZmaG4TIDj9PpbGhoCA0NDQ0N1Wg0drudylUikSgsLOzDDz+USCTffPONy+WanZ2dn59nutqAY7Vab968if7zAwzoEPzud79ju4bAZjabX7x4YbVau7q6hEKhTCbj8Xj/86pNmzYhhMLDw3Nycqqrq3Ecj4+Phw05JIIgHj9+/PXXXw8ODuI4juP4xMTE48ePw8PDExISKL68BEFER0enpaV9/fXXmzZtEovFCCEYikII4Tje3t7+97//fWlpCSGUl5e3Y8cOtosKbDwYwaFvaGjowYMH5JBzXFycSqVKT0+neC2O401NTYcOHdJqtQKBoKKiAm3sBYLRaNRoNOTNuEwmq6ysFAgEGo1mbGwMIZSYmIhh2NatWyl+NqfT2draWlJScvv2bblcXlBQIBAIqARxsBoZGdFoNOTdT3JyclFRUUZGBttFBTyIUZ8ZHh7WaDSzs7MIodTUVAzD4uPjKV5LEMSdO3eOHj3a3d29uLhYWVnJZKUcZbFYdDodObQkFosVCkVeXt7LyDMYDGq1emFhASGUkZFRWVlJ/XA8l8tVVVV1/Pjx+vr6sLCwkpIShr4FLjObzXq9vq+vDyEUGxurUCiys7PZLipIQIz6Eo7jHR0d9+/ft9vtfD5/3759hw8fFolEFC8nCOLPf/7z8ePHJycnp6enyZXpRuByuR4+fNjU1ORwOEJCQvbv319SUhIaGvrKhzmdzvb29v/5YR6+yqeffnr69OmnT5/iOH7gwAFffx8c5XA4Wltbm5ub3W63UCgsKio6dOgQ9Dd8CGLU96xWa2NjY3t7O0EQ4eHhpaWlBQUFFG8kyX+Oq1evHj16lMfjjY+PFxUVMVwvy9a7zPS8aPWMIAgcxy9fvnz69Gmz2byyspKfn++T74KbCILo6empq6tbWVnh8Xi5ublKpZLsywMfghhlyvT0tEajGR0dRQglJCRgGJacnEzxWrvdLhKJrl+/XlhYKJfLJyYmcnNzmSyWHVNTUy+bnut9ida2UOVyOYZhSUlJFK+12+1CofDKlSvvvPNOWFiYxWIJyv6g0WhUq9VGoxGt/yUC6wIxyiw6Hb2ZmZn4+PibN28mJSXt3r3bZDJt2bKFyWL9h86C/SVyqaXT6ZaXlxFCeXl5R44ciYyMpHg5+fJ+9tlnu3fvTk1NXV1dTUhIWPd3wklLS0t6vd67BTvwAsQo4yg2/n5If39/RkaGVqslCII7T3Dr7u5eWloqLS1d74U028evczqdLS0t3jX+CILo6+vLzs6+c+dOfHy8F98OQ1paWkQi0d69e9d74dr2sVAoLCgoWNcPG/AOxKif0OnoIYSam5v37NnDhWPM+/r63G53cnLytWvXLl26tK7/onSGGTyj8zY0QRCNjY3FxcUhIeyfG/no0aPo6OioqKivvvrq0qVL6xp9MxgM9+7dW1xcROu/9QF0QIz61eTkpFqtXjsUGUDtqufPn/P5fKFQ+OWXX/7yl7/EcZz6KnJubq62tpbc577e0Vrq1g5FpqSkYBi2efNmn38VhgwMDEgkkuXlZbVafeHCBYfDQf3lXdtlXu9oLaAPYtTfaHb0WGEymfh8vslk0ul058+fN5lM1OPJZrM1Nze3tbW53e6wsLDi4uLCwkLmpm1wHO/u7q6vr19dXeXz+fn5+eXl5REREQx9OZ+YmpqKjIwcHBzs6en52c9+NjMzQ/3lXV1dbWpqIrvMERERJSUlXnSZAU0Qo+wgO3otLS0ul4vs6HHkpvIVNpuNIIgnT54MDAz89Kc/7evr27FjB8U7TRanbci3sDo6OnAcJ9/C2rdvHwf3hq2srAiFwpaWlvn5+ePHj5ONWooh6PMuM/AaxCib5ufndTod2dGLiooqLy/ftWsX20X9Gzli2dTUZLFY3n77bXLHKvVV5PPnzzUazYsXLxBC27ZtwzDsjTfeYLLe/8JkMtXW1g4NDSGEpFKpSqVKS0vzcw0/xO128/n8b7/9llxCkjtWqa8iDQaDRqMhj1xJTU2trKyUSqVM1gs8gRhl38jISG1tLbuJ8zqdTicUCgsLC+/evXvixAnqS7m10zZc+N2wNnEyMjIwDIuJiWGxHlJ1dXVSUlJmZqZOpzt+/Dj1C9f+bmCuywzWBWKUE8j7X61Wu7q6St7/qlQqtjp6DQ0NEokkJSXl5s2bZ8+epb5E4mynglP3v/fu3UtPT4+KitJoNB999BH1C202W0NDA9mpCAsLKysr42anYgOCGOUQq9Xa0NDQ2dlJdvQUCkV+fr4//5+0t7fHx8eLRKI7d+5cvHgRIUR9k+XTp0+1Wi35vtmuXbsUCgV5Nh13WCwWvV7/3XffIYQiIyOVSuXOnTv9+W5MQ0NDVlaWxWJpbGz8+OOPCYKg3gbt7u7W6/VWq5XP5+/du7esrIwL02+ABDHKOS9ng7Zu3bqysuKfu7a+vr74+Pi5ubn79++fP39+XdM2k5OTGo0Gx3Gj0SiTyTAM4/Juq6mpKbVaPT4+LpPJCILwz2xQd3d3WlqawWDo7e398MMPyc2+FK8lp7jCwsLGxsZSUlJUKhUXej5gLYhRjjIYDFqtdm5uDiGUmZmpVCpjY2OZ+EJGo1EikfT29hoMhtOnT69r2sZisdTV1ZEPlRKLxSqVivobzSwiNy/V1tZaLBaEUG5u7pEjRxhaOz9//lwmkzU3Ny8uLh47dsxkMlHfcWA2m7Va7cDAAEIoLi5OqVQG5d7/IAAxyl1Md/QsFkt4ePj9+/dtNtvRo0e///77rKwsiiHodrs7Ozvr6+sdDodAINi7d295eXlgbTpkupO7sLAQHR1dXV0dHR1dXFw8MjKSmZnJkdqAb0GMcp1PTvF4hcvlEggE1dXVcXFx+/fvf/jw4bpOMqZz3grXvD5XQP8UD5fLFRIScuPGjaysrIyMjN7e3sLCQorXBuLuDAAxGhh8u9vv9u3baWlpKSkpjY2N7777LvUL157+J5VKMQzbvn2712Vwx+joqEajmZ6eRgjJ5fLKykq5XO71Z/v8888PHjwYGRnZ09OjVCqpXxjQe4U3MojRQOKrZeDk5OT9+/d/8pOfUL+EiUUxp/hwz9Xg4ODTp0/XNQ1K8+QawC6I0QBD80EaL61r2qajo6OhocFmswXKLnWvrT0BIDQ09MCBA949b4P6y0vzHEXABRCjAclvixfmjrbjMr89/S2YuswbGcRoAKPzII3/aW5uTqvVGgwGhFBsbKxKpdpo0zav/ApRqVQ+PHaPzjNmANdAjAa2tR095KM3dv18tB2XMXHsXtB3mTcgiNFgQOdBGmvBgyT/K18FH6e29gMfghgNHjQ7emuPtktOTsYwLGge8eYTJpNJo9E8e/YMeTXstTG7zBsExGiw8eJBGkyMoAcrL47d888DVACLIEaDEPWOHmw69MLrG2F/6N4cuswbBMRo0PL8IA2CIPr7+7VaLfkgyezsbKVSGR0dzWrJgYQ8766rq4sgCLFYXFpaunv37pdLeOgybygQo0HulQdpKBSKHTt2jI2N6XS68fFxhFBiYmJlZSWXj7bjMvKQQPKVlMlkCoUiNTV1aGhIp9Nx7XEGgDkQoxsCufAkx7wFAoHb7UYIRUZGVlRUQBuUplcOE3n58kokEqVSmZWVxXaBgHEQoxuF2+2ur69vbW0l/5qVlfXee+/BtI2vOJ3Ompoa8mh9hNCePXswDIMu8wYBMbqxTE1NPX36NCMjA/bMMGF0dNRgMOzcuTMxMZHtWoD/QIwCAAAt8FhBAACgBWIUAABogRgFAABaIEYBAIAWiFEAAKDl/wAX/bEgXhGBZgAAAS56VFh0cmRraXRQS0wgcmRraXQgMjAyNi4wMy4xAAB4nHu/b+09BiAQAGJmBgjgAmJuIG5gZDOwAAkwMUmyAynHkvxcx7wUORkmVB4HlBdSWZCqKMUGNUWGgR8mnl+SmOOSml6UCpRmgUtzQaU9nPNL80oUpZjgMtoDbC8jIz3sZRw0/h21dzRdDYtw5mZgFJAUAbKDM/PSc1L9ixyL8nMTSzKTnfLzUhw5gRIghn9RSmoRSjgxMpGljYmZLG3MLGRpY2ElSxsrG1na2NjJ0sbOQZY2Dk6ytHEykOdI8qLbCZTS2Bg4OdiZGNmYWVjZ2JnEm4BCMCUMXA/d1BwYGBz2gzgP3ZbZMzAc2A+RaliCJL4fJg5UfwAhDmbbI6mxh+hdoIokbg8Th9oFZosBAEDSeCmwniDkAAABhXpUWHRNT0wgcmRraXQgMjAyNi4wMy4xAAB4nKWUyW6DMBCG7zzFKIeoPYC8YIMPHAjQNGpZAqRqVPUBeu/7q+MgMFiKlcqGQWb0+7NngQD06Mu3n19YBiuDAIA4bqUUfHBCSFCDnsChOp4aKMb8MHuK9tKMA1AClOonXltxPrb17KFQAIuESkkiISRRIpCNKyJCpsksZCikEVOK8BRCGglyR8hRGC5uFzLWyoeYQisfOqbcKB3CZLO5Y+8UhcZ7H6jWCXLwsCKrlDuAVVNuSjUV79A2pSmeRGOmRBKNm0JItNhkW6IJk1KpzeRNX4nJDr5AanIg0ZQJVaLRdUjy1m+Lg94W8HUo64NPoQzHvr10JpgyH7FZdchD9oSt+wznS9Vfx2tXZUOd9+Nwnjxtl2XwcqreS1ySZ7uvYv8Z71/Z986kwoIxDxi3Yfy/MGpgsQ2LPU4mbJjwgEkbJj1giQ1LPGCpDUs9CqBsmPI4GTa93bXEjQvnpU6u/mC2n4f2zH95nAd/0ApdFsjQaO0AAABoelRYdFNNSUxFUyByZGtpdCAyMDI2LjAzLjEAAHici3b2MIo1jAaRMCLWCIWLIWGoUKOha6RnamlhYKGja6BnbqpjDedDuYZ6RpaWBiY6hnpAngFUFEUQVQOacTCVulD9umjGgsU1awDohSo21w1u/QAAAABJRU5ErkJggg==", "text/plain": [ "" ] }, "execution_count": 91, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# A bicyclic system combining a 6-membered and a 5-membered ring\n", "smt = Chem.MolFromSmarts(\"[CX4H2]1[CX4H2][CX4H]2[CX4H2][CX4H2][CX4H2][CX4H2][CX4H]2[CX4H2][CX4H2]1\")\n", "\n", "smt" ] }, { "cell_type": "markdown", "id": "aeb7cfe5", "metadata": {}, "source": [ "Let's carefully analyze where the ring labels are placed to understand the connectivity:\n", "\n", "```shell\n", "[CX4H2] 1 [CX4H2][CX4H] ([CX4H2][CX4H2][CX4H2][CX4H2] 2 ) [CX4H] 2 [CX4H2][CX4H2] 1\n", "```\n", "\n", "Here is how the engine interprets it:\n", "* The labels **1** open and close the main 6-membered ring.\n", "* Inside that main ring, we encounter the first bridgehead carbon (`[CX4H]`),\n", " which opens the second ring (in the parenthesis).\n", "* The structure then continues along a linear chain of four `[CX4H2]` groups.\n", "* At the end of this chain the final `[CX4H2]` is labeled with a **2**, the\n", " second bridgehead carbon (`[CX4H]`) is also labeled with a **2**, closing the\n", " second ring and fusing the two cycles together.\n", "\n", "(Note: Notice that the bridgehead carbons are defined as `[CX4H]` instead of\n", "`[CX4H2]`, because they are bonded to three heavy atoms total, leaving room for\n", "only one hydrogen)." ] }, { "cell_type": "markdown", "id": "ad7da74c", "metadata": {}, "source": [ "#### Logical operators, ring constraints, and aromaticity\n", "\n", "What happens when we want to define a fragment that must only be detected if it \n", "is part of an aliphatic ring? To achieve this level of control, we need to utilize \n", "SMARTS logical expressions:\n", "\n", "* `!`: \"NOT\" (highest precedence)\n", "* `&`: \"AND\" (high precedence)\n", "* `,`: \"OR\" (low precedence)\n", "* `;`: \"AND\" (lowest precedence)\n", "\n", "Precedence here follows the exact same concept as in any programming language: \n", "operators are evaluated in a specific order. High-precedence operators are \n", "resolved first. It is important to note that **you cannot use parentheses to group \n", "logical operations** in SMARTS, because parentheses are strictly reserved for \n", "chemical branching.\n", "\n", "To illustrate how precedence changes the evaluation order, consider the operands \n", "$A$, $B$, and $C$:\n", "\n", "**A&B,C**\n", "\n", "This expression means \"either ($A$ AND $B$), or $C$\", which translates\n", "mathematically to $(A \\wedge B) \\vee C$. The high-precedence `&` operator is\n", "evaluated first.\n", "\n", "On the other hand:\n", "\n", "**A;B,C**\n", "\n", "This expression means \"$A$ AND ($B$ or $C$)\", which translates mathematically\n", "to $A \\wedge (B \\vee C)$. The low-precedence `;` operator is evaluated last,\n", "effectively binding the entire \"OR\" block that precedes it.\n", "\n", "Now, imagine you want to define two different $-\\text{CH}_2-$ fragment types:\n", "one that must be part of an aliphatic ring (like in cyclohexane) and another\n", "that must strictly belong to an open chain (like in n-hexane). We can cleanly\n", "separate them using the ring membership primitive `R` combined with our logical\n", "operators:" ] }, { "cell_type": "code", "execution_count": 92, "id": "ba2ae189", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Cyclohexane ring CH2 matches: ((0,), (1,), (2,), (3,), (4,), (5,))\n", "Cyclohexane chain CH2 matches: ()\n", "Hexane ring CH2 matches: ()\n", "Hexane chain CH2 matches: ((1,), (2,), (3,), (4,))\n" ] } ], "source": [ "cyclohexane = Chem.MolFromSmiles(\"C1CCCCC1\") # Cyclohexane\n", "hexane = Chem.MolFromSmiles(\"CCCCCC\") # n-Hexane\n", "\n", "# CH2 must NOT be part of a ring\n", "ch2_chain = Chem.MolFromSmarts(\"[CX4H2;!R]\")\n", "\n", "# CH2 MUST be part of a ring\n", "ch2_ring = Chem.MolFromSmarts(\"[CX4H2;R]\")\n", "\n", "print(\"Cyclohexane ring CH2 matches:\", cyclohexane.GetSubstructMatches(ch2_ring))\n", "print(\"Cyclohexane chain CH2 matches:\", cyclohexane.GetSubstructMatches(ch2_chain))\n", "print(\"Hexane ring CH2 matches:\", hexane.GetSubstructMatches(ch2_ring))\n", "print(\"Hexane chain CH2 matches:\", hexane.GetSubstructMatches(ch2_chain))" ] }, { "cell_type": "markdown", "id": "d7d25afe", "metadata": {}, "source": [ "In the expression `[CX4H2;!R]`, the engine interprets the logic as: \"This is\n", "an aliphatic carbon with a total connectivity of 4 and exactly two hydrogens,\n", "**AND** it is **NOT** part of a ring.\" The `!` operator negates the `R`\n", "primitive, ensuring no cyclic carbons are matched.\n", "\n", "Conversely, in the expression `[CX4H2;R]`, we are enforcing the opposite\n", "constraint: \"This is an aliphatic carbon with a total connectivity of 4 and\n", "exactly two hydrogens, **AND** it **MUST** be part of a ring.\"\n", "\n", "You can also specify the exact size of the ring by using a numeric value after\n", "the lowercase `r` primitive. For example, `[CX4H2;r5]` will strictly match\n", "aliphatic carbons that are part of a 5-membered ring:" ] }, { "cell_type": "code", "execution_count": 93, "id": "9754e638", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Cyclopentane 5-membered ring CH2 matches: ((0,), (1,), (2,), (3,), (4,))\n", "cyclohexane 5-membered ring CH2 matches: ()\n" ] } ], "source": [ "cyclopentane = Chem.MolFromSmiles(\"C1CCCC1\") # cyclopentane\n", "\n", "ch2_5ring = Chem.MolFromSmarts(\"[CX4H2;r5]\") # CH2 must be part of a 5-membered ring\n", "\n", "print(\"Cyclopentane 5-membered ring CH2 matches:\", cyclopentane.GetSubstructMatches(ch2_5ring))\n", "print(\"cyclohexane 5-membered ring CH2 matches:\", cyclohexane.GetSubstructMatches(ch2_5ring))" ] }, { "cell_type": "markdown", "id": "89bbf6c2", "metadata": {}, "source": [ "Note the lowercase `r5` used to indicate the ring size. If you accidentally use\n", "an uppercase `R5`, the meaning changes completely: the engine will search for a\n", "`CX4H2` carbon that belongs to **five different rings simultaneously**." ] }, { "cell_type": "markdown", "id": "19dd1b87", "metadata": {}, "source": [ "Finally, how do we define an aromatic fragment? In many cases, you don't even\n", "need explicit logical operators for this. Instead, you can simply use the\n", "**lowercase** atom primitives to indicate aromaticity. \n", "\n", "For example, `[cH]` defines an aromatic carbon with exactly one hydrogen, while\n", "`[cH0]` defines an aromatic carbon with no hydrogens. In SMARTS (and SMILES),\n", "lowercase atom symbols always denote aromatic atoms, whereas uppercase symbols\n", "specify aliphatic ones.\n", "\n", "By combining what we have learned so far, we can build highly specific filters.\n", "For instance, if you need to target an aromatic carbon with one hydrogen inside\n", "an 8-membered ring, you can write: `[cH;r8]`. \n", "\n", "* `[cH0;R1]` may seem redundant at first glance, since an aromatic atom is by\n", " definition always part of a ring system. However, if your model needs to\n", " strictly distinguish peripheral aromatic carbons from those at a ring fusion,\n", " enforcing the `R1` constraint becomes mandatory to prevent\n", " cross-contamination.\n", "* `[cH0;R2]` is **NOT redundant**: This pattern specifically targets an\n", " aromatic carbon with no hydrogens that is shared by **exactly two different\n", " rings simultaneously** (a bridgehead fusion carbon).\n", "\n", "Let's visualize this distinction using a naphthalene:" ] }, { "cell_type": "code", "execution_count": 94, "id": "4129fe09", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 94, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ac_onering = Chem.MolFromSmarts(\"[cH0;R1]\") # Aromatic carbon only in one ring\n", "ac_tworings = Chem.MolFromSmarts(\"[cH0;R2]\") # Aromatic carbon on two rings simultaneously\n", "\n", "molecule = Chem.MolFromSmiles(\"CC1=CC2=C(C=CC=C2)C=C1\") # Naphthalene\n", "\n", "molecule" ] }, { "cell_type": "markdown", "id": "48017552", "metadata": {}, "source": [ "With the fragments we have defined, we can differentiate between the different\n", "aromatic carbons with no hydrogens:" ] }, { "cell_type": "code", "execution_count": 95, "id": "bbee1a44", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 95, "metadata": {}, "output_type": "execute_result" } ], "source": [ "molecule.GetSubstructMatches(ac_onering)\n", "\n", "molecule" ] }, { "cell_type": "code", "execution_count": 96, "id": "41a2bccf", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 96, "metadata": {}, "output_type": "execute_result" } ], "source": [ "molecule.GetSubstructMatches(ac_tworings)\n", "\n", "molecule" ] }, { "cell_type": "markdown", "id": "c11cff2d", "metadata": {}, "source": [ "Finally, it is possible to define a pattern that matches an element regardless\n", "of whether it is aliphatic or aromatic. This is extremely powerful for\n", "generalization and can be applied to any element in the periodic table. \n", "\n", "To define a generic element, you use the `#` primitive followed by its atomic\n", "number. For instance, carbon is represented by `#6`. Every other constraint we\n", "have learned so far (connectivity, hydrogen count, ring constraints) remains\n", "fully applicable:\n", "\n", "* `[#6H]`: A carbon atom (either aliphatic or aromatic) with an unspecified total connectivity, but possessing exactly one hydrogen.\n", "* `[#6X3H]`: A carbon atom (either aliphatic or aromatic) with a total connectivity of 3 and exactly one hydrogen.\n", "* `[#7X3H2]`: A nitrogen atom (either aliphatic or aromatic) with a total connectivity of 3 and exactly two hydrogens." ] }, { "cell_type": "markdown", "id": "3ddee45b", "metadata": {}, "source": [ "#### More complex logical patterns and recursive SMARTS\n", "\n", "`ugropy` requires you to provide a single, unique SMARTS pattern for each\n", "distinct fragment. For that reason, isolating complex groups requires a\n", "combination of creativity and advanced logic to ensure RDKit identifies\n", "*exactly* the atoms belonging to that fragment, without accidentally matching\n", "the surrounding environment.\n", "\n", "Let's inspect a real-world example from `ugropy`. The Dortmund UNIFAC model\n", "differentiates between three different types of hydroxyl groups: primary,\n", "secondary, and tertiary." ] }, { "cell_type": "code", "execution_count": 97, "id": "41897929", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['[OH;$([OH][CX4H0]([!#6])([!#6])[#6]),$([OH][CX4H]([!#6])[#6]),$([OH][CX4H2][#6]),$([OH][CX3H]=[#6]),$([OH][CX3H0](=[#6])[!#6]),$([OH][CX2]#[#6])]',\n", " '[OH;$([OH][CX4H0]([!#6])([#6])[#6]),$([OH][CX4H]([#6])[#6]),$([OH][CX3H0](=[#6])[#6])]',\n", " '[OH;$([OH][#6]);$([OH][CX4H0]([#6])([#6])[#6])]']" ] }, "execution_count": 97, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from ugropy import dortmund\n", "\n", "# Let's inspect the SMARTS for Dortmund UNIFAC OH subgroups\n", "dortmund.subgroups.loc[[\"OH (P)\", \"OH (S)\", \"OH (T)\"], \"smarts\"].to_list()" ] }, { "cell_type": "markdown", "id": "f64a7c36", "metadata": {}, "source": [ "This is where things get interesting because we are introducing a highly \n", "advanced notation. \n", "\n", "Let's dissect the **tertiary hydroxyl group** (`OH (T)`). By definition, a\n", "tertiary hydroxyl is an $-\\text{OH}$ group bonded to a tertiary carbon (a\n", "carbon bonded to three other carbon atoms). \n", "\n", "Here is the tricky part for `ugropy`: we only want to match and count the\n", "$-\\text{OH}$ group itself, not the carbons that it is attached to. \n", "\n", "If we try to define it using the basic linear and branching syntax we learned\n", "before, we might instinctively write something like this:\n", "\n", "`[OH][#6]([#6])([#6])([#6])`\n", "\n", "While it is chemically intuitive—an $-\\text{OH}$ group bonded to a carbon that\n", "is simultaneously bonded to three other carbons—if we feed this pattern to\n", "RDKit, the engine will return a match that includes **all five atoms** in that\n", "cluster. \n", "\n", "Let's see this issue in action with a branched alcohol:" ] }, { "cell_type": "code", "execution_count": 98, "id": "a39a2d7d", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 98, "metadata": {}, "output_type": "execute_result" } ], "source": [ "molecule = Chem.MolFromSmiles(\"OC(CCC)(C)(CC)\")\n", "\n", "molecule" ] }, { "cell_type": "markdown", "id": "4ca31f0e", "metadata": {}, "source": [ "There we clearly have a tertiary hydroxyl group, let try to search for matches:" ] }, { "cell_type": "code", "execution_count": 99, "id": "924157d5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Naive matches: ((0, 1, 2, 5, 6),)\n" ] }, { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 99, "metadata": {}, "output_type": "execute_result" } ], "source": [ "smt_naive = Chem.MolFromSmarts(\"[OH][#6]([#6])([#6])([#6])\")\n", "\n", "print(\"Naive matches:\", molecule.GetSubstructMatches(smt_naive))\n", "\n", "molecule" ] }, { "cell_type": "markdown", "id": "e09e774c", "metadata": {}, "source": [ "Of course, the definitions currently in `ugropy` are far from perfect. However,\n", "by critiquing my own past implementations, we can uncover some incredibly\n", "valuable lessons. The tertiary hydroxyl group is defined in `ugropy` as\n", "follows:\n", "\n", "`[OH;$([OH][#6]);$([OH][CX4H0]([#6])([#6])[#6])]`\n", "\n", "First, let's look at the outer brackets `[]` enclosing the entire structure. As\n", "we established earlier, brackets allow us to define a single target atom using\n", "specific logical constraints. Up until now, we have restricted atoms by their\n", "aliphatic/aromatic nature, total connectivity, hydrogen count, or ring status.\n", "Now, we are introducing a new superpower: **Recursive SMARTS**.\n", "\n", "When building a complex pattern like this from scratch, you should always start\n", "by writing the outer brackets:\n", "\n", "`[]`\n", "\n", "Next, ask yourself: *What single atom am I actually trying to isolate and count?* Since only the hydroxyl group should be counted when this fragment is matched, our \n", "primary target is the `OH` group. So, we place it inside:\n", "\n", "`[OH]`\n", "\n", "Now, we can append our environmental constraints. A **Recursive SMARTS**\n", "expression allows us to specify a structural pattern that must exist around our\n", "target atom *without* actually matching or \"claiming\" those neighboring atoms.\n", "This is done using the `$()` syntax, joined by our low-precedence AND (`;`)\n", "operator:\n", "\n", "`[OH;$()]`\n", "\n", "This translates to: \"Match a hydroxyl group AND (`;`) ensure that this exact\n", "oxygen is part of the structural environment described inside the parenthesis\n", "`$()`.\"\n", "\n", "The first recursive condition in the `ugropy` pattern is:\n", "\n", "`[OH;$([OH][#6])]`\n", "\n", "Here, we are saying: \"Match a hydroxyl group, but only if it is part of a\n", "larger `[OH][#6]` environment (meaning it must be directly bonded to a carbon\n", "of any nature).\"\n", "\n", "We can chain as many of these recursive conditions as we need by using\n", "additional low-precedence AND (`;`) operators. This brings us to the full\n", "`ugropy` expression:\n", "\n", "`[OH;$([OH][#6]);$([OH][CX4H0]([#6])([#6])[#6])]`\n", "\n", "For the match to be successful, our target `OH` must now *also* satisfy this\n", "second environmental checkpoint:\n", "\n", "`$([OH][CX4H0]([#6])([#6])[#6])`\n", "\n", "Which explicitly states: \"The hydroxyl group must be part of an environment\n", "where it is bonded to an aliphatic carbon with a total connectivity of 4 and\n", "zero hydrogens (`[CX4H0]`), which in turn is bonded to three other carbons of\n", "any nature (`[#6]`).\"\n", "\n", "**Time for some self-critique!** Looking back at my past code, the first\n", "condition (`$([OH][#6])`) is kind of redundant. Why? Because the second, much\n", "stricter condition already mandates that the `OH` must be bonded to a carbon.\n", "If it satisfies the second environment, it automatically satisfies the first\n", "one. \n", "\n", "But as I mentioned, the definitions in `ugropy` are a work in progress—and\n", "making (and analyzing) these redundant steps is exactly how we master SMARTS\n", "craftsmanship!\n", "\n", "Let's use this pattern to search for tertiary hydroxyl groups in the previous\n", "molecule:" ] }, { "cell_type": "code", "execution_count": 100, "id": "75653786", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tertiary hydroxyl groups: ((0,),)\n" ] }, { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 100, "metadata": {}, "output_type": "execute_result" } ], "source": [ "molecule = Chem.MolFromSmiles(\"OC(CCC)(C)(CC)\")\n", "\n", "smt = Chem.MolFromSmarts(\"[OH;$([OH][#6]);$([OH][CX4H0]([#6])([#6])[#6])]\")\n", "\n", "print(\"Tertiary hydroxyl groups:\", molecule.GetSubstructMatches(smt))\n", "\n", "molecule\n" ] }, { "cell_type": "markdown", "id": "855245e9", "metadata": {}, "source": [ "Now, let's look at one final example that demonstrates how the presence of\n", "*other* groups within a fragmentation model can heavily influence how you\n", "design the logic of a single fragment.\n", "\n", "The fragment in question seems fairly simple: the classic UNIFAC **ketone fragment** (`CH3CO`). This group consists of a methyl carbon bonded to a carbonyl carbon (a carbon with zero hydrogens, double-bonded to an oxygen). The pattern must match exactly those two carbons and the oxygen atom. \n", "\n", "It seems easy enough. Let's build it directly and intuitively:\n", "\n", "`[CX4H3][CX3H0]=O`\n", "\n", "And basically, that's it! It looks flawless. However, let's see how it is\n", "actually defined in `ugropy`:" ] }, { "cell_type": "code", "execution_count": 102, "id": "30cecdee", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'[CH3][CH0;!$(C(-[O,NH2,$([NH][CH3]),$([NH][CH2]),$([NH0]([CH3])[CH3]),$([NH0]([CH3])[CH2]),$([NH0]([CH2])[CH2])])=O)]=O'" ] }, "execution_count": 102, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from ugropy import unifac\n", "\n", "\n", "unifac.subgroups.loc[\"CH3CO\", \"smarts\"]" ] }, { "cell_type": "markdown", "id": "08c457dc", "metadata": {}, "source": [ "Well, what a masterpiece of a mess! Let's break down what is happening here.\n", "First, let's look at the straightforward components of this beast:\n", "\n", "`[CH3][CH0;!$(C(-[O,NH2,$([NH][CH3]),$([NH][CH2]),$([NH0]([CH3])[CH3]),$([NH0]([CH3])[CH2]),$([NH0]([CH2])[CH2])])=O)]=O`\n", "\n", "We can dissect it into three main parts:\n", "* `[CH3]`: The methyl group. Simple enough. This is directly bonded to the logical nightmare in the middle.\n", "* `[CH0; with a lot of conditions]`: The carbonyl carbon, which contains all the protective constraints.\n", "* `=O`: The double bond connecting the carbonyl carbon to its oxygen.\n", "\n", "The entire challenge lies in decoding the environmental conditions imposed on that central carbonyl carbon:\n", "\n", "`[CH0;!$(C(-[O,NH2,...])=O)]`\n", "\n", "Here, we are applying the structural filter we just learned: `[CH0;!$()]`\n", "(\"This is a carbonyl carbon, **AND IT MUST NOT** match the following\n", "environments\"). \n", "\n", "Essentially, we are telling RDKit: *\"It is a carbonyl, but it cannot be bonded\n", "to X, or Y, or Z.\"* Let's look at what we are excluding:\n", "\n", "* `-[O...]`: The carbonyl carbon must **not** have a single bond to an oxygen.\n", " If it did, this group would actually be an **ester** or a **carboxylic\n", " acid**. We definitely don't want a ketone pattern falsely triggering there.\n", "* `NH2`, `[NH][CH3]`, `[NH][CH2]`, ...: These represent the various amide\n", " patterns parameterized within this UNIFAC model. Above all, we want to\n", " prevent molecules that *should* be resolved as amides from prematurely\n", " converging into a ketone due to a multiplicity of valid matching paths. By\n", " explicitly excluding these environments, we ensure that the more specific\n", " amide group takes priority, preventing the simpler ketone pattern from\n", " cannibalizing its atoms.\n", "\n", "This is a prime example of how the presence of other functional groups within a\n", "model can force you to transform a straightforward SMARTS pattern into a highly\n", "complex, defensive one. Of course, you could still define the ketone as easily\n", "as we saw at the beginning—but only if you don't mind dealing with the chaos of\n", "multiple overlapping solutions and prioritization errors later on during the\n", "fragmentation process." ] }, { "cell_type": "markdown", "id": "ff034bd3", "metadata": {}, "source": [ "#### Link-nodes\n", "\n", "`ugropy` supports Chemaxon-style **link-nodes**, though it implements them in a\n", "custom way to fit its `.csv` storage format. For a deeper dive into the theory,\n", "please check the official Chemaxon documentation, or inspect the\n", "`abdulelah_gani` model definitions for real-world examples of how this is\n", "structured:" ] }, { "cell_type": "code", "execution_count": 107, "id": "8510e8c9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'[CH0;$([CH0]([OH])=O)][CX4H2;!R][CH0;$([CH0]([OH])=O)] LN:1:3.20:2'" ] }, "execution_count": 107, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from ugropy import abdulelah_gani\n", "\n", "# Inspecting a link-node pattern in the Gani model\n", "abdulelah_gani.tertiary_model.subgroups.iloc[0][\"smarts\"]" ] }, { "cell_type": "markdown", "id": "a75adc05", "metadata": {}, "source": [ "Since RDKit does not natively support link-nodes infinitely, `ugropy` expands\n", "these custom definitions up to a user-defined threshold.\n", "\n", "When writing these patterns, you must specify an upper limit for the repetition\n", "size that you consider large enough for your systems. Keep in mind that there\n", "is an inherent trade-off: **the larger the repetition limits, the higher the\n", "computational cost** during the substructure detection phase." ] } ], "metadata": { "kernelspec": { "display_name": "ugropy", "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.13" } }, "nbformat": 4, "nbformat_minor": 5 }