Macs in Chemistry

Insanely great science

 

Scripting Vortex 19 (Updated)

It is clear from many publications that a number of physicochemical properties influence central nervous system (CNS) penetration and it is often possible to play off one property against another in an effort to improve CNS penetration. An interesting paper from Wagner et al Moving beyond Rules: The Development of a Central Nervous System Multiparameter Optimization (CNS MPO) Approach To Enable Alignment of Druglike Properties describes an algorithm to score compounds with respect to CNS penetration.

The CNS MPO score was built based on six fundamental physicochemical properties: ClogP, ClogD, MW, TPSA, HBD, and pKa each weighted from 0 to 1.0 and most desirable and least desirable ranges for each physicochemical property is displayed in the table below.

Property Transformation (T0) Weight More desirable range (T0 = 1.0) Less desirable range (T0 = 0.0)
ClogP monotonic decreasing 1.0 ClogP <= 3 ClogP > 5
ClogD monotonic decreasing 1.0 ClogD <= 2 ClogD > 4
MW monotonic decreasing 1.0 MW <= 360 MW> 500
TPSA hump function 1.0 40 < TPSA <= 90 TPSA <= 20; TPSA > 120
HBD monotonic decreasing 1.0 HBD <= 0.5 HBD > 3.5
pKa monotonic decreasing 1.0 pKa <= 8 pKa > 10

The calculated physicochemical properties used in the paper were obtained using a selection commercial packages: Biobyte for ClogP calculations, ACD/Laboratories for ClogD at pH 7.4, and ACD/Laboratories for pKa. TPSA was calculated using a sum of fragment-based contributions methodology described by in J. Med. Chem. 43, 3714–3717..

It is important to note that changing the package used to calculate the physicochemical properties will render the subsequent calculations unreliable.

The script relies on workspace containing the correctly calculated properties in columns entitled MW, cLogP, TPSA, cLogD, HBD, PKA, the script first creates new columns for calculated to be inserted into.

# Create columns

collogPscore = vtable.findColumnWithName("LogPScore", 1, 1)
collogDscore = vtable.findColumnWithName("LogDScore", 1, 1)

It then calculates the individual scores for each property using the logic described in the paper, shown below for cLogP,

col = vtable.findColumnWithName('cLogP', 0)
rows = vtable.getRealRowCount()
for r in range(0, int(rows)):
    taskID = col.getValue(r)
    if taskID <3:
        TheScore = 1
    elif taskID < 5:
            TheScore = 1-(taskID-3)/2   
        elif taskID > 5:
    TheScore = 0        
    column = vtable.findColumnWithName('LogPScore', 0)
    column.setDouble(r, TheScore)

Finally the composite score is calculated and the worksheet updated as shown in the image below.

Updated to include colour formatting columns

One of the popular features in Vortex is to colour code columns, this is done automatically but sometimes you want to customise the colouring. For example in one set of values smaller values might be better, in another column (perhaps an off-target activity) larger numbers might be better. Chatting to Sune Askjær, the author of the Unichem Script, it seemed that this might be a nice addition to this script.

Setting the colouring scheme is done on each individual column. You have 3 options: ColoringMode 0 = the default heat map (min value green high value red) ColoringMode 1 = Custom colour in simple mode, the one you get on the first pane in the Configure.. menu when you right click a column and select 'Coloring'. ColoringMode 2 = Custom color in advanced mode,  the second pane in Coloring > Configure menu. This one you need to by hand in the GUI and then export as a large string that you then have in you code.

If you whant the advanced scheme it is probably best of setting it by hand and then getting the full coloring scheme string for that column and store it as a string that you can then apply to the column in your script. See the screen shot below.

advColour

Once you have a colour scheme you like you can then get the code by typing in the Vortex terminal,

color = c3.getColorScheme()
color

color ='minExpression=-0.01;maxExpression=0.5;minColor=0xff0000;maxColor=0xffff00;log=false|minExpression=0.5;maxExpression=1;minColor=0xffff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false'

You can then set the colour scheme in the script.

column.setColoringMode(2)
column.setColorScheme(color)

This screenshot shows the original colour scheme

CNSscoreResults

The screenshot below shows the same worksheet with the new colour scheme applied.

colorScheme

I’ve calculated the CNSscore for the 119 drugs described in the publication and the plot below shows the comparison with the CNS MPO results from the publication, the minor differences appear to be due to differences in rounding results.

CNSscore

Whilst there are several algorithms for predicting brain penetration one nice feature of this implementation is that it is possible to see how each of the six different physicochemical properties contribute to the overall score.

The Vortex Script


# Created by Chris Swain http://www.macinchem.org
# Based on
# Moving beyond Rules: The Development of a Central Nervous System Multiparameter Optimization (CNS MPO) Approach To Enable Alignment of Druglike Properties
# DOI: 10.1021/cn100008c |ACS Chem. Neurosci. (2010), 1, 435449

import sys


sys.path.append(vortex.getVortexFolder() + '/modules/jythonlib')

import subprocess

# Create columns

collogPscore = vtable.findColumnWithName("LogPScore", 1, 1)
collogDscore = vtable.findColumnWithName("LogDScore", 1, 1)
colMwtscore = vtable.findColumnWithName("MWtScore", 1, 1)
colTPSAscore = vtable.findColumnWithName("TPSAScore", 1, 1)
colHBDscore = vtable.findColumnWithName("HBDScore", 1, 1)
colPKascore = vtable.findColumnWithName("PkaScore", 1, 1)
colPCNSscore = vtable.findColumnWithName("CNSScore", 1, 1)

