1# 2# Copyright (c) 2013, Novartis Institutes for BioMedical Research Inc. 3# Copyright (c) 2021, Greg Landrum 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are 8# met: 9# 10# * Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# * Redistributions in binary form must reproduce the above 13# copyright notice, this list of conditions and the following 14# disclaimer in the documentation and/or other materials provided 15# with the distribution. 16# * Neither the name of Novartis Institutes for BioMedical Research Inc. 17# nor the names of its contributors may be used to endorse or promote 18# products derived from this software without specific prior written permission. 19# 20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31# 32# Created by Sereina Riniker, Aug 2013 33""" unit testing code for molecule drawing 34""" 35 36import sys 37import unittest 38import os 39from rdkit import Chem 40from rdkit.RDLogger import logger 41import platform 42try: 43 import matplotlib 44 if platform.system() == "Linux": 45 if not os.environ.get("DISPLAY", None): 46 # Force matplotlib to not use any Xwindows backend. 47 print("Forcing use of Agg renderer", file=sys.stderr) 48 matplotlib.use('Agg') 49except ImportError: 50 matplotlib = None 51 52from rdkit.Chem import Draw 53from rdkit.Chem.Draw import SimilarityMaps as sm 54try: 55 from rdkit.Chem.Draw.mplCanvas import Canvas 56except RuntimeError: 57 Canvas = None 58except ImportError: 59 Canvas = None 60 61logger = logger() 62 63 64class TestCase(unittest.TestCase): 65 66 def setUp(self): 67 self.mol1 = Chem.MolFromSmiles('c1ccccc1') 68 self.mol2 = Chem.MolFromSmiles('c1ccncc1') 69 70 @unittest.skipUnless(Canvas, 'Matplotlib required') 71 def testSimilarityMap(self): 72 # Morgan2 BV 73 refWeights = [0.5, 0.5, 0.5, -0.5, 0.5, 0.5] 74 weights = sm.GetAtomicWeightsForFingerprint( 75 self.mol1, self.mol2, lambda m, i: sm.GetMorganFingerprint(m, i, radius=2, fpType='bv')) 76 for w, r in zip(weights, refWeights): 77 self.assertEqual(w, r) 78 79 _, maxWeight = sm.GetSimilarityMapForFingerprint( 80 self.mol1, self.mol2, lambda m, i: sm.GetMorganFingerprint(m, i, radius=2, fpType='bv')) 81 self.assertEqual(maxWeight, 0.5) 82 83 weights, maxWeight = sm.GetStandardizedWeights(weights) 84 self.assertEqual(maxWeight, 0.5) 85 refWeights = [1.0, 1.0, 1.0, -1.0, 1.0, 1.0] 86 for w, r in zip(weights, refWeights): 87 self.assertEqual(w, r) 88 89 weights = sm.GetAtomicWeightsForFingerprint( 90 self.mol1, self.mol2, lambda m, i: sm.GetMorganFingerprint(m, i, fpType='count')) 91 self.assertTrue(weights[3] < 0) 92 weights = sm.GetAtomicWeightsForFingerprint( 93 self.mol1, self.mol2, 94 lambda m, i: sm.GetMorganFingerprint(m, i, fpType='bv', useFeatures=True)) 95 self.assertTrue(weights[3] < 0) 96 97 # hashed AP BV 98 refWeights = [0.09523, 0.17366, 0.17366, -0.23809, 0.17366, 0.17366] 99 weights = sm.GetAtomicWeightsForFingerprint( 100 self.mol1, self.mol2, lambda m, i: sm.GetAPFingerprint(m, i, fpType='bv', nBits=1024)) 101 for w, r in zip(weights, refWeights): 102 self.assertAlmostEqual(w, r, 4) 103 104 weights = sm.GetAtomicWeightsForFingerprint( 105 self.mol1, self.mol2, lambda m, i: sm.GetAPFingerprint(m, i, fpType='normal')) 106 self.assertTrue(weights[3] < 0) 107 weights = sm.GetAtomicWeightsForFingerprint( 108 self.mol1, self.mol2, lambda m, i: sm.GetAPFingerprint(m, i, fpType='hashed')) 109 self.assertTrue(weights[3] < 0) 110 111 # hashed TT BV 112 refWeights = [0.5, 0.5, -0.16666, -0.5, -0.16666, 0.5] 113 weights = sm.GetAtomicWeightsForFingerprint( 114 self.mol1, self.mol2, 115 lambda m, i: sm.GetTTFingerprint(m, i, fpType='bv', nBits=1024, nBitsPerEntry=1)) 116 for w, r in zip(weights, refWeights): 117 self.assertAlmostEqual(w, r, 4) 118 119 weights = sm.GetAtomicWeightsForFingerprint( 120 self.mol1, self.mol2, lambda m, i: sm.GetTTFingerprint(m, i, fpType='normal')) 121 self.assertTrue(weights[3] < 0) 122 weights = sm.GetAtomicWeightsForFingerprint( 123 self.mol1, self.mol2, lambda m, i: sm.GetTTFingerprint(m, i, fpType='hashed')) 124 self.assertTrue(weights[3] < 0) 125 126 # RDK fingerprint BV 127 refWeights = [0.42105, 0.42105, 0.42105, -0.32895, 0.42105, 0.42105] 128 weights = sm.GetAtomicWeightsForFingerprint( 129 self.mol1, self.mol2, lambda m, i: sm.GetRDKFingerprint(m, i, nBits=1024, nBitsPerHash=1)) 130 for w, r in zip(weights, refWeights): 131 self.assertAlmostEqual(w, r, 4) 132 133 @unittest.skipUnless(Canvas, 'Matplotlib required') 134 def testSimilarityMapKWArgs(self): 135 # Morgan2 BV 136 m1 = Chem.MolFromSmiles('CC[C@](F)(Cl)c1ccccc1') 137 m2 = Chem.MolFromSmiles('CC[C@@](F)(Cl)c1ccccc1') 138 weights = sm.GetAtomicWeightsForFingerprint( 139 m1, m2, lambda m, i: sm.GetAPFingerprint(m, atomId=i, includeChirality=False)) 140 for w in weights: 141 self.assertAlmostEqual(w, 0.100, 4) 142 weights = sm.GetAtomicWeightsForFingerprint( 143 m1, m2, lambda m, i: sm.GetAPFingerprint(m, atomId=i, includeChirality=True)) 144 for i, w in enumerate(weights): 145 if i != 2: 146 self.assertAlmostEqual(w, 0.098, 3) 147 else: 148 self.assertAlmostEqual(w, -0.082, 3) 149 150 weights = sm.GetAtomicWeightsForFingerprint( 151 m1, m2, lambda m, i: sm.GetTTFingerprint(m, atomId=i, includeChirality=False)) 152 for w in weights: 153 self.assertTrue(w > 0.0) 154 weights = sm.GetAtomicWeightsForFingerprint( 155 m1, m2, lambda m, i: sm.GetTTFingerprint(m, atomId=i, includeChirality=True)) 156 for i, w in enumerate(weights): 157 if i > 4: 158 self.assertTrue(w > 0.0) 159 else: 160 self.assertTrue(w < 0.0) 161 162 weights = sm.GetAtomicWeightsForFingerprint( 163 m1, m2, lambda m, i: sm.GetMorganFingerprint(m, radius=1, atomId=i, useChirality=False)) 164 weights2 = sm.GetAtomicWeightsForFingerprint( 165 m1, m2, lambda m, i: sm.GetMorganFingerprint(m, radius=1, atomId=i, useChirality=True)) 166 # testing explicit values here seems silly, just check that the contribution of the 167 # chiral center drops: 168 self.assertTrue(weights[2] > weights2[2]) 169 170 def testSimilarityMapsMolDraw2D(self): 171 # nothing really sensible to test here, just make sure things run 172 mol = Chem.MolFromSmiles('COc1cccc2cc(C(=O)NCCCCN3CCN(c4cccc5nccnc54)CC3)oc21') 173 refmol = Chem.MolFromSmiles('CCCN(CCCCN1CCN(c2ccccc2OC)CC1)Cc1ccc2ccccc2c1') 174 d = Draw.MolDraw2DSVG(400, 400) 175 d.ClearDrawing() 176 _, maxWeight = sm.GetSimilarityMapForFingerprint( 177 refmol, mol, lambda m, i: sm.GetMorganFingerprint(m, i, radius=2, fpType='bv'), draw2d=d) 178 d.FinishDrawing() 179 with open('similarityMap1_out.svg', 'w+') as outf: 180 outf.write(d.GetDrawingText()) 181 182 # Github #2904: make sure we can provide our own colormap as a list: 183 colors = [(0, 1, 0, 0.5), (1, 1, 1), (0, 0, 1, 0.5)] 184 d = Draw.MolDraw2DSVG(400, 400) 185 d.ClearDrawing() 186 _, maxWeight = sm.GetSimilarityMapForFingerprint( 187 refmol, mol, lambda m, i: sm.GetMorganFingerprint(m, i, radius=2, fpType='bv'), draw2d=d, 188 colorMap=colors) 189 d.FinishDrawing() 190 with open('similarityMap1_out2.svg', 'w+') as outf: 191 outf.write(d.GetDrawingText()) 192 193 # Github #2904: make sure we can provide our own colormap as a matplotlib colormap: 194 try: 195 from matplotlib import cm 196 d = Draw.MolDraw2DSVG(400, 400) 197 d.ClearDrawing() 198 _, maxWeight = sm.GetSimilarityMapForFingerprint( 199 refmol, mol, lambda m, i: sm.GetMorganFingerprint(m, i, radius=2, fpType='bv'), draw2d=d, 200 colorMap=cm.PiYG) 201 d.FinishDrawing() 202 with open('similarityMap1_out3.svg', 'w+') as outf: 203 outf.write(d.GetDrawingText()) 204 except ImportError: 205 pass 206 207 208if __name__ == '__main__': 209 try: 210 import matplotlib 211 from rdkit.Chem.Draw.mplCanvas import Canvas 212 except ImportError: 213 pass 214 except RuntimeError: # happens with GTK can't initialize 215 pass 216 else: 217 unittest.main() 218