Depicting Molecular Properties

Problem

You want to visualize molecules with their properties in order to identify the ones that can be considered as drug-like. In this example five of such properties are calculated and color coded in a property pie (see example in Table 1):

  • MW – molecular weight
  • XLogP – octanol/water partition coefficient
  • TPSA – topological polar surface area
  • Sol – solubility
  • Rof5 – Lipinski rules [Lipinski-1997]

When hovering over the slices of the property pie, more information can be reveled about the properties (and the color gradients that are used to visualize them). Each property is colored similarly: red color indicates that the property is outside the desired range while green color indicates drug-likeness.

Table 1. Examples of molecule with property pie
../_images/properties2img-01-colorg.svg
../_images/properties2img-01-labels.svg

Ingredients

Difficulty level

../_images/chilly1.png ../_images/chilly1.png ../_images/chilly1.png

Download

Download code

properties2img.py

See also Usage subsection.

Solution

The five properties that are depicted in this example are calculated using MolProp TK that is designed eliminate inappropriate or undesirable compounds from a large set based on user-defined criteria such as physical properties, functional group content or molecular topology.

While MolProp TK has been designed for filtering molecules, there is a way (even thought it is not straightforward) to access the calculated properties that are used during the filtering process. First the filter rule has to be defined (see get_filter_rules).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def get_filter_rules():

    FILTER_RULES = """
# This file defines the rules for filtering multi-structure files based on
# properties and substructure patterns.

MIN_MOLWT      130       "Minimum molecular weight"
MAX_MOLWT      781       "Maximum molecular weight"

MIN_XLOGP      -3.0      "Minimum XLogP"
MAX_XLOGP       6.85     "Maximum XLogP"

PSA_USE_SandP   false    "Count S and P as polar atoms"
MIN_2D_PSA      0.0      "Minimum 2-Dimensional (SMILES) Polar Surface Area"
MAX_2D_PSA      205.0    "Maximum 2-Dimensional (SMILES) Polar Surface Area"

# choices are insoluble<poorly<moderately<soluble<very<highly
MIN_SOLUBILITY insoluble "Minimum solubility"

MIN_LIPINSKI_DONORS  0      "Minimum number of hydrogens on O & N atoms"
MAX_LIPINSKI_DONORS  6      "Maximum number of hydrogens on O & N atoms"

MIN_LIPINSKI_ACCEPTORS  1   "Minimum number of oxygen & nitrogen atoms"
MAX_LIPINSKI_ACCEPTORS  14  "Maximum number of oxygen & nitrogen atoms"

MAX_LIPINSKI   3         "Maximum number of Lipinski violations"
"""
    return FILTER_RULES

Note

The minimum and maximum values associated with properties in get_filter_rules are irrelevant in this example since we are not going to use MolProp TK as a filtering tool.

See also

The OEFilter object then can be initialized to calculate the properties defined in the filter rule file (see line 3-4). When passing a molecule into the OEFilter object (see line 16) it returns whether or not the molecule satisfies all the requirements:

if filter(mol):
   # pass
else
   # reject

In this example we do not use the return value, but rather access the calculated properties that are return in an output stream that are associated with the filter object (see line 9-11). The rest of the code is just parsing the results that are returned in a format similar to this:

SMILES                                        molecular weight XLogP Solubility  2d PSA Lipinski violations Filter
Cc1ccc2c(c1O)NC(C3CC(=CN3C2=O)/C=C/C(=O)N)O   315.32           -1.28 moderately  115.89 0                   Pass
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def set_properties(mol, properties):

    ifs = oechem.oeisstream(get_filter_rules())
    filter = oemolprop.OEFilter(ifs)

    level = oechem.OEThrow.GetLevel()
    oechem.OEThrow.SetLevel(oechem.OEErrorLevel_Warning)

    ostr = oechem.oeosstream()
    pwnd = False
    filter.SetTable(ostr, pwnd)

    headers = ostr.str().split(b'\t')
    ostr.clear()  # remove the header row from the stream

    filter(mol)

    fields = ostr.str().decode("UTF-8").split('\t')
    ostr.clear()  # remove this row from the stream

    filterdict = dict(zip(headers, fields))

    for prop in properties:
        if prop.GetFilterName() in filterdict:
            prop.SetValue(filterdict[prop.GetFilterName()])

    oechem.OEThrow.SetLevel(level)

After the properties are calculated the following code snippet illustrates how the properties are visualized with the hover effect in an SVG image file format. In order to add either a hover or a toggle effect to an image SVG group are utilized. You can generate an SVG group for an image by calling the OEImageBase.NewSVGGroup method. In the example below two groups are generated for each property. These two groups are associated by calling the OEAddSVGHover function: while hovering the mouse over objects drawn inside the area_group the objects drawn in the hover_group are displayed. Everything that is rendered between the OEImageBase.PushGroup and the corresponding OEImageBase.PopGroup methods is considered “inside” the group.

Note

The OEAddSVGHover function should always be called prior to pushing / popping the OESVGGroup objects.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
    bgnangle, endangle = 0.0, incangle

    group_prefix = 'property_hover_'
    for prop in properties:
        area_group = image.NewSVGGroup(prop.GetId())
        hover_group = image.NewSVGGroup(group_prefix + prop.GetId())
        oedepict.OEAddSVGHover(area_group, hover_group)

        image.PushGroup(area_group)
        draw_property_pie(pframe, prop, center, bgnangle, bgnangle + incangle, radius)
        image.PopGroup(area_group)

        image.PushGroup(hover_group)
        labeltext = '{} = {}'.format(prop.GetLabel(), prop.GetOrigValue())
        if colorgradient:
            draw_property_color_gradient(cframe, prop, labeltext)
        else:
            draw_property_label(image, prop, labeltext)
        image.PopGroup(hover_group)

Usage

Usage

properties2img.py

The following commands will generate the image shown on the left shown in Table 1.

prompt > echo "Cc1ccc2c(c1O)NC(C3CC(=CN3C2=O)/C=C/C(=O)N)O" > input.ism
prompt > python3 properties2img.py -in input.ism -out property.svg -colorgradient

See also in OEChem TK manual

API

See also in MolProp TK manual

Theory

API

See also in OEDepict TK manual

Theory

API

See also in GraphemeTM TK manual

API