# Colourscheme for formatting
color ='minExpression=-0.01;maxExpression=0.5;minColor=0xff0000;maxColor=0xffff00;log=false|minExpression=0.5;maxExpression=1;minColor=0xffff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false'

# Colourscheme for TotalScore
colorTot ='minExpression=0;maxExpression=3;minColor=0xff0000;maxColor=0xffff00;log=false|minExpression=3;maxExpression=6;minColor=0xffff00;maxColor=0x00ff00;log=false| minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|    minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false|minExpression=;maxExpression=;minColor=0x00ff00;maxColor=0x00ff00;log=false'


# Calculate scores

# if(logP 3,1,if(logP >5,0,1((logP3)/2)))

col = vtable.findColumnWithName('cLogP', 0)
rows = vtable.getRealRowCount()
for r in range(0, int(rows)):
    taskID = col.getValue(r)
    if taskID <3:
        TheScore = 1
    elif taskID < 5:
            TheScore = 1-(taskID-3)/2   
        elif taskID > 5:
    TheScore = 0        
    column = vtable.findColumnWithName('LogPScore', 0)
    column.setDouble(r, TheScore)
column.setColoringMode(2)
column.setColorScheme(color)

# IF(C11<2,1,IF(C11>4,0,1((C11-2)/2)))

col = vtable.findColumnWithName('cLogD', 0)
rows = vtable.getRealRowCount()
for r in range(0, int(rows)):
    taskID = col.getValue(r)
    if taskID <2:
        TheScore = 1
    elif taskID < 4:
        TheScore = 1-(taskID-2)/2   
    elif taskID > 4:
        TheScore = 0        
    column = vtable.findColumnWithName('LogDScore', 0)
    column.setDouble(r, TheScore)
column.setColoringMode(2)
column.setColorScheme(color)

#   MWtScore=if_else(${Mass}<360,1,if_else(${Mass}>500,0,1-((${Mass}-360)/140)))

col = vtable.findColumnWithName('MW', 0)
rows = vtable.getRealRowCount()
for r in range(0, int(rows)):
    taskID = col.getValue(r)
    if taskID <360:
        TheScore = 1
    elif taskID < 500:
        TheScore = 1-(taskID-360)/140   
    elif taskID > 500:
        TheScore = 0        
    column = vtable.findColumnWithName('MWtScore', 0)
    column.setDouble(r, TheScore)
column.setColoringMode(2)
column.setColorScheme(color)

# IF(E11<20,0,IF(E11<40,((E1120)20),IF(E1190,1,IF(E11120,(1(E1190)30),0)))) 

col = vtable.findColumnWithName('TPSA', 0)
rows = vtable.getRealRowCount()
for r in range(0, int(rows)):
    taskID = col.getValue(r)
    if taskID <20:
        TheScore = 0
    elif taskID < 40:
        TheScore = (taskID-20)/20   
    elif taskID < 90:
        TheScore = 1
    elif taskID < 120:
        TheScore = 1 -(taskID -90)/30
    elif taskID >120:
        TheScore = 0            
    column = vtable.findColumnWithName('TPSAScore', 0)
    column.setDouble(r, TheScore)
column.setColoringMode(2)
column.setColorScheme(color)

# IF(F110.5,1,IF(F11>3.5,0,1((F110.5)3)))

col = vtable.findColumnWithName('HBD', 0)
rows = vtable.getRealRowCount()
for r in range(0, int(rows)):
    taskID = col.getValue(r)
    if taskID <0.5:
        TheScore = 1
    elif taskID < 3.5:
        TheScore = 1-(taskID-0.5)/3 
    elif taskID > 3.5:
        TheScore = 0        
    column = vtable.findColumnWithName('HBDScore', 0)
    column.setDouble(r, TheScore)
column.setColoringMode(2)
column.setColorScheme(color)

# IF(G118,1,IF(G11>10,0,1((G118)2)))

col = vtable.findColumnWithName('PKA', 0)
rows = vtable.getRealRowCount()
for r in range(0, int(rows)):
    taskID = col.getValue(r)
    if taskID <8:
        TheScore = 1
    elif taskID <= 10:
        TheScore = 1-(taskID-8)/2   
    elif taskID > 10:
        TheScore = 0        
    column = vtable.findColumnWithName('PkaScore', 0)
    column.setDouble(r, TheScore)
column.setColoringMode(2)
column.setColorScheme(color)

# Calc total score

rows = vtable.getRealRowCount()
for r in range(0, int(rows)):
    col = vtable.findColumnWithName('LogPScore', 0)
    logPscore = col.getValue(r)
    col = vtable.findColumnWithName('LogDScore', 0)
    logDscore = col.getValue(r)
    col = vtable.findColumnWithName('MWtScore', 0)
    Mwtscore = col.getValue(r)
    col = vtable.findColumnWithName('TPSAScore', 0)
    tpsascore = col.getValue(r)
    col = vtable.findColumnWithName('HBDScore', 0)
    hbdscore = col.getValue(r)
    col = vtable.findColumnWithName('PkaScore', 0)
    pkascore = col.getValue(r)



    TotalScore = logPscore + logDscore + Mwtscore + tpsascore + hbdscore +pkascore
    column = vtable.findColumnWithName('CNSScore', 0)
    column.setDouble(r, TotalScore)
column.setColoringMode(2)
column.setColorScheme(colorTot)

vtable.fireTableStructureChanged()

The script can be downloaded from here CNScalcFromPropsintTable.vpy.zip

Page Updated 9 June 2014