1# 2# Copyright (C) 2003-2021 Greg Landrum and Rational Discovery LLC 3# All Rights Reserved 4# 5""" This is a rough coverage test of the python wrapper 6 7it's intended to be shallow, but broad 8 9""" 10 11import os, sys, tempfile, gzip, gc 12import unittest, doctest 13from datetime import datetime, timedelta 14from rdkit import RDConfig, rdBase 15from rdkit import DataStructs 16from rdkit import Chem 17import rdkit.Chem.rdDepictor 18from rdkit.Chem import rdqueries 19import tempfile 20from rdkit import __version__ 21 22# Boost functions are NOT found by doctest, this "fixes" them 23# by adding the doctests to a fake module 24import importlib.util 25spec = importlib.util.spec_from_loader("TestReplaceCore", loader=None) 26TestReplaceCore = importlib.util.module_from_spec(spec) 27code = """ 28from rdkit.Chem import ReplaceCore 29def ReplaceCore(*a, **kw): 30 '''%s 31 ''' 32 return Chem.ReplaceCore(*a, **kw) 33""" % "\n".join([x.lstrip() for x in Chem.ReplaceCore.__doc__.split("\n")]) 34exec(code, TestReplaceCore.__dict__) 35 36 37def load_tests(loader, tests, ignore): 38 tests.addTests(doctest.DocTestSuite(TestReplaceCore)) 39 return tests 40 41 42def feq(v1, v2, tol2=1e-4): 43 return abs(v1 - v2) <= tol2 44 45 46def getTotalFormalCharge(mol): 47 totalFormalCharge = 0 48 for atom in mol.GetAtoms(): 49 totalFormalCharge += atom.GetFormalCharge() 50 return totalFormalCharge 51 52 53def cmpFormalChargeBondOrder(self, mol1, mol2): 54 self.assertEqual(mol1.GetNumAtoms(), mol2.GetNumAtoms()) 55 self.assertEqual(mol1.GetNumBonds(), mol2.GetNumBonds()) 56 for i in range(mol1.GetNumAtoms()): 57 self.assertEqual( 58 mol1.GetAtomWithIdx(i).GetFormalCharge(), 59 mol2.GetAtomWithIdx(i).GetFormalCharge()) 60 for i in range(mol1.GetNumBonds()): 61 self.assertEqual(mol1.GetBondWithIdx(i).GetBondType(), mol2.GetBondWithIdx(i).GetBondType()) 62 63 64def setResidueFormalCharge(mol, res, fc): 65 for query in res: 66 matches = mol.GetSubstructMatches(query) 67 for match in matches: 68 mol.GetAtomWithIdx(match[-1]).SetFormalCharge(fc) 69 70 71def getBtList2(resMolSuppl): 72 btList2 = [] 73 while (not resMolSuppl.atEnd()): 74 resMol = next(resMolSuppl) 75 bt = [] 76 for bond in resMol.GetBonds(): 77 bt.append(int(bond.GetBondTypeAsDouble())) 78 btList2.append(bt) 79 for i in range(len(btList2)): 80 same = True 81 for j in range(len(btList2[i])): 82 if (not i): 83 continue 84 if (same): 85 same = (btList2[i][j] == btList2[i - 1][j]) 86 if (i and same): 87 return None 88 return btList2 89 90 91class TestCase(unittest.TestCase): 92 93 def test0Except(self): 94 95 with self.assertRaises(IndexError): 96 Chem.tossit() 97 98 def test1Table(self): 99 100 tbl = Chem.GetPeriodicTable() 101 self.assertTrue(tbl) 102 103 self.assertTrue(feq(tbl.GetAtomicWeight(6), 12.011)) 104 self.assertTrue(feq(tbl.GetAtomicWeight("C"), 12.011)) 105 self.assertTrue(tbl.GetAtomicNumber('C') == 6) 106 self.assertTrue(feq(tbl.GetRvdw(6), 1.7)) 107 self.assertTrue(feq(tbl.GetRvdw("C"), 1.7)) 108 self.assertTrue(feq(tbl.GetRcovalent(6), 0.680)) 109 self.assertTrue(feq(tbl.GetRcovalent("C"), 0.680)) 110 self.assertTrue(tbl.GetDefaultValence(6) == 4) 111 self.assertTrue(tbl.GetDefaultValence("C") == 4) 112 self.assertTrue(tuple(tbl.GetValenceList(6)) == (4, )) 113 self.assertTrue(tuple(tbl.GetValenceList("C")) == (4, )) 114 self.assertTrue(tuple(tbl.GetValenceList(16)) == (2, 4, 6)) 115 self.assertTrue(tuple(tbl.GetValenceList("S")) == (2, 4, 6)) 116 self.assertTrue(tbl.GetNOuterElecs(6) == 4) 117 self.assertTrue(tbl.GetNOuterElecs("C") == 4) 118 self.assertTrue(tbl.GetMostCommonIsotope(6) == 12) 119 self.assertTrue(tbl.GetMostCommonIsotope('C') == 12) 120 self.assertTrue(tbl.GetMostCommonIsotopeMass(6) == 12.0) 121 self.assertTrue(tbl.GetMostCommonIsotopeMass('C') == 12.0) 122 self.assertTrue(tbl.GetAbundanceForIsotope(6, 12) == 98.93) 123 self.assertTrue(tbl.GetAbundanceForIsotope('C', 12) == 98.93) 124 self.assertTrue(feq(tbl.GetRb0(6), 0.77)) 125 self.assertTrue(feq(tbl.GetRb0("C"), 0.77)) 126 self.assertTrue(tbl.GetElementSymbol(6) == 'C') 127 128 def test2Atom(self): 129 atom = Chem.Atom(6) 130 self.assertTrue(atom) 131 self.assertTrue(atom.GetAtomicNum() == 6) 132 atom.SetAtomicNum(8) 133 self.assertTrue(atom.GetAtomicNum() == 8) 134 135 atom = Chem.Atom("C") 136 self.assertTrue(atom) 137 self.assertTrue(atom.GetAtomicNum() == 6) 138 139 def test3Bond(self): 140 # No longer relevant, bonds are not constructible from Python 141 pass 142 143 def test4Mol(self): 144 mol = Chem.Mol() 145 self.assertTrue(mol) 146 147 def test5Smiles(self): 148 mol = Chem.MolFromSmiles('n1ccccc1') 149 self.assertTrue(mol) 150 self.assertTrue(mol.GetNumAtoms() == 6) 151 self.assertTrue(mol.GetNumAtoms(1) == 6) 152 self.assertTrue(mol.GetNumAtoms(0) == 11) 153 at = mol.GetAtomWithIdx(2) 154 self.assertTrue(at.GetAtomicNum() == 6) 155 at = mol.GetAtomWithIdx(0) 156 self.assertTrue(at.GetAtomicNum() == 7) 157 158 def _test6Bookmarks(self): 159 mol = Chem.MolFromSmiles('n1ccccc1') 160 self.assertTrue(mol) 161 162 self.assertTrue(not mol.HasAtomBookmark(0)) 163 mol.SetAtomBookmark(mol.GetAtomWithIdx(0), 0) 164 mol.SetAtomBookmark(mol.GetAtomWithIdx(1), 1) 165 self.assertTrue(mol.HasAtomBookmark(0)) 166 self.assertTrue(mol.HasAtomBookmark(1)) 167 168 if 1: 169 self.assertTrue(not mol.HasBondBookmark(0)) 170 self.assertTrue(not mol.HasBondBookmark(1)) 171 mol.SetBondBookmark(mol.GetBondWithIdx(0), 0) 172 mol.SetBondBookmark(mol.GetBondWithIdx(1), 1) 173 self.assertTrue(mol.HasBondBookmark(0)) 174 self.assertTrue(mol.HasBondBookmark(1)) 175 176 at = mol.GetAtomWithBookmark(0) 177 self.assertTrue(at) 178 self.assertTrue(at.GetAtomicNum() == 7) 179 mol.ClearAtomBookmark(0) 180 self.assertTrue(not mol.HasAtomBookmark(0)) 181 self.assertTrue(mol.HasAtomBookmark(1)) 182 mol.ClearAllAtomBookmarks() 183 self.assertTrue(not mol.HasAtomBookmark(0)) 184 self.assertTrue(not mol.HasAtomBookmark(1)) 185 186 mol.SetAtomBookmark(mol.GetAtomWithIdx(1), 1) 187 188 if 1: 189 self.assertTrue(mol.HasBondBookmark(0)) 190 self.assertTrue(mol.HasBondBookmark(1)) 191 bond = mol.GetBondWithBookmark(0) 192 self.assertTrue(bond) 193 mol.ClearBondBookmark(0) 194 self.assertTrue(not mol.HasBondBookmark(0)) 195 self.assertTrue(mol.HasBondBookmark(1)) 196 mol.ClearAllBondBookmarks() 197 self.assertTrue(not mol.HasBondBookmark(0)) 198 self.assertTrue(not mol.HasBondBookmark(1)) 199 200 self.assertTrue(mol.HasAtomBookmark(1)) 201 202 def test7Atom(self): 203 mol = Chem.MolFromSmiles('n1ccccc1C[CH2-]') 204 self.assertTrue(mol) 205 Chem.SanitizeMol(mol) 206 a0 = mol.GetAtomWithIdx(0) 207 a1 = mol.GetAtomWithIdx(1) 208 a6 = mol.GetAtomWithIdx(6) 209 a7 = mol.GetAtomWithIdx(7) 210 211 self.assertTrue(a0.GetAtomicNum() == 7) 212 self.assertTrue(a0.GetSymbol() == 'N') 213 self.assertTrue(a0.GetIdx() == 0) 214 215 aList = [a0, a1, a6, a7] 216 self.assertTrue(a0.GetDegree() == 2) 217 self.assertTrue(a1.GetDegree() == 2) 218 self.assertTrue(a6.GetDegree() == 2) 219 self.assertTrue(a7.GetDegree() == 1) 220 self.assertTrue([x.GetDegree() for x in aList] == [2, 2, 2, 1]) 221 222 self.assertTrue([x.GetTotalNumHs() for x in aList] == [0, 1, 2, 2]) 223 self.assertTrue([x.GetNumImplicitHs() for x in aList] == [0, 1, 2, 0]) 224 self.assertTrue([x.GetExplicitValence() for x in aList] == [3, 3, 2, 3]) 225 self.assertTrue([x.GetImplicitValence() for x in aList] == [0, 1, 2, 0]) 226 self.assertTrue([x.GetFormalCharge() for x in aList] == [0, 0, 0, -1]) 227 self.assertTrue([x.GetNoImplicit() for x in aList] == [0, 0, 0, 1]) 228 self.assertTrue([x.GetNumExplicitHs() for x in aList] == [0, 0, 0, 2]) 229 self.assertTrue([x.GetIsAromatic() for x in aList] == [1, 1, 0, 0]) 230 self.assertTrue([x.GetHybridization() for x in aList]==[Chem.HybridizationType.SP2,Chem.HybridizationType.SP2, 231 Chem.HybridizationType.SP3,Chem.HybridizationType.SP3],\ 232 [x.GetHybridization() for x in aList]) 233 234 def test8Bond(self): 235 mol = Chem.MolFromSmiles('n1ccccc1CC(=O)O') 236 self.assertTrue(mol) 237 Chem.SanitizeMol(mol) 238 # note bond numbering is funny because of ring closure 239 b0 = mol.GetBondWithIdx(0) 240 b6 = mol.GetBondWithIdx(6) 241 b7 = mol.GetBondWithIdx(7) 242 b8 = mol.GetBondWithIdx(8) 243 244 bList = [b0, b6, b7, b8] 245 self.assertTrue( 246 [x.GetBondType() for x in bList] == 247 [Chem.BondType.AROMATIC, Chem.BondType.SINGLE, Chem.BondType.DOUBLE, Chem.BondType.SINGLE]) 248 self.assertTrue([x.GetIsAromatic() for x in bList] == [1, 0, 0, 0]) 249 self.assertEqual(bList[0].GetBondTypeAsDouble(), 1.5) 250 self.assertEqual(bList[1].GetBondTypeAsDouble(), 1.0) 251 self.assertEqual(bList[2].GetBondTypeAsDouble(), 2.0) 252 253 self.assertTrue([x.GetIsConjugated() != 0 for x in bList] == [1, 0, 1, 1], 254 [x.GetIsConjugated() != 0 for x in bList]) 255 self.assertTrue([x.GetBeginAtomIdx() for x in bList] == [0, 6, 7, 7], 256 [x.GetBeginAtomIdx() for x in bList]) 257 self.assertTrue([x.GetBeginAtom().GetIdx() for x in bList] == [0, 6, 7, 7]) 258 self.assertTrue([x.GetEndAtomIdx() for x in bList] == [1, 7, 8, 9]) 259 self.assertTrue([x.GetEndAtom().GetIdx() for x in bList] == [1, 7, 8, 9]) 260 261 def test9Smarts(self): 262 query1 = Chem.MolFromSmarts('C(=O)O') 263 self.assertTrue(query1) 264 query2 = Chem.MolFromSmarts('C(=O)[O,N]') 265 self.assertTrue(query2) 266 query3 = Chem.MolFromSmarts('[$(C(=O)O)]') 267 self.assertTrue(query3) 268 269 mol = Chem.MolFromSmiles('CCC(=O)O') 270 self.assertTrue(mol) 271 272 self.assertTrue(mol.HasSubstructMatch(query1)) 273 self.assertTrue(mol.HasSubstructMatch(query2)) 274 self.assertTrue(mol.HasSubstructMatch(query3)) 275 276 mol = Chem.MolFromSmiles('CCC(=O)N') 277 self.assertTrue(mol) 278 279 self.assertTrue(not mol.HasSubstructMatch(query1)) 280 self.assertTrue(mol.HasSubstructMatch(query2)) 281 self.assertTrue(not mol.HasSubstructMatch(query3)) 282 283 def test10Iterators(self): 284 mol = Chem.MolFromSmiles('CCOC') 285 self.assertTrue(mol) 286 287 for atom in mol.GetAtoms(): 288 self.assertTrue(atom) 289 ats = mol.GetAtoms() 290 ats[1] 291 with self.assertRaisesRegex(IndexError, ""): 292 ats[12] 293 294 for bond in mol.GetBonds(): 295 self.assertTrue(bond) 296 bonds = mol.GetBonds() 297 bonds[1] 298 with self.assertRaisesRegex(IndexError, ""): 299 bonds[12] 300 301 def test11MolOps(self): 302 mol = Chem.MolFromSmiles('C1=CC=C(C=C1)P(C2=CC=CC=C2)C3=CC=CC=C3') 303 self.assertTrue(mol) 304 smi = Chem.MolToSmiles(mol) 305 Chem.SanitizeMol(mol) 306 nr = Chem.GetSymmSSSR(mol) 307 308 self.assertTrue((len(nr) == 3)) 309 310 def test12Smarts(self): 311 query1 = Chem.MolFromSmarts('C(=O)O') 312 self.assertTrue(query1) 313 query2 = Chem.MolFromSmarts('C(=O)[O,N]') 314 self.assertTrue(query2) 315 query3 = Chem.MolFromSmarts('[$(C(=O)O)]') 316 self.assertTrue(query3) 317 318 mol = Chem.MolFromSmiles('CCC(=O)O') 319 self.assertTrue(mol) 320 321 self.assertTrue(mol.HasSubstructMatch(query1)) 322 self.assertTrue(mol.GetSubstructMatch(query1) == (2, 3, 4)) 323 self.assertTrue(mol.HasSubstructMatch(query2)) 324 self.assertTrue(mol.GetSubstructMatch(query2) == (2, 3, 4)) 325 self.assertTrue(mol.HasSubstructMatch(query3)) 326 self.assertTrue(mol.GetSubstructMatch(query3) == (2, )) 327 328 mol = Chem.MolFromSmiles('CCC(=O)N') 329 self.assertTrue(mol) 330 331 self.assertTrue(not mol.HasSubstructMatch(query1)) 332 self.assertTrue(not mol.GetSubstructMatch(query1)) 333 self.assertTrue(mol.HasSubstructMatch(query2)) 334 self.assertTrue(mol.GetSubstructMatch(query2) == (2, 3, 4)) 335 self.assertTrue(not mol.HasSubstructMatch(query3)) 336 337 mol = Chem.MolFromSmiles('OC(=O)CC(=O)O') 338 self.assertTrue(mol) 339 self.assertTrue(mol.HasSubstructMatch(query1)) 340 self.assertTrue(mol.GetSubstructMatch(query1) == (1, 2, 0)) 341 self.assertTrue(mol.GetSubstructMatches(query1) == ((1, 2, 0), (4, 5, 6))) 342 self.assertTrue(mol.HasSubstructMatch(query2)) 343 self.assertTrue(mol.GetSubstructMatch(query2) == (1, 2, 0)) 344 self.assertTrue(mol.GetSubstructMatches(query2) == ((1, 2, 0), (4, 5, 6))) 345 self.assertTrue(mol.HasSubstructMatch(query3)) 346 self.assertTrue(mol.GetSubstructMatches(query3) == ((1, ), (4, ))) 347 348 def test13Smarts(self): 349 # previous smarts problems: 350 query = Chem.MolFromSmarts('N(=,-C)') 351 self.assertTrue(query) 352 mol = Chem.MolFromSmiles('N#C') 353 self.assertTrue(not mol.HasSubstructMatch(query)) 354 mol = Chem.MolFromSmiles('N=C') 355 self.assertTrue(mol.HasSubstructMatch(query)) 356 mol = Chem.MolFromSmiles('NC') 357 self.assertTrue(mol.HasSubstructMatch(query)) 358 359 query = Chem.MolFromSmarts('[Cl,$(O)]') 360 mol = Chem.MolFromSmiles('C(=O)O') 361 self.assertTrue(len(mol.GetSubstructMatches(query)) == 2) 362 mol = Chem.MolFromSmiles('C(=N)N') 363 self.assertTrue(len(mol.GetSubstructMatches(query)) == 0) 364 365 query = Chem.MolFromSmarts('[$([O,S]-[!$(*=O)])]') 366 mol = Chem.MolFromSmiles('CC(S)C(=O)O') 367 self.assertTrue(len(mol.GetSubstructMatches(query)) == 1) 368 mol = Chem.MolFromSmiles('C(=O)O') 369 self.assertTrue(len(mol.GetSubstructMatches(query)) == 0) 370 371 def test14Hs(self): 372 m = Chem.MolFromSmiles('CC(=O)[OH]') 373 self.assertEqual(m.GetNumAtoms(), 4) 374 m2 = Chem.AddHs(m) 375 self.assertEqual(m2.GetNumAtoms(), 8) 376 m2 = Chem.RemoveHs(m2) 377 self.assertEqual(m2.GetNumAtoms(), 4) 378 379 m = Chem.MolFromSmiles('CC[H]', False) 380 self.assertEqual(m.GetNumAtoms(), 3) 381 m2 = Chem.MergeQueryHs(m) 382 self.assertEqual(m2.GetNumAtoms(), 2) 383 self.assertTrue(m2.GetAtomWithIdx(1).HasQuery()) 384 385 m = Chem.MolFromSmiles('CC[H]', False) 386 self.assertEqual(m.GetNumAtoms(), 3) 387 m1 = Chem.RemoveHs(m) 388 self.assertEqual(m1.GetNumAtoms(), 2) 389 self.assertEqual(m1.GetAtomWithIdx(1).GetNumExplicitHs(), 0) 390 m1 = Chem.RemoveHs(m, updateExplicitCount=True) 391 self.assertEqual(m1.GetNumAtoms(), 2) 392 self.assertEqual(m1.GetAtomWithIdx(1).GetNumExplicitHs(), 1) 393 394 # test merging of mapped hydrogens 395 m = Chem.MolFromSmiles('CC[H]', False) 396 m.GetAtomWithIdx(2).SetProp("molAtomMapNumber", "1") 397 self.assertEqual(m.GetNumAtoms(), 3) 398 m2 = Chem.MergeQueryHs(m, mergeUnmappedOnly=True) 399 self.assertTrue(m2 is not None) 400 self.assertEqual(m2.GetNumAtoms(), 3) 401 self.assertFalse(m2.GetAtomWithIdx(1).HasQuery()) 402 403 # here the hydrogen is unmapped 404 # should be the same as merging all hydrogens 405 m = Chem.MolFromSmiles('CC[H]', False) 406 m.GetAtomWithIdx(1).SetProp("molAtomMapNumber", "1") 407 self.assertEqual(m.GetNumAtoms(), 3) 408 m2 = Chem.MergeQueryHs(m, mergeUnmappedOnly=True) 409 self.assertTrue(m2 is not None) 410 self.assertEqual(m2.GetNumAtoms(), 2) 411 self.assertTrue(m2.GetAtomWithIdx(1).HasQuery()) 412 413 # test github758 414 m = Chem.MolFromSmiles('CCC') 415 self.assertEqual(m.GetNumAtoms(), 3) 416 m = Chem.AddHs(m, onlyOnAtoms=(0, 2)) 417 self.assertEqual(m.GetNumAtoms(), 9) 418 self.assertEqual(m.GetAtomWithIdx(0).GetDegree(), 4) 419 self.assertEqual(m.GetAtomWithIdx(2).GetDegree(), 4) 420 self.assertEqual(m.GetAtomWithIdx(1).GetDegree(), 2) 421 422 def test15Neighbors(self): 423 m = Chem.MolFromSmiles('CC(=O)[OH]') 424 self.assertTrue(m.GetNumAtoms() == 4) 425 426 a = m.GetAtomWithIdx(1) 427 ns = a.GetNeighbors() 428 self.assertTrue(len(ns) == 3) 429 430 bs = a.GetBonds() 431 self.assertTrue(len(bs) == 3) 432 433 for b in bs: 434 try: 435 a2 = b.GetOtherAtom(a) 436 except Exception: 437 a2 = None 438 self.assertTrue(a2) 439 self.assertTrue(len(bs) == 3) 440 441 def test16Pickle(self): 442 import pickle 443 m = Chem.MolFromSmiles('C1=CN=CC=C1') 444 pkl = pickle.dumps(m) 445 m2 = pickle.loads(pkl) 446 self.assertTrue(type(m2) == Chem.Mol) 447 smi1 = Chem.MolToSmiles(m) 448 smi2 = Chem.MolToSmiles(m2) 449 self.assertTrue(smi1 == smi2) 450 451 pkl = pickle.dumps(Chem.RWMol(m)) 452 m2 = pickle.loads(pkl) 453 self.assertTrue(type(m2) == Chem.RWMol) 454 smi1 = Chem.MolToSmiles(m) 455 smi2 = Chem.MolToSmiles(m2) 456 self.assertTrue(smi1 == smi2) 457 458 def test16Props(self): 459 m = Chem.MolFromSmiles('C1=CN=CC=C1') 460 self.assertTrue(not m.HasProp('prop1')) 461 self.assertTrue(not m.HasProp('prop2')) 462 self.assertTrue(not m.HasProp('prop2')) 463 m.SetProp('prop1', 'foob') 464 self.assertTrue(not m.HasProp('prop2')) 465 self.assertTrue(m.HasProp('prop1')) 466 self.assertTrue(m.GetProp('prop1') == 'foob') 467 self.assertTrue(not m.HasProp('propo')) 468 try: 469 m.GetProp('prop2') 470 except KeyError: 471 ok = 1 472 else: 473 ok = 0 474 self.assertTrue(ok) 475 476 # test computed properties 477 m.SetProp('cprop1', 'foo', 1) 478 m.SetProp('cprop2', 'foo2', 1) 479 480 m.ClearComputedProps() 481 self.assertTrue(not m.HasProp('cprop1')) 482 self.assertTrue(not m.HasProp('cprop2')) 483 484 m.SetDoubleProp("a", 2.0) 485 self.assertTrue(m.GetDoubleProp("a") == 2.0) 486 487 try: 488 self.assertTrue(m.GetIntProp("a") == 2.0) 489 raise Exception("Expected runtime exception") 490 except ValueError: 491 pass 492 493 try: 494 self.assertTrue(m.GetUnsignedProp("a") == 2.0) 495 raise Exception("Expected runtime exception") 496 except ValueError: 497 pass 498 499 m.SetDoubleProp("a", -2) 500 self.assertTrue(m.GetDoubleProp("a") == -2.0) 501 m.SetIntProp("a", -2) 502 self.assertTrue(m.GetIntProp("a") == -2) 503 504 try: 505 m.SetUnsignedProp("a", -2) 506 raise Exception("Expected failure with negative unsigned number") 507 except OverflowError: 508 pass 509 510 m.SetBoolProp("a", False) 511 self.assertTrue(m.GetBoolProp("a") == False) 512 513 self.assertEqual(m.GetPropsAsDict(), {'a': False, 'prop1': 'foob'}) 514 m.SetDoubleProp("b", 1000.0) 515 m.SetUnsignedProp("c", 2000) 516 m.SetIntProp("d", -2) 517 m.SetUnsignedProp("e", 2, True) 518 self.assertEqual(m.GetPropsAsDict(False, True), { 519 'a': False, 520 'c': 2000, 521 'b': 1000.0, 522 'e': 2, 523 'd': -2, 524 'prop1': 'foob' 525 }) 526 m = Chem.MolFromSmiles('C1=CN=CC=C1') 527 m.SetProp("int", "1000") 528 m.SetProp("double", "10000.123") 529 self.assertEqual(m.GetPropsAsDict(), {"int": 1000, "double": 10000.123}) 530 531 self.assertEqual(type(m.GetPropsAsDict()['int']), int) 532 self.assertEqual(type(m.GetPropsAsDict()['double']), float) 533 534 def test17Kekulize(self): 535 m = Chem.MolFromSmiles('c1ccccc1') 536 smi = Chem.MolToSmiles(m) 537 self.assertTrue(smi == 'c1ccccc1') 538 539 Chem.Kekulize(m) 540 smi = Chem.MolToSmiles(m) 541 self.assertTrue(smi == 'c1ccccc1') 542 543 m = Chem.MolFromSmiles('c1ccccc1') 544 smi = Chem.MolToSmiles(m) 545 self.assertTrue(smi == 'c1ccccc1') 546 547 Chem.Kekulize(m, 1) 548 smi = Chem.MolToSmiles(m) 549 self.assertTrue(smi == 'C1=CC=CC=C1', smi) 550 551 def test18Paths(self): 552 553 m = Chem.MolFromSmiles("C1CC2C1CC2") 554 #self.assertTrue(len(Chem.FindAllPathsOfLengthN(m,1,useBonds=1))==7) 555 #print(Chem.FindAllPathsOfLengthN(m,3,useBonds=0)) 556 self.assertTrue( 557 len(Chem.FindAllPathsOfLengthN(m, 2, useBonds=1)) == 10, 558 Chem.FindAllPathsOfLengthN(m, 2, useBonds=1)) 559 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 3, useBonds=1)) == 14) 560 561 m = Chem.MolFromSmiles('C1CC1C') 562 self.assertTrue(m) 563 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 1, useBonds=1)) == 4) 564 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 2, useBonds=1)) == 5) 565 self.assertTrue( 566 len(Chem.FindAllPathsOfLengthN(m, 3, useBonds=1)) == 3, 567 Chem.FindAllPathsOfLengthN(m, 3, useBonds=1)) 568 self.assertTrue( 569 len(Chem.FindAllPathsOfLengthN(m, 4, useBonds=1)) == 1, 570 Chem.FindAllPathsOfLengthN(m, 4, useBonds=1)) 571 self.assertTrue( 572 len(Chem.FindAllPathsOfLengthN(m, 5, useBonds=1)) == 0, 573 Chem.FindAllPathsOfLengthN(m, 5, useBonds=1)) 574 575 # 576 # Hexane example from Hall-Kier Rev.Comp.Chem. paper 577 # Rev. Comp. Chem. vol 2, 367-422, (1991) 578 # 579 m = Chem.MolFromSmiles("CCCCCC") 580 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 1, useBonds=1)) == 5) 581 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 2, useBonds=1)) == 4) 582 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 3, useBonds=1)) == 3) 583 584 m = Chem.MolFromSmiles("CCC(C)CC") 585 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 1, useBonds=1)) == 5) 586 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 2, useBonds=1)) == 5) 587 self.assertTrue( 588 len(Chem.FindAllPathsOfLengthN(m, 3, useBonds=1)) == 4, 589 Chem.FindAllPathsOfLengthN(m, 3, useBonds=1)) 590 591 m = Chem.MolFromSmiles("CCCC(C)C") 592 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 1, useBonds=1)) == 5) 593 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 2, useBonds=1)) == 5) 594 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 3, useBonds=1)) == 3) 595 596 m = Chem.MolFromSmiles("CC(C)C(C)C") 597 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 1, useBonds=1)) == 5) 598 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 2, useBonds=1)) == 6) 599 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 3, useBonds=1)) == 4) 600 601 m = Chem.MolFromSmiles("CC(C)(C)CC") 602 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 1, useBonds=1)) == 5) 603 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 2, useBonds=1)) == 7) 604 self.assertTrue( 605 len(Chem.FindAllPathsOfLengthN(m, 3, useBonds=1)) == 3, 606 Chem.FindAllPathsOfLengthN(m, 3, useBonds=1)) 607 608 m = Chem.MolFromSmiles("C1CCCCC1") 609 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 1, useBonds=1)) == 6) 610 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 2, useBonds=1)) == 6) 611 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 3, useBonds=1)) == 6) 612 613 m = Chem.MolFromSmiles("C1CC2C1CC2") 614 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 1, useBonds=1)) == 7) 615 self.assertTrue( 616 len(Chem.FindAllPathsOfLengthN(m, 2, useBonds=1)) == 10, 617 Chem.FindAllPathsOfLengthN(m, 2, useBonds=1)) 618 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 3, useBonds=1)) == 14) 619 620 m = Chem.MolFromSmiles("CC2C1CCC12") 621 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 1, useBonds=1)) == 7) 622 self.assertTrue(len(Chem.FindAllPathsOfLengthN(m, 2, useBonds=1)) == 11) 623 # FIX: this result disagrees with the paper (which says 13), 624 # but it seems right 625 self.assertTrue( 626 len(Chem.FindAllPathsOfLengthN(m, 3, useBonds=1)) == 15, 627 Chem.FindAllPathsOfLengthN(m, 3, useBonds=1)) 628 629 def test19Subgraphs(self): 630 m = Chem.MolFromSmiles('C1CC1C') 631 self.assertTrue(m) 632 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 1, 0)) == 4) 633 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 2)) == 5) 634 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 3)) == 4) 635 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 4)) == 1) 636 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 5)) == 0) 637 638 # 639 # Hexane example from Hall-Kier Rev.Comp.Chem. paper 640 # Rev. Comp. Chem. vol 2, 367-422, (1991) 641 # 642 m = Chem.MolFromSmiles("CCCCCC") 643 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 1)) == 5) 644 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 2)) == 4) 645 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 3)) == 3) 646 647 l = Chem.FindAllSubgraphsOfLengthMToN(m, 1, 3) 648 self.assertEqual(len(l), 3) 649 self.assertEqual(len(l[0]), 5) 650 self.assertEqual(len(l[1]), 4) 651 self.assertEqual(len(l[2]), 3) 652 self.assertRaises(ValueError, lambda: Chem.FindAllSubgraphsOfLengthMToN(m, 4, 3)) 653 654 m = Chem.MolFromSmiles("CCC(C)CC") 655 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 1)) == 5) 656 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 2)) == 5) 657 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 3)) == 5) 658 659 m = Chem.MolFromSmiles("CCCC(C)C") 660 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 1)) == 5) 661 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 2)) == 5) 662 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 3)) == 4) 663 664 m = Chem.MolFromSmiles("CC(C)C(C)C") 665 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 1)) == 5) 666 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 2)) == 6) 667 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 3)) == 6) 668 669 m = Chem.MolFromSmiles("CC(C)(C)CC") 670 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 1)) == 5) 671 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 2)) == 7) 672 self.assertTrue( 673 len(Chem.FindAllSubgraphsOfLengthN(m, 3)) == 7, Chem.FindAllSubgraphsOfLengthN(m, 3)) 674 675 m = Chem.MolFromSmiles("C1CCCCC1") 676 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 1)) == 6) 677 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 2)) == 6) 678 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 3)) == 6) 679 #self.assertTrue(len(Chem.FindUniqueSubgraphsOfLengthN(m,1))==1) 680 self.assertTrue(len(Chem.FindUniqueSubgraphsOfLengthN(m, 2)) == 1) 681 self.assertTrue(len(Chem.FindUniqueSubgraphsOfLengthN(m, 3)) == 1) 682 683 m = Chem.MolFromSmiles("C1CC2C1CC2") 684 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 1)) == 7) 685 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 2)) == 10) 686 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 3)) == 16) 687 688 m = Chem.MolFromSmiles("CC2C1CCC12") 689 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 1)) == 7) 690 self.assertTrue(len(Chem.FindAllSubgraphsOfLengthN(m, 2)) == 11) 691 self.assertTrue( 692 len(Chem.FindAllSubgraphsOfLengthN(m, 3)) == 18, len(Chem.FindAllSubgraphsOfLengthN(m, 3))) 693 694 def test20IsInRing(self): 695 m = Chem.MolFromSmiles('C1CCC1C') 696 self.assertTrue(m) 697 self.assertTrue(m.GetAtomWithIdx(0).IsInRingSize(4)) 698 self.assertTrue(m.GetAtomWithIdx(1).IsInRingSize(4)) 699 self.assertTrue(m.GetAtomWithIdx(2).IsInRingSize(4)) 700 self.assertTrue(m.GetAtomWithIdx(3).IsInRingSize(4)) 701 self.assertTrue(not m.GetAtomWithIdx(4).IsInRingSize(4)) 702 703 self.assertTrue(not m.GetAtomWithIdx(0).IsInRingSize(3)) 704 self.assertTrue(not m.GetAtomWithIdx(1).IsInRingSize(3)) 705 self.assertTrue(not m.GetAtomWithIdx(2).IsInRingSize(3)) 706 self.assertTrue(not m.GetAtomWithIdx(3).IsInRingSize(3)) 707 self.assertTrue(not m.GetAtomWithIdx(4).IsInRingSize(3)) 708 709 self.assertTrue(m.GetBondWithIdx(0).IsInRingSize(4)) 710 self.assertTrue(not m.GetBondWithIdx(3).IsInRingSize(4)) 711 self.assertTrue(not m.GetBondWithIdx(0).IsInRingSize(3)) 712 self.assertTrue(not m.GetBondWithIdx(3).IsInRingSize(3)) 713 714 def test21Robustification(self): 715 ok = False 716 # FIX: at the moment I can't figure out how to catch the 717 # actual exception that BPL is throwing when it gets 718 # invalid arguments (Boost.Python.ArgumentError) 719 try: 720 Chem.MolFromSmiles('C=O').HasSubstructMatch(Chem.MolFromSmarts('fiib')) 721 #except ValueError: 722 # ok=True 723 except Exception: 724 ok = True 725 self.assertTrue(ok) 726 727 def test22DeleteSubstruct(self): 728 query = Chem.MolFromSmarts('C(=O)O') 729 mol = Chem.MolFromSmiles('CCC(=O)O') 730 nmol = Chem.DeleteSubstructs(mol, query) 731 732 self.assertTrue(Chem.MolToSmiles(nmol) == 'CC') 733 734 mol = Chem.MolFromSmiles('CCC(=O)O.O=CO') 735 # now delete only fragments 736 nmol = Chem.DeleteSubstructs(mol, query, 1) 737 self.assertTrue(Chem.MolToSmiles(nmol) == 'CCC(=O)O', Chem.MolToSmiles(nmol)) 738 739 mol = Chem.MolFromSmiles('CCC(=O)O.O=CO') 740 nmol = Chem.DeleteSubstructs(mol, query, 0) 741 self.assertTrue(Chem.MolToSmiles(nmol) == 'CC') 742 743 mol = Chem.MolFromSmiles('CCCO') 744 nmol = Chem.DeleteSubstructs(mol, query, 0) 745 self.assertTrue(Chem.MolToSmiles(nmol) == 'CCCO') 746 747 # Issue 96 prevented this from working: 748 mol = Chem.MolFromSmiles('CCC(=O)O.O=CO') 749 nmol = Chem.DeleteSubstructs(mol, query, 1) 750 self.assertTrue(Chem.MolToSmiles(nmol) == 'CCC(=O)O') 751 nmol = Chem.DeleteSubstructs(nmol, query, 1) 752 self.assertTrue(Chem.MolToSmiles(nmol) == 'CCC(=O)O') 753 nmol = Chem.DeleteSubstructs(nmol, query, 0) 754 self.assertTrue(Chem.MolToSmiles(nmol) == 'CC') 755 756 def test23MolFileParsing(self): 757 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 758 'triazine.mol') 759 #fileN = "../FileParsers/test_data/triazine.mol" 760 with open(fileN, 'r') as inF: 761 inD = inF.read() 762 m1 = Chem.MolFromMolBlock(inD) 763 self.assertTrue(m1 is not None) 764 self.assertTrue(m1.GetNumAtoms() == 9) 765 766 m1 = Chem.MolFromMolFile(fileN) 767 self.assertTrue(m1 is not None) 768 self.assertTrue(m1.GetNumAtoms() == 9) 769 770 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 771 'triazine.mof') 772 self.assertRaises(IOError, lambda: Chem.MolFromMolFile(fileN)) 773 774 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 775 'list-query.mol') 776 query = Chem.MolFromMolFile(fileN) 777 smi = Chem.MolToSmiles(query) 778 self.assertEqual(smi, 'c1ccccc1') 779 smi = Chem.MolToSmarts(query) 780 self.assertEqual(smi, '[#6]1:[#6]:[#6]:[#6]:[#6]:[#6,#7,#15]:1', smi) 781 782 query = Chem.MolFromMolFile(fileN, sanitize=False) 783 smi = Chem.MolToSmiles(query) 784 self.assertEqual(smi, 'C1=CC=CC=C1') 785 query.UpdatePropertyCache() 786 smi = Chem.MolToSmarts(query) 787 self.assertEqual(smi, '[#6]1=[#6]-[#6]=[#6]-[#6]=[#6,#7,#15]-1') 788 smi = "C1=CC=CC=C1" 789 mol = Chem.MolFromSmiles(smi, 0) 790 self.assertTrue(mol.HasSubstructMatch(query)) 791 Chem.SanitizeMol(mol) 792 self.assertTrue(not mol.HasSubstructMatch(query)) 793 794 mol = Chem.MolFromSmiles('N1=CC=CC=C1', 0) 795 self.assertTrue(mol.HasSubstructMatch(query)) 796 mol = Chem.MolFromSmiles('S1=CC=CC=C1', 0) 797 self.assertTrue(not mol.HasSubstructMatch(query)) 798 mol = Chem.MolFromSmiles('P1=CC=CC=C1', 0) 799 self.assertTrue(mol.HasSubstructMatch(query)) 800 801 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 802 'issue123.mol') 803 mol = Chem.MolFromMolFile(fileN) 804 self.assertTrue(mol) 805 self.assertEqual(mol.GetNumAtoms(), 23) 806 mol = Chem.MolFromMolFile(fileN, removeHs=False) 807 self.assertTrue(mol) 808 self.assertEqual(mol.GetNumAtoms(), 39) 809 810 # test23 was for Chem.DaylightFingerprint, which is deprecated 811 812 def test24RDKFingerprint(self): 813 from rdkit import DataStructs 814 m1 = Chem.MolFromSmiles('C1=CC=CC=C1') 815 fp1 = Chem.RDKFingerprint(m1) 816 self.assertTrue(len(fp1) == 2048) 817 m2 = Chem.MolFromSmiles('C1=CC=CC=C1') 818 fp2 = Chem.RDKFingerprint(m2) 819 820 tmp = DataStructs.TanimotoSimilarity(fp1, fp2) 821 self.assertTrue(tmp == 1.0, tmp) 822 823 m2 = Chem.MolFromSmiles('C1=CC=CC=N1') 824 fp2 = Chem.RDKFingerprint(m2) 825 self.assertTrue(len(fp2) == 2048) 826 tmp = DataStructs.TanimotoSimilarity(fp1, fp2) 827 self.assertTrue(tmp < 1.0, tmp) 828 self.assertTrue(tmp > 0.0, tmp) 829 830 fp3 = Chem.RDKFingerprint(m1, tgtDensity=0.3) 831 self.assertTrue(len(fp3) < 2048) 832 833 m1 = Chem.MolFromSmiles('C1=CC=CC=C1') 834 fp1 = Chem.RDKFingerprint(m1) 835 m2 = Chem.MolFromSmiles('C1=CC=CC=N1') 836 fp2 = Chem.RDKFingerprint(m2) 837 self.assertNotEqual(fp1, fp2) 838 839 atomInvariants = [1] * 6 840 fp1 = Chem.RDKFingerprint(m1, atomInvariants=atomInvariants) 841 fp2 = Chem.RDKFingerprint(m2, atomInvariants=atomInvariants) 842 self.assertEqual(fp1, fp2) 843 844 m2 = Chem.MolFromSmiles('C1CCCCN1') 845 fp1 = Chem.RDKFingerprint(m1, atomInvariants=atomInvariants, useBondOrder=False) 846 fp2 = Chem.RDKFingerprint(m2, atomInvariants=atomInvariants, useBondOrder=False) 847 self.assertEqual(fp1, fp2) 848 849 # rooted at atom 850 m1 = Chem.MolFromSmiles('CCCCCO') 851 fp1 = Chem.RDKFingerprint(m1, 1, 4, nBitsPerHash=1, fromAtoms=[0]) 852 self.assertEqual(fp1.GetNumOnBits(), 4) 853 m1 = Chem.MolFromSmiles('CCCCCO') 854 fp1 = Chem.RDKFingerprint(m1, 1, 4, nBitsPerHash=1, fromAtoms=[0, 5]) 855 self.assertEqual(fp1.GetNumOnBits(), 8) 856 857 # test sf.net issue 270: 858 fp1 = Chem.RDKFingerprint(m1, atomInvariants=[x.GetAtomicNum() + 10 for x in m1.GetAtoms()]) 859 860 # atomBits 861 m1 = Chem.MolFromSmiles('CCCO') 862 l = [] 863 fp1 = Chem.RDKFingerprint(m1, minPath=1, maxPath=2, nBitsPerHash=1, atomBits=l) 864 self.assertEqual(fp1.GetNumOnBits(), 4) 865 self.assertEqual(len(l), m1.GetNumAtoms()) 866 self.assertEqual(len(l[0]), 2) 867 self.assertEqual(len(l[1]), 3) 868 self.assertEqual(len(l[2]), 4) 869 self.assertEqual(len(l[3]), 2) 870 871 def test25SDMolSupplier(self): 872 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 873 'NCI_aids_few.sdf') 874 #fileN = "../FileParsers/test_data/NCI_aids_few.sdf" 875 sdSup = Chem.SDMolSupplier(fileN) 876 molNames = [ 877 "48", "78", "128", "163", "164", "170", "180", "186", "192", "203", "210", "211", "213", 878 "220", "229", "256" 879 ] 880 881 chgs192 = {8: 1, 11: 1, 15: -1, 18: -1, 20: 1, 21: 1, 23: -1, 25: -1} 882 i = 0 883 for mol in sdSup: 884 self.assertTrue(mol) 885 self.assertTrue(mol.GetProp("_Name") == molNames[i]) 886 i += 1 887 if (mol.GetProp("_Name") == "192"): 888 # test parsed charges on one of the molecules 889 for id in chgs192.keys(): 890 self.assertTrue(mol.GetAtomWithIdx(id).GetFormalCharge() == chgs192[id]) 891 self.assertRaises(StopIteration, lambda: next(sdSup)) 892 sdSup.reset() 893 894 ns = [mol.GetProp("_Name") for mol in sdSup] 895 self.assertTrue(ns == molNames) 896 897 sdSup = Chem.SDMolSupplier(fileN, 0) 898 for mol in sdSup: 899 self.assertTrue(not mol.HasProp("numArom")) 900 901 sdSup = Chem.SDMolSupplier(fileN) 902 self.assertTrue(len(sdSup) == 16) 903 mol = sdSup[5] 904 self.assertTrue(mol.GetProp("_Name") == "170") 905 906 # test handling of H removal: 907 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 908 'withHs.sdf') 909 sdSup = Chem.SDMolSupplier(fileN) 910 m = next(sdSup) 911 self.assertTrue(m) 912 self.assertTrue(m.GetNumAtoms() == 23) 913 m = next(sdSup) 914 self.assertTrue(m) 915 self.assertTrue(m.GetNumAtoms() == 28) 916 917 sdSup = Chem.SDMolSupplier(fileN, removeHs=False) 918 m = next(sdSup) 919 self.assertTrue(m) 920 self.assertTrue(m.GetNumAtoms() == 39) 921 m = next(sdSup) 922 self.assertTrue(m) 923 self.assertTrue(m.GetNumAtoms() == 30) 924 925 with open(fileN, 'rb') as dFile: 926 d = dFile.read() 927 sdSup.SetData(d) 928 m = next(sdSup) 929 self.assertTrue(m) 930 self.assertTrue(m.GetNumAtoms() == 23) 931 m = next(sdSup) 932 self.assertTrue(m) 933 self.assertTrue(m.GetNumAtoms() == 28) 934 935 sdSup.SetData(d, removeHs=False) 936 m = next(sdSup) 937 self.assertTrue(m) 938 self.assertTrue(m.GetNumAtoms() == 39) 939 m = next(sdSup) 940 self.assertTrue(m) 941 self.assertTrue(m.GetNumAtoms() == 30) 942 943 # test strictParsing1: 944 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 945 'strictLax1.sdf') 946 #strict from file 947 sdSup = Chem.SDMolSupplier(fileN, strictParsing=True) 948 949 i = 0 950 for mol in sdSup: 951 self.assertTrue(mol.HasProp("_Name")) 952 if (i == 0): 953 self.assertTrue(not mol.HasProp("ID")) 954 self.assertTrue(not mol.HasProp("ANOTHER_PROPERTY")) 955 i += 1 956 self.assertTrue(i == 2) 957 958 #lax from file 959 sdSup = Chem.SDMolSupplier(fileN, strictParsing=False) 960 961 i = 0 962 for mol in sdSup: 963 self.assertTrue(mol.HasProp("_Name")) 964 self.assertTrue(mol.HasProp("ID")) 965 self.assertTrue(mol.HasProp("ANOTHER_PROPERTY")) 966 i += 1 967 self.assertTrue(i == 2) 968 969 #strict from text 970 with open(fileN, 'rb') as dFile: 971 d = dFile.read() 972 sdSup = Chem.SDMolSupplier() 973 sdSup.SetData(d, strictParsing=True) 974 975 i = 0 976 for mol in sdSup: 977 self.assertTrue(mol.HasProp("_Name")) 978 if (i == 0): 979 self.assertTrue(not mol.HasProp("ID")) 980 self.assertTrue(not mol.HasProp("ANOTHER_PROPERTY")) 981 i += 1 982 self.assertTrue(i == 2) 983 984 #lax from text 985 sdSup = Chem.SDMolSupplier() 986 sdSup.SetData(d, strictParsing=False) 987 988 i = 0 989 for mol in sdSup: 990 self.assertTrue(mol.HasProp("_Name")) 991 self.assertTrue(mol.HasProp("ID")) 992 self.assertTrue(mol.HasProp("ANOTHER_PROPERTY")) 993 i += 1 994 self.assertTrue(i == 2) 995 996 # test strictParsing2: 997 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 998 'strictLax2.sdf') 999 #strict from file 1000 sdSup = Chem.SDMolSupplier(fileN, strictParsing=True) 1001 1002 i = 0 1003 for mol in sdSup: 1004 self.assertTrue(mol.HasProp("_Name")) 1005 self.assertTrue(mol.HasProp("ID")) 1006 self.assertTrue(mol.GetProp("ID") == "Lig1") 1007 self.assertTrue(mol.HasProp("ANOTHER_PROPERTY")) 1008 self.assertTrue(mol.GetProp("ANOTHER_PROPERTY") == \ 1009 "No blank line before dollars\n" \ 1010 "$$$$\n" \ 1011 "Structure1\n" \ 1012 "csChFnd70/05230312262D") 1013 i += 1 1014 self.assertTrue(i == 1) 1015 1016 #lax from file 1017 sdSup = Chem.SDMolSupplier(fileN, strictParsing=False) 1018 1019 i = 0 1020 for mol in sdSup: 1021 self.assertTrue(mol.HasProp("_Name")) 1022 self.assertTrue(mol.HasProp("ID")) 1023 self.assertTrue(mol.GetProp("ID") == "Lig2") 1024 self.assertTrue(mol.HasProp("ANOTHER_PROPERTY")) 1025 self.assertTrue(mol.GetProp("ANOTHER_PROPERTY") == "Value2") 1026 i += 1 1027 self.assertTrue(i == 1) 1028 1029 #strict from text 1030 with open(fileN, 'rb') as dFile: 1031 d = dFile.read() 1032 sdSup = Chem.SDMolSupplier() 1033 sdSup.SetData(d, strictParsing=True) 1034 1035 i = 0 1036 for mol in sdSup: 1037 self.assertTrue(mol.HasProp("_Name")) 1038 self.assertTrue(mol.HasProp("ID")) 1039 self.assertTrue(mol.GetProp("ID") == "Lig1") 1040 self.assertTrue(mol.HasProp("ANOTHER_PROPERTY")) 1041 self.assertTrue(mol.GetProp("ANOTHER_PROPERTY") == \ 1042 "No blank line before dollars\n" \ 1043 "$$$$\n" \ 1044 "Structure1\n" \ 1045 "csChFnd70/05230312262D") 1046 i += 1 1047 self.assertTrue(i == 1) 1048 1049 #lax from text 1050 sdSup = Chem.SDMolSupplier() 1051 sdSup.SetData(d, strictParsing=False) 1052 1053 i = 0 1054 for mol in sdSup: 1055 self.assertTrue(mol.HasProp("_Name")) 1056 self.assertTrue(mol.HasProp("ID")) 1057 self.assertTrue(mol.GetProp("ID") == "Lig2") 1058 self.assertTrue(mol.HasProp("ANOTHER_PROPERTY")) 1059 self.assertTrue(mol.GetProp("ANOTHER_PROPERTY") == "Value2") 1060 i += 1 1061 self.assertTrue(i == 1) 1062 1063 def test26SmiMolSupplier(self): 1064 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 1065 'first_200.tpsa.csv') 1066 #fileN = "../FileParsers/test_data/first_200.tpsa.csv" 1067 smiSup = Chem.SmilesMolSupplier(fileN, ",", 0, -1) 1068 mol = smiSup[16] 1069 self.assertTrue(mol.GetProp("TPSA") == "46.25") 1070 1071 mol = smiSup[8] 1072 self.assertTrue(mol.GetProp("TPSA") == "65.18") 1073 1074 self.assertTrue(len(smiSup) == 200) 1075 1076 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 1077 'fewSmi.csv') 1078 #fileN = "../FileParsers/test_data/fewSmi.csv" 1079 smiSup = Chem.SmilesMolSupplier(fileN, delimiter=",", smilesColumn=1, nameColumn=0, titleLine=0) 1080 names = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"] 1081 i = 0 1082 for mol in smiSup: 1083 self.assertTrue(mol.GetProp("_Name") == names[i]) 1084 i += 1 1085 1086 mol = smiSup[3] 1087 1088 self.assertTrue(mol.GetProp("_Name") == "4") 1089 self.assertTrue(mol.GetProp("Column_2") == "82.78") 1090 1091 # and test doing a supplier from text: 1092 with open(fileN, 'r') as inF: 1093 inD = inF.read() 1094 smiSup.SetData(inD, delimiter=",", smilesColumn=1, nameColumn=0, titleLine=0) 1095 names = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"] 1096 i = 0 1097 # iteration interface: 1098 for mol in smiSup: 1099 self.assertTrue(mol.GetProp("_Name") == names[i]) 1100 i += 1 1101 self.assertTrue(i == 10) 1102 # random access: 1103 mol = smiSup[3] 1104 self.assertTrue(len(smiSup) == 10) 1105 self.assertTrue(mol.GetProp("_Name") == "4") 1106 self.assertTrue(mol.GetProp("Column_2") == "82.78") 1107 1108 # issue 113: 1109 smiSup.SetData(inD, delimiter=",", smilesColumn=1, nameColumn=0, titleLine=0) 1110 self.assertTrue(len(smiSup) == 10) 1111 1112 # and test failure handling: 1113 inD = """mol-1,CCC 1114mol-2,CCCC 1115mol-3,fail 1116mol-4,CCOC 1117 """ 1118 smiSup.SetData(inD, delimiter=",", smilesColumn=1, nameColumn=0, titleLine=0) 1119 # there are 4 entries in the supplier: 1120 self.assertTrue(len(smiSup) == 4) 1121 # but the 3rd is a None: 1122 self.assertTrue(smiSup[2] is None) 1123 1124 1125 text="Id SMILES Column_2\n"+\ 1126 "mol-1 C 1.0\n"+\ 1127 "mol-2 CC 4.0\n"+\ 1128 "mol-4 CCCC 16.0" 1129 smiSup.SetData(text, delimiter=" ", smilesColumn=1, nameColumn=0, titleLine=1) 1130 self.assertTrue(len(smiSup) == 3) 1131 self.assertTrue(smiSup[0]) 1132 self.assertTrue(smiSup[1]) 1133 self.assertTrue(smiSup[2]) 1134 m = [x for x in smiSup] 1135 self.assertTrue(smiSup[2]) 1136 self.assertTrue(len(m) == 3) 1137 self.assertTrue(m[0].GetProp("Column_2") == "1.0") 1138 1139 # test simple parsing and Issue 114: 1140 smis = ['CC', 'CCC', 'CCOC', 'CCCOCC', 'CCCOCCC'] 1141 inD = '\n'.join(smis) 1142 smiSup.SetData(inD, delimiter=",", smilesColumn=0, nameColumn=-1, titleLine=0) 1143 self.assertTrue(len(smiSup) == 5) 1144 m = [x for x in smiSup] 1145 self.assertTrue(smiSup[4]) 1146 self.assertTrue(len(m) == 5) 1147 1148 # order dependence: 1149 smiSup.SetData(inD, delimiter=",", smilesColumn=0, nameColumn=-1, titleLine=0) 1150 self.assertTrue(smiSup[4]) 1151 self.assertTrue(len(smiSup) == 5) 1152 1153 # this was a nasty BC: 1154 # asking for a particular entry with a higher index than what we've 1155 # already seen resulted in a duplicate: 1156 smis = ['CC', 'CCC', 'CCOC', 'CCCCOC'] 1157 inD = '\n'.join(smis) 1158 smiSup.SetData(inD, delimiter=",", smilesColumn=0, nameColumn=-1, titleLine=0) 1159 m = next(smiSup) 1160 m = smiSup[3] 1161 self.assertTrue(len(smiSup) == 4) 1162 1163 with self.assertRaisesRegex(Exception, ""): 1164 smiSup[4] 1165 1166 smiSup.SetData(inD, delimiter=",", smilesColumn=0, nameColumn=-1, titleLine=0) 1167 with self.assertRaisesRegex(Exception, ""): 1168 smiSup[4] 1169 1170 sys.stderr.write( 1171 '>>> This may result in an infinite loop. It should finish almost instantly\n') 1172 self.assertEqual(len(smiSup), 4) 1173 sys.stderr.write('<<< OK, it finished.\n') 1174 1175 def test27SmilesWriter(self): 1176 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 1177 'fewSmi.csv') 1178 #fileN = "../FileParsers/test_data/fewSmi.csv" 1179 1180 smiSup = Chem.SmilesMolSupplier(fileN, delimiter=",", smilesColumn=1, nameColumn=0, titleLine=0) 1181 propNames = [] 1182 propNames.append("Column_2") 1183 ofile = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'Wrap', 'test_data', 1184 'outSmiles.txt') 1185 writer = Chem.SmilesWriter(ofile) 1186 writer.SetProps(propNames) 1187 for mol in smiSup: 1188 writer.write(mol) 1189 writer.flush() 1190 1191 def test28SmilesReverse(self): 1192 names = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"] 1193 props = [ 1194 "34.14", "25.78", "106.51", "82.78", "60.16", "87.74", "37.38", "77.28", "65.18", "0.00" 1195 ] 1196 ofile = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'Wrap', 'test_data', 1197 'outSmiles.txt') 1198 #ofile = "test_data/outSmiles.csv" 1199 smiSup = Chem.SmilesMolSupplier(ofile) 1200 i = 0 1201 for mol in smiSup: 1202 #print([repr(x) for x in mol.GetPropNames()]) 1203 self.assertTrue(mol.GetProp("_Name") == names[i]) 1204 self.assertTrue(mol.GetProp("Column_2") == props[i]) 1205 i += 1 1206 1207 def writerSDFile(self): 1208 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 1209 'NCI_aids_few.sdf') 1210 #fileN = "../FileParsers/test_data/NCI_aids_few.sdf" 1211 ofile = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'Wrap', 'test_data', 1212 'outNCI_few.sdf') 1213 writer = Chem.SDWriter(ofile) 1214 sdSup = Chem.SDMolSupplier(fileN) 1215 for mol in sdSup: 1216 writer.write(mol) 1217 writer.flush() 1218 1219 def test29SDWriterLoop(self): 1220 self.writerSDFile() 1221 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'Wrap', 'test_data', 1222 'outNCI_few.sdf') 1223 sdSup = Chem.SDMolSupplier(fileN) 1224 molNames = [ 1225 "48", "78", "128", "163", "164", "170", "180", "186", "192", "203", "210", "211", "213", 1226 "220", "229", "256" 1227 ] 1228 chgs192 = {8: 1, 11: 1, 15: -1, 18: -1, 20: 1, 21: 1, 23: -1, 25: -1} 1229 i = 0 1230 1231 for mol in sdSup: 1232 #print('mol:',mol) 1233 #print('\t',molNames[i]) 1234 self.assertTrue(mol.GetProp("_Name") == molNames[i]) 1235 i += 1 1236 if (mol.GetProp("_Name") == "192"): 1237 # test parsed charges on one of the molecules 1238 for id in chgs192.keys(): 1239 self.assertTrue(mol.GetAtomWithIdx(id).GetFormalCharge() == chgs192[id]) 1240 1241 def test30Issues109and110(self): 1242 """ issues 110 and 109 were both related to handling of explicit Hs in 1243 SMILES input. 1244 1245 """ 1246 m1 = Chem.MolFromSmiles('N12[CH](SC(C)(C)[CH]1C(O)=O)[CH](C2=O)NC(=O)[CH](N)c3ccccc3') 1247 self.assertTrue(m1.GetNumAtoms() == 24) 1248 m2 = Chem.MolFromSmiles( 1249 'C1C=C([CH](N)C(=O)N[C]2([H])[C]3([H])SC(C)(C)[CH](C(=O)O)N3C(=O)2)C=CC=1') 1250 self.assertTrue(m2.GetNumAtoms() == 24) 1251 1252 smi1 = Chem.MolToSmiles(m1) 1253 smi2 = Chem.MolToSmiles(m2) 1254 self.assertTrue(smi1 == smi2) 1255 1256 m1 = Chem.MolFromSmiles('[H]CCl') 1257 self.assertTrue(m1.GetNumAtoms() == 2) 1258 self.assertTrue(m1.GetAtomWithIdx(0).GetNumExplicitHs() == 1) 1259 m1 = Chem.MolFromSmiles('[H][CH2]Cl') 1260 self.assertTrue(m1.GetNumAtoms() == 2) 1261 self.assertTrue(m1.GetAtomWithIdx(0).GetNumExplicitHs() == 3) 1262 m2 = Chem.AddHs(m1) 1263 self.assertTrue(m2.GetNumAtoms() == 5) 1264 m2 = Chem.RemoveHs(m2) 1265 self.assertTrue(m2.GetNumAtoms() == 2) 1266 1267 def test31ChiralitySmiles(self): 1268 m1 = Chem.MolFromSmiles('F[C@](Br)(I)Cl') 1269 self.assertTrue(m1 is not None) 1270 self.assertTrue(m1.GetNumAtoms() == 5) 1271 self.assertTrue(Chem.MolToSmiles(m1, 1) == 'F[C@](Cl)(Br)I', Chem.MolToSmiles(m1, 1)) 1272 1273 m1 = Chem.MolFromSmiles('CC1C[C@@]1(Cl)F') 1274 self.assertTrue(m1 is not None) 1275 self.assertTrue(m1.GetNumAtoms() == 6) 1276 self.assertTrue(Chem.MolToSmiles(m1, 1) == 'CC1C[C@]1(F)Cl', Chem.MolToSmiles(m1, 1)) 1277 1278 m1 = Chem.MolFromSmiles('CC1C[C@]1(Cl)F') 1279 self.assertTrue(m1 is not None) 1280 self.assertTrue(m1.GetNumAtoms() == 6) 1281 self.assertTrue(Chem.MolToSmiles(m1, 1) == 'CC1C[C@@]1(F)Cl', Chem.MolToSmiles(m1, 1)) 1282 1283 def test31aChiralitySubstructs(self): 1284 m1 = Chem.MolFromSmiles('CC1C[C@@]1(Cl)F') 1285 self.assertTrue(m1 is not None) 1286 self.assertTrue(m1.GetNumAtoms() == 6) 1287 self.assertTrue(Chem.MolToSmiles(m1, 1) == 'CC1C[C@]1(F)Cl', Chem.MolToSmiles(m1, 1)) 1288 1289 m2 = Chem.MolFromSmiles('CC1C[C@]1(Cl)F') 1290 self.assertTrue(m2 is not None) 1291 self.assertTrue(m2.GetNumAtoms() == 6) 1292 self.assertTrue(Chem.MolToSmiles(m2, 1) == 'CC1C[C@@]1(F)Cl', Chem.MolToSmiles(m2, 1)) 1293 1294 self.assertTrue(m1.HasSubstructMatch(m1)) 1295 self.assertTrue(m1.HasSubstructMatch(m2)) 1296 self.assertTrue(m1.HasSubstructMatch(m1, useChirality=True)) 1297 self.assertTrue(not m1.HasSubstructMatch(m2, useChirality=True)) 1298 1299 def _test32MolFilesWithChirality(self): 1300 inD = """chiral1.mol 1301 ChemDraw10160313232D 1302 1303 5 4 0 0 0 0 0 0 0 0999 V2000 1304 0.0553 0.6188 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 1305 0.0553 -0.2062 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1306 0.7697 -0.6188 0.0000 I 0 0 0 0 0 0 0 0 0 0 0 0 1307 -0.6592 -0.6188 0.0000 Br 0 0 0 0 0 0 0 0 0 0 0 0 1308 -0.7697 -0.2062 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 1309 1 2 1 0 1310 2 3 1 0 1311 2 4 1 1 1312 2 5 1 0 1313M END 1314""" 1315 m1 = Chem.MolFromMolBlock(inD) 1316 self.assertTrue(m1 is not None) 1317 self.assertTrue(m1.GetNumAtoms() == 5) 1318 self.assertTrue(smi == 'F[C@](Cl)(Br)I', smi) 1319 1320 inD = """chiral2.cdxml 1321 ChemDraw10160314052D 1322 1323 5 4 0 0 0 0 0 0 0 0999 V2000 1324 0.0553 0.6188 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 1325 0.0553 -0.2062 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1326 0.7697 -0.6188 0.0000 I 0 0 0 0 0 0 0 0 0 0 0 0 1327 -0.6592 -0.6188 0.0000 Br 0 0 0 0 0 0 0 0 0 0 0 0 1328 -0.7697 -0.2062 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 1329 1 2 1 0 1330 2 3 1 0 1331 2 4 1 6 1332 2 5 1 0 1333M END 1334""" 1335 m1 = Chem.MolFromMolBlock(inD) 1336 self.assertTrue(m1 is not None) 1337 self.assertTrue(m1.GetNumAtoms() == 5) 1338 self.assertTrue(Chem.MolToSmiles(m1, 1) == 'F[C@@](Cl)(Br)I') 1339 1340 inD = """chiral1.mol 1341 ChemDraw10160313232D 1342 1343 5 4 0 0 0 0 0 0 0 0999 V2000 1344 0.0553 0.6188 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 1345 0.0553 -0.2062 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1346 -0.7697 -0.2062 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 1347 -0.6592 -0.6188 0.0000 Br 0 0 0 0 0 0 0 0 0 0 0 0 1348 0.7697 -0.6188 0.0000 I 0 0 0 0 0 0 0 0 0 0 0 0 1349 1 2 1 0 1350 2 3 1 0 1351 2 4 1 1 1352 2 5 1 0 1353M END 1354""" 1355 m1 = Chem.MolFromMolBlock(inD) 1356 self.assertTrue(m1 is not None) 1357 self.assertTrue(m1.GetNumAtoms() == 5) 1358 self.assertTrue(Chem.MolToSmiles(m1, 1) == 'F[C@](Cl)(Br)I') 1359 1360 inD = """chiral1.mol 1361 ChemDraw10160313232D 1362 1363 5 4 0 0 0 0 0 0 0 0999 V2000 1364 0.0553 -0.2062 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1365 -0.7697 -0.2062 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 1366 -0.6592 -0.6188 0.0000 Br 0 0 0 0 0 0 0 0 0 0 0 0 1367 0.7697 -0.6188 0.0000 I 0 0 0 0 0 0 0 0 0 0 0 0 1368 0.0553 0.6188 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 1369 1 2 1 0 1370 1 3 1 1 1371 1 4 1 0 1372 1 5 1 0 1373M END 1374""" 1375 m1 = Chem.MolFromMolBlock(inD) 1376 self.assertTrue(m1 is not None) 1377 self.assertTrue(m1.GetNumAtoms() == 5) 1378 self.assertTrue(Chem.MolToSmiles(m1, 1) == 'F[C@](Cl)(Br)I') 1379 1380 inD = """chiral3.mol 1381 ChemDraw10160314362D 1382 1383 4 3 0 0 0 0 0 0 0 0999 V2000 1384 0.4125 0.6188 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 1385 0.4125 -0.2062 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1386 -0.3020 -0.6188 0.0000 Br 0 0 0 0 0 0 0 0 0 0 0 0 1387 -0.4125 -0.2062 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 1388 1 2 1 0 1389 2 3 1 1 1390 2 4 1 0 1391M END 1392 1393""" 1394 m1 = Chem.MolFromMolBlock(inD) 1395 self.assertTrue(m1 is not None) 1396 self.assertTrue(m1.GetNumAtoms() == 4) 1397 self.assertTrue(Chem.MolToSmiles(m1, 1) == 'F[C@H](Cl)Br') 1398 1399 inD = """chiral4.mol 1400 ChemDraw10160314362D 1401 1402 4 3 0 0 0 0 0 0 0 0999 V2000 1403 0.4125 0.6188 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 1404 0.4125 -0.2062 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1405 -0.3020 -0.6188 0.0000 Br 0 0 0 0 0 0 0 0 0 0 0 0 1406 -0.4125 -0.2062 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 1407 1 2 1 0 1408 2 3 1 1 1409 2 4 1 0 1410M END 1411 1412""" 1413 m1 = Chem.MolFromMolBlock(inD) 1414 self.assertTrue(m1 is not None) 1415 self.assertTrue(m1.GetNumAtoms() == 4) 1416 self.assertTrue(Chem.MolToSmiles(m1, 1) == 'FN(Cl)Br') 1417 1418 inD = """chiral5.mol 1419 ChemDraw10160314362D 1420 1421 4 3 0 0 0 0 0 0 0 0999 V2000 1422 0.4125 0.6188 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 1423 0.4125 -0.2062 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 1424 -0.3020 -0.6188 0.0000 Br 0 0 0 0 0 0 0 0 0 0 0 0 1425 -0.4125 -0.2062 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 1426 1 2 1 0 1427 2 3 1 1 1428 2 4 1 0 1429M CHG 1 2 1 1430M END 1431 1432""" 1433 m1 = Chem.MolFromMolBlock(inD) 1434 self.assertTrue(m1 is not None) 1435 self.assertTrue(m1.GetNumAtoms() == 4) 1436 self.assertTrue(Chem.MolToSmiles(m1, 1) == 'F[N@H+](Cl)Br') 1437 1438 inD = """Case 10-14-3 1439 ChemDraw10140308512D 1440 1441 4 3 0 0 0 0 0 0 0 0999 V2000 1442 -0.8250 -0.4125 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 1443 0.0000 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1444 0.8250 -0.4125 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 1445 0.0000 0.4125 0.0000 Br 0 0 0 0 0 0 0 0 0 0 0 0 1446 1 2 1 0 1447 2 3 1 0 1448 2 4 1 1 1449M END 1450""" 1451 m1 = Chem.MolFromMolBlock(inD) 1452 self.assertTrue(m1 is not None) 1453 self.assertTrue(m1.GetNumAtoms() == 4) 1454 self.assertTrue(Chem.MolToSmiles(m1, 1) == 'F[C@H](Cl)Br') 1455 1456 inD = """Case 10-14-4 1457 ChemDraw10140308512D 1458 1459 4 3 0 0 0 0 0 0 0 0999 V2000 1460 -0.8250 -0.4125 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 1461 0.0000 -0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1462 0.8250 -0.4125 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 1463 0.0000 0.4125 0.0000 Br 0 0 0 0 0 0 0 0 0 0 0 0 1464 1 2 1 0 1465 2 3 1 1 1466 2 4 1 0 1467M END 1468 1469""" 1470 m1 = Chem.MolFromMolBlock(inD) 1471 self.assertTrue(m1 is not None) 1472 self.assertTrue(m1.GetNumAtoms() == 4) 1473 self.assertTrue(Chem.MolToSmiles(m1, 1) == 'F[C@H](Cl)Br') 1474 1475 inD = """chiral4.mol 1476 ChemDraw10160315172D 1477 1478 6 6 0 0 0 0 0 0 0 0999 V2000 1479 -0.4422 0.1402 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1480 -0.4422 -0.6848 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1481 0.2723 -0.2723 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1482 -0.8547 0.8547 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1483 0.6848 0.4422 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 1484 0.8547 -0.8547 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 1485 1 2 1 0 1486 2 3 1 0 1487 3 1 1 0 1488 1 4 1 0 1489 3 5 1 1 1490 3 6 1 0 1491M END 1492""" 1493 m1 = Chem.MolFromMolBlock(inD) 1494 self.assertTrue(m1 is not None) 1495 self.assertTrue(m1.GetNumAtoms() == 6) 1496 self.assertTrue(Chem.MolToSmiles(m1, 1) == 'CC1C[C@@]1(F)Cl', Chem.MolToSmiles(m1, 1)) 1497 1498 inD = """chiral4.mol 1499 ChemDraw10160315172D 1500 1501 6 6 0 0 0 0 0 0 0 0999 V2000 1502 -0.4422 0.1402 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1503 -0.4422 -0.6848 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1504 0.2723 -0.2723 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1505 -0.8547 0.8547 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 1506 0.6848 0.4422 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 1507 0.8547 -0.8547 0.0000 Cl 0 0 0 0 0 0 0 0 0 0 0 0 1508 1 2 1 0 1509 2 3 1 0 1510 3 1 1 0 1511 1 4 1 0 1512 3 5 1 6 1513 3 6 1 0 1514M END 1515""" 1516 m1 = Chem.MolFromMolBlock(inD) 1517 self.assertTrue(m1 is not None) 1518 self.assertTrue(m1.GetNumAtoms() == 6) 1519 self.assertTrue(Chem.MolToSmiles(m1, 1) == 'CC1C[C@]1(F)Cl', Chem.MolToSmiles(m1, 1)) 1520 1521 def test33Issue65(self): 1522 """ issue 65 relates to handling of [H] in SMARTS 1523 1524 """ 1525 m1 = Chem.MolFromSmiles('OC(O)(O)O') 1526 m2 = Chem.MolFromSmiles('OC(O)O') 1527 m3 = Chem.MolFromSmiles('OCO') 1528 q1 = Chem.MolFromSmarts('OC[H]', 1) 1529 q2 = Chem.MolFromSmarts('O[C;H1]', 1) 1530 q3 = Chem.MolFromSmarts('O[C;H1][H]', 1) 1531 1532 self.assertTrue(not m1.HasSubstructMatch(q1)) 1533 self.assertTrue(not m1.HasSubstructMatch(q2)) 1534 self.assertTrue(not m1.HasSubstructMatch(q3)) 1535 1536 self.assertTrue(m2.HasSubstructMatch(q1)) 1537 self.assertTrue(m2.HasSubstructMatch(q2)) 1538 self.assertTrue(m2.HasSubstructMatch(q3)) 1539 1540 self.assertTrue(m3.HasSubstructMatch(q1)) 1541 self.assertTrue(not m3.HasSubstructMatch(q2)) 1542 self.assertTrue(not m3.HasSubstructMatch(q3)) 1543 1544 m1H = Chem.AddHs(m1) 1545 m2H = Chem.AddHs(m2) 1546 m3H = Chem.AddHs(m3) 1547 q1 = Chem.MolFromSmarts('OC[H]') 1548 q2 = Chem.MolFromSmarts('O[C;H1]') 1549 q3 = Chem.MolFromSmarts('O[C;H1][H]') 1550 1551 self.assertTrue(not m1H.HasSubstructMatch(q1)) 1552 self.assertTrue(not m1H.HasSubstructMatch(q2)) 1553 self.assertTrue(not m1H.HasSubstructMatch(q3)) 1554 1555 #m2H.Debug() 1556 self.assertTrue(m2H.HasSubstructMatch(q1)) 1557 self.assertTrue(m2H.HasSubstructMatch(q2)) 1558 self.assertTrue(m2H.HasSubstructMatch(q3)) 1559 1560 self.assertTrue(m3H.HasSubstructMatch(q1)) 1561 self.assertTrue(not m3H.HasSubstructMatch(q2)) 1562 self.assertTrue(not m3H.HasSubstructMatch(q3)) 1563 1564 def test34Issue124(self): 1565 """ issue 124 relates to calculation of the distance matrix 1566 1567 """ 1568 m = Chem.MolFromSmiles('CC=C') 1569 d = Chem.GetDistanceMatrix(m, 0) 1570 self.assertTrue(feq(d[0, 1], 1.0)) 1571 self.assertTrue(feq(d[0, 2], 2.0)) 1572 # force an update: 1573 d = Chem.GetDistanceMatrix(m, 1, 0, 1) 1574 self.assertTrue(feq(d[0, 1], 1.0)) 1575 self.assertTrue(feq(d[0, 2], 1.5)) 1576 1577 def test35ChiralityPerception(self): 1578 """ Test perception of chirality and CIP encoding 1579 """ 1580 m = Chem.MolFromSmiles('F[C@]([C@])(Cl)Br') 1581 Chem.AssignStereochemistry(m, 1) 1582 self.assertTrue(m.GetAtomWithIdx(1).HasProp('_CIPCode')) 1583 self.assertFalse(m.GetAtomWithIdx(2).HasProp('_CIPCode')) 1584 Chem.RemoveStereochemistry(m) 1585 self.assertFalse(m.GetAtomWithIdx(1).HasProp('_CIPCode')) 1586 1587 m = Chem.MolFromSmiles('F[C@H](C)C') 1588 Chem.AssignStereochemistry(m, 1) 1589 self.assertTrue(m.GetAtomWithIdx(1).GetChiralTag() == Chem.ChiralType.CHI_UNSPECIFIED) 1590 self.assertFalse(m.GetAtomWithIdx(1).HasProp('_CIPCode')) 1591 1592 m = Chem.MolFromSmiles('F\\C=C/Cl') 1593 self.assertTrue(m.GetBondWithIdx(0).GetStereo() == Chem.BondStereo.STEREONONE) 1594 self.assertTrue(m.GetBondWithIdx(1).GetStereo() == Chem.BondStereo.STEREOZ) 1595 atoms = m.GetBondWithIdx(1).GetStereoAtoms() 1596 self.assertTrue(0 in atoms) 1597 self.assertTrue(3 in atoms) 1598 self.assertTrue(m.GetBondWithIdx(2).GetStereo() == Chem.BondStereo.STEREONONE) 1599 Chem.RemoveStereochemistry(m) 1600 self.assertTrue(m.GetBondWithIdx(1).GetStereo() == Chem.BondStereo.STEREONONE) 1601 1602 m = Chem.MolFromSmiles('F\\C=CCl') 1603 self.assertTrue(m.GetBondWithIdx(1).GetStereo() == Chem.BondStereo.STEREONONE) 1604 1605 def checkDefaultBondProperties(self, m): 1606 for bond in m.GetBonds(): 1607 self.assertIn(bond.GetBondType(), [Chem.BondType.SINGLE, Chem.BondType.DOUBLE]) 1608 self.assertEqual(bond.GetBondDir(), Chem.BondDir.NONE) 1609 self.assertEqual(list(bond.GetStereoAtoms()), []) 1610 self.assertEqual(bond.GetStereo(), Chem.BondStereo.STEREONONE) 1611 1612 def assertHasDoubleBondStereo(self, smi): 1613 m = Chem.MolFromSmiles(smi) 1614 1615 self.checkDefaultBondProperties(m) 1616 1617 Chem.FindPotentialStereoBonds(m) 1618 1619 for bond in m.GetBonds(): 1620 self.assertIn(bond.GetBondType(), [Chem.BondType.SINGLE, Chem.BondType.DOUBLE]) 1621 self.assertEqual(bond.GetBondDir(), Chem.BondDir.NONE) 1622 1623 if bond.GetBondType() == Chem.BondType.DOUBLE: 1624 self.assertEqual(bond.GetStereo(), Chem.BondStereo.STEREOANY) 1625 self.assertEqual(len(list(bond.GetStereoAtoms())), 2) 1626 else: 1627 self.assertEqual(list(bond.GetStereoAtoms()), []) 1628 self.assertEqual(bond.GetStereo(), Chem.BondStereo.STEREONONE) 1629 1630 def testFindPotentialStereoBonds(self): 1631 self.assertHasDoubleBondStereo("FC=CF") 1632 self.assertHasDoubleBondStereo("FC(Cl)=C(Br)I") 1633 self.assertHasDoubleBondStereo("FC=CC=CC=CCl") 1634 self.assertHasDoubleBondStereo("C1CCCCC1C=CC1CCCCC1") 1635 1636 def assertDoesNotHaveDoubleBondStereo(self, smi): 1637 m = Chem.MolFromSmiles(smi) 1638 self.checkDefaultBondProperties(m) 1639 Chem.FindPotentialStereoBonds(m) 1640 self.checkDefaultBondProperties(m) 1641 1642 def testFindPotentialStereoBondsShouldNotFindThisDoubleBondAsStereo(self): 1643 self.assertDoesNotHaveDoubleBondStereo("FC(F)=CF") 1644 self.assertDoesNotHaveDoubleBondStereo("C=C") 1645 self.assertDoesNotHaveDoubleBondStereo("C1CCCCC1C(C1CCCCC1)=CC1CCCCC1") 1646 1647 def assertDoubleBondStereo(self, smi, stereo): 1648 mol = Chem.MolFromSmiles(smi) 1649 1650 bond = mol.GetBondWithIdx(1) 1651 self.assertEqual(bond.GetBondType(), Chem.BondType.DOUBLE) 1652 self.assertEqual(bond.GetStereo(), stereo) 1653 self.assertEqual(list(bond.GetStereoAtoms()), [0, 3]) 1654 1655 def allStereoBonds(self, bonds): 1656 for bond in bonds: 1657 self.assertEqual(len(list(bond.GetStereoAtoms())), 2) 1658 1659 def testBondSetStereo(self): 1660 for testAssignStereo in [False, True]: 1661 mol = Chem.MolFromSmiles("FC=CF") 1662 Chem.FindPotentialStereoBonds(mol) 1663 1664 for bond in mol.GetBonds(): 1665 if (bond.GetBondType() == Chem.BondType.DOUBLE 1666 and bond.GetStereo() == Chem.BondStereo.STEREOANY): 1667 break 1668 self.assertEqual(bond.GetBondType(), Chem.BondType.DOUBLE) 1669 self.assertEqual(bond.GetStereo(), Chem.BondStereo.STEREOANY) 1670 self.assertEqual(list(bond.GetStereoAtoms()), [0, 3]) 1671 1672 bond.SetStereo(Chem.BondStereo.STEREOTRANS) 1673 self.assertEqual(bond.GetStereo(), Chem.BondStereo.STEREOTRANS) 1674 if testAssignStereo: # should be invariant of Chem.AssignStereochemistry being called 1675 Chem.AssignStereochemistry(mol, force=True) 1676 smi = Chem.MolToSmiles(mol, isomericSmiles=True) 1677 self.allStereoBonds([bond]) 1678 self.assertEqual(smi, "F/C=C/F") 1679 self.assertDoubleBondStereo(smi, Chem.BondStereo.STEREOE) 1680 1681 bond.SetStereo(Chem.BondStereo.STEREOCIS) 1682 self.assertEqual(bond.GetStereo(), Chem.BondStereo.STEREOCIS) 1683 if testAssignStereo: 1684 Chem.AssignStereochemistry(mol, force=True) 1685 smi = Chem.MolToSmiles(mol, isomericSmiles=True) 1686 self.allStereoBonds([bond]) 1687 self.assertEqual(smi, r"F/C=C\F") 1688 self.assertDoubleBondStereo(smi, Chem.BondStereo.STEREOZ) 1689 1690 def recursive_enumerate_stereo_bonds(self, mol, done_bonds, bonds): 1691 if not bonds: 1692 yield done_bonds, Chem.Mol(mol) 1693 return 1694 1695 bond = bonds[0] 1696 child_bonds = bonds[1:] 1697 self.assertEqual(len(list(bond.GetStereoAtoms())), 2) 1698 bond.SetStereo(Chem.BondStereo.STEREOTRANS) 1699 for isomer in self.recursive_enumerate_stereo_bonds(mol, done_bonds + [Chem.BondStereo.STEREOE], 1700 child_bonds): 1701 yield isomer 1702 1703 self.assertEqual(len(list(bond.GetStereoAtoms())), 2) 1704 bond.SetStereo(Chem.BondStereo.STEREOCIS) 1705 for isomer in self.recursive_enumerate_stereo_bonds(mol, done_bonds + [Chem.BondStereo.STEREOZ], 1706 child_bonds): 1707 yield isomer 1708 1709 def testBondSetStereoDifficultCase(self): 1710 unspec_smiles = "CCC=CC(CO)=C(C)CC" 1711 mol = Chem.MolFromSmiles(unspec_smiles) 1712 Chem.FindPotentialStereoBonds(mol) 1713 1714 stereo_bonds = [] 1715 for bond in mol.GetBonds(): 1716 if bond.GetStereo() == Chem.BondStereo.STEREOANY: 1717 stereo_bonds.append(bond) 1718 1719 isomers = set() 1720 for bond_stereo, isomer in self.recursive_enumerate_stereo_bonds(mol, [], stereo_bonds): 1721 self.allStereoBonds(stereo_bonds) 1722 isosmi = Chem.MolToSmiles(isomer, isomericSmiles=True) 1723 self.allStereoBonds(stereo_bonds) 1724 1725 self.assertNotIn(isosmi, isomers) 1726 isomers.add(isosmi) 1727 1728 isomol = Chem.MolFromSmiles(isosmi) 1729 round_trip_stereo = [ 1730 b.GetStereo() for b in isomol.GetBonds() if b.GetStereo() != Chem.BondStereo.STEREONONE 1731 ] 1732 1733 self.assertEqual(bond_stereo, round_trip_stereo) 1734 1735 self.assertEqual(len(isomers), 4) 1736 1737 def getNumUnspecifiedBondStereo(self, smi): 1738 mol = Chem.MolFromSmiles(smi) 1739 Chem.FindPotentialStereoBonds(mol) 1740 1741 count = 0 1742 for bond in mol.GetBonds(): 1743 if bond.GetStereo() == Chem.BondStereo.STEREOANY: 1744 count += 1 1745 1746 return count 1747 1748 def testBondSetStereoReallyDifficultCase(self): 1749 # this one is much trickier because a double bond can gain and 1750 # lose it's stereochemistry based upon whether 2 other double 1751 # bonds have the same or different stereo chemistry. 1752 1753 unspec_smiles = "CCC=CC(C=CCC)=C(CO)CC" 1754 mol = Chem.MolFromSmiles(unspec_smiles) 1755 Chem.FindPotentialStereoBonds(mol) 1756 1757 stereo_bonds = [] 1758 for bond in mol.GetBonds(): 1759 if bond.GetStereo() == Chem.BondStereo.STEREOANY: 1760 stereo_bonds.append(bond) 1761 1762 self.assertEqual(len(stereo_bonds), 2) 1763 1764 isomers = set() 1765 for bond_stereo, isomer in self.recursive_enumerate_stereo_bonds(mol, [], stereo_bonds): 1766 isosmi = Chem.MolToSmiles(isomer, isomericSmiles=True) 1767 isomers.add(isosmi) 1768 1769 self.assertEqual(len(isomers), 3) 1770 1771 # one of these then gains a new stereo bond due to the 1772 # introduction of a new symmetry 1773 counts = {} 1774 for isosmi in isomers: 1775 num_unspecified = self.getNumUnspecifiedBondStereo(isosmi) 1776 counts[num_unspecified] = counts.get(num_unspecified, 0) + 1 1777 1778 # 2 of the isomers don't have any unspecified bond stereo centers 1779 # left, 1 does 1780 self.assertEqual(counts, {0: 2, 1: 1}) 1781 1782 def assertBondSetStereoIsAlwaysEquivalent(self, all_smiles, desired_stereo, bond_idx): 1783 refSmiles = None 1784 for smi in all_smiles: 1785 mol = Chem.MolFromSmiles(smi) 1786 1787 doubleBond = None 1788 for bond in mol.GetBonds(): 1789 if bond.GetBondType() == Chem.BondType.DOUBLE: 1790 doubleBond = bond 1791 1792 self.assertTrue(doubleBond is not None) 1793 1794 Chem.FindPotentialStereoBonds(mol) 1795 doubleBond.SetStereo(desired_stereo) 1796 1797 isosmi = Chem.MolToSmiles(mol, isomericSmiles=True) 1798 1799 if refSmiles is None: 1800 refSmiles = isosmi 1801 1802 self.assertEqual(refSmiles, isosmi) 1803 1804 def testBondSetStereoAllHalogens(self): 1805 # can't get much more brutal than this test 1806 from itertools import combinations, permutations 1807 halogens = ['F', 'Cl', 'Br', 'I'] 1808 1809 # binary double bond stereo 1810 for unique_set in combinations(halogens, 2): 1811 all_smiles = [] 1812 for fmt in ['%sC=C%s', 'C(%s)=C%s']: 1813 for ordering in permutations(unique_set): 1814 all_smiles.append(fmt % ordering) 1815 1816 #print(fmt, all_smiles) 1817 for desired_stereo in [Chem.BondStereo.STEREOTRANS, Chem.BondStereo.STEREOCIS]: 1818 self.assertBondSetStereoIsAlwaysEquivalent(all_smiles, desired_stereo, 1) 1819 1820 # tertiary double bond stereo 1821 for unique_set in combinations(halogens, 3): 1822 for mono_side in unique_set: 1823 halogens_left = list(unique_set) 1824 halogens_left.remove(mono_side) 1825 for binary_side in combinations(halogens_left, 2): 1826 all_smiles = [] 1827 1828 for binary_side_permutation in permutations(binary_side): 1829 all_smiles.append('%sC=C(%s)%s' % ((mono_side, ) + binary_side_permutation)) 1830 all_smiles.append('C(%s)=C(%s)%s' % ((mono_side, ) + binary_side_permutation)) 1831 1832 all_smiles.append('%sC(%s)=C%s' % (binary_side_permutation + (mono_side, ))) 1833 all_smiles.append('C(%s)(%s)=C%s' % (binary_side_permutation + (mono_side, ))) 1834 1835 #print(all_smiles) 1836 for desired_stereo in [Chem.BondStereo.STEREOTRANS, Chem.BondStereo.STEREOCIS]: 1837 self.assertBondSetStereoIsAlwaysEquivalent(all_smiles, desired_stereo, 1) 1838 1839 # quaternary double bond stereo 1840 for unique_ordering in permutations(halogens): 1841 left_side = unique_ordering[:2] 1842 rght_side = unique_ordering[2:] 1843 1844 all_smiles = [] 1845 for left_side_permutation in permutations(left_side): 1846 for rght_side_permutation in permutations(rght_side): 1847 for smifmt in ['%sC(%s)=C(%s)%s', 'C(%s)(%s)=C(%s)%s']: 1848 all_smiles.append(smifmt % (left_side_permutation + rght_side_permutation)) 1849 1850 #print(all_smiles) 1851 for desired_stereo in [Chem.BondStereo.STEREOTRANS, Chem.BondStereo.STEREOCIS]: 1852 self.assertBondSetStereoIsAlwaysEquivalent(all_smiles, desired_stereo, 1) 1853 1854 def testBondSetStereoAtoms(self): 1855 # use this difficult molecule that only generates 4 isomers, but 1856 # assume all double bonds are stereo! 1857 unspec_smiles = "CCC=CC(C=CCC)=C(CO)CC" 1858 mol = Chem.MolFromSmiles(unspec_smiles) 1859 1860 def getNbr(atom, exclude): 1861 for nbr in atom.GetNeighbors(): 1862 if nbr.GetIdx() not in exclude: 1863 return nbr 1864 raise ValueError("No neighbor found!") 1865 1866 double_bonds = [] 1867 for bond in mol.GetBonds(): 1868 if bond.GetBondType() == 2: 1869 double_bonds.append(bond) 1870 1871 exclude = {bond.GetBeginAtomIdx(), bond.GetEndAtomIdx()} 1872 bgnNbr = getNbr(bond.GetBeginAtom(), exclude) 1873 endNbr = getNbr(bond.GetEndAtom(), exclude) 1874 1875 bond.SetStereoAtoms(bgnNbr.GetIdx(), endNbr.GetIdx()) 1876 1877 self.assertEqual(len(double_bonds), 3) 1878 1879 import itertools 1880 stereos = [Chem.BondStereo.STEREOE, Chem.BondStereo.STEREOZ] 1881 isomers = set() 1882 for stereo_config in itertools.product(stereos, repeat=len(double_bonds)): 1883 for bond, stereo in zip(double_bonds, stereo_config): 1884 bond.SetStereo(stereo) 1885 smi = Chem.MolToSmiles(mol, True) 1886 isomers.add(smi) 1887 1888 # the dependent double bond stereo isn't picked up by this, should it? 1889 self.assertEqual(len(isomers), 6) 1890 1891 # round tripping them through one more time does pick up the dependency, so meh? 1892 round_trip_isomers = set() 1893 for smi in isomers: 1894 isosmi = Chem.MolToSmiles(Chem.MolFromSmiles(smi), True) 1895 round_trip_isomers.add(isosmi) 1896 1897 self.assertEqual(len(round_trip_isomers), 4) 1898 1899 def test36SubstructMatchStr(self): 1900 """ test the _SubstructMatchStr function """ 1901 query = Chem.MolFromSmarts('[n,p]1ccccc1') 1902 self.assertTrue(query) 1903 mol = Chem.MolFromSmiles('N1=CC=CC=C1') 1904 self.assertTrue(mol.HasSubstructMatch(query)) 1905 self.assertTrue(Chem._HasSubstructMatchStr(mol.ToBinary(), query)) 1906 mol = Chem.MolFromSmiles('S1=CC=CC=C1') 1907 self.assertTrue(not Chem._HasSubstructMatchStr(mol.ToBinary(), query)) 1908 self.assertTrue(not mol.HasSubstructMatch(query)) 1909 mol = Chem.MolFromSmiles('P1=CC=CC=C1') 1910 self.assertTrue(mol.HasSubstructMatch(query)) 1911 self.assertTrue(Chem._HasSubstructMatchStr(mol.ToBinary(), query)) 1912 1913 def test37SanitException(self): 1914 mol = Chem.MolFromSmiles('CC(C)(C)(C)C', 0) 1915 self.assertTrue(mol) 1916 self.assertRaises(ValueError, lambda: Chem.SanitizeMol(mol)) 1917 1918 def test38TDTSuppliers(self): 1919 data = """$SMI<Cc1nnc(N)nc1C> 1920CAS<17584-12-2> 1921| 1922$SMI<Cc1n[nH]c(=O)nc1N> 1923CAS<~> 1924| 1925$SMI<Cc1n[nH]c(=O)[nH]c1=O> 1926CAS<932-53-6> 1927| 1928$SMI<Cc1nnc(NN)nc1O> 1929CAS<~> 1930|""" 1931 suppl = Chem.TDTMolSupplier() 1932 suppl.SetData(data, "CAS") 1933 i = 0 1934 for mol in suppl: 1935 self.assertTrue(mol) 1936 self.assertTrue(mol.GetNumAtoms()) 1937 self.assertTrue(mol.HasProp("CAS")) 1938 self.assertTrue(mol.HasProp("_Name")) 1939 self.assertTrue(mol.GetProp("CAS") == mol.GetProp("_Name")) 1940 self.assertTrue(mol.GetNumConformers() == 0) 1941 i += 1 1942 self.assertTrue(i == 4) 1943 self.assertTrue(len(suppl) == 4) 1944 1945 def test38Issue266(self): 1946 """ test issue 266: generation of kekulized smiles""" 1947 mol = Chem.MolFromSmiles('c1ccccc1') 1948 Chem.Kekulize(mol) 1949 smi = Chem.MolToSmiles(mol) 1950 self.assertTrue(smi == 'c1ccccc1') 1951 smi = Chem.MolToSmiles(mol, kekuleSmiles=True) 1952 self.assertTrue(smi == 'C1=CC=CC=C1') 1953 1954 def test39Issue273(self): 1955 """ test issue 273: MolFileComments and MolFileInfo props ending up in SD files 1956 1957 """ 1958 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'Wrap', 'test_data', 1959 'outNCI_few.sdf') 1960 suppl = Chem.SDMolSupplier(fileN) 1961 ms = [x for x in suppl] 1962 for m in ms: 1963 self.assertTrue(m.HasProp('_MolFileInfo')) 1964 self.assertTrue(m.HasProp('_MolFileComments')) 1965 fName = tempfile.NamedTemporaryFile(suffix='.sdf', delete=False).name 1966 w = Chem.SDWriter(fName) 1967 w.SetProps(ms[0].GetPropNames()) 1968 for m in ms: 1969 w.write(m) 1970 w = None 1971 1972 with open(fName, 'r') as txtFile: 1973 txt = txtFile.read() 1974 os.unlink(fName) 1975 self.assertTrue(txt.find('MolFileInfo') == -1) 1976 self.assertTrue(txt.find('MolFileComments') == -1) 1977 1978 def test40SmilesRootedAtAtom(self): 1979 """ test the rootAtAtom functionality 1980 1981 """ 1982 smi = 'CN(C)C' 1983 m = Chem.MolFromSmiles(smi) 1984 1985 self.assertTrue(Chem.MolToSmiles(m) == 'CN(C)C') 1986 self.assertTrue(Chem.MolToSmiles(m, rootedAtAtom=1) == 'N(C)(C)C') 1987 1988 def test41SetStreamIndices(self): 1989 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 1990 'NCI_aids_few.sdf') 1991 allIndices = [] 1992 ifs = open(fileN, 'rb') 1993 addIndex = True 1994 line = True 1995 pos = 0 1996 while (line): 1997 if (addIndex): 1998 pos = ifs.tell() 1999 line = ifs.readline().decode('utf-8') 2000 if (line): 2001 if (addIndex): 2002 allIndices.append(pos) 2003 addIndex = (line[:4] == '$$$$') 2004 ifs.close() 2005 indices = allIndices 2006 sdSup = Chem.SDMolSupplier(fileN) 2007 molNames = [ 2008 "48", "78", "128", "163", "164", "170", "180", "186", "192", "203", "210", "211", "213", 2009 "220", "229", "256" 2010 ] 2011 2012 sdSup._SetStreamIndices(indices) 2013 self.assertTrue(len(sdSup) == 16) 2014 mol = sdSup[5] 2015 self.assertTrue(mol.GetProp("_Name") == "170") 2016 2017 i = 0 2018 for mol in sdSup: 2019 self.assertTrue(mol) 2020 self.assertTrue(mol.GetProp("_Name") == molNames[i]) 2021 i += 1 2022 2023 ns = [mol.GetProp("_Name") for mol in sdSup] 2024 self.assertTrue(ns == molNames) 2025 2026 # this can also be used to skip molecules in the file: 2027 indices = [allIndices[0], allIndices[2], allIndices[5]] 2028 sdSup._SetStreamIndices(indices) 2029 self.assertTrue(len(sdSup) == 3) 2030 mol = sdSup[2] 2031 self.assertTrue(mol.GetProp("_Name") == "170") 2032 2033 # or to reorder them: 2034 indices = [allIndices[0], allIndices[5], allIndices[2]] 2035 sdSup._SetStreamIndices(indices) 2036 self.assertTrue(len(sdSup) == 3) 2037 mol = sdSup[1] 2038 self.assertTrue(mol.GetProp("_Name") == "170") 2039 2040 def test42LifeTheUniverseAndEverything(self): 2041 self.assertTrue(True) 2042 2043 def test43TplFileParsing(self): 2044 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2045 'cmpd2.tpl') 2046 m1 = Chem.MolFromTPLFile(fileN) 2047 self.assertTrue(m1 is not None) 2048 self.assertTrue(m1.GetNumAtoms() == 12) 2049 self.assertTrue(m1.GetNumConformers() == 2) 2050 2051 m1 = Chem.MolFromTPLFile(fileN, skipFirstConf=True) 2052 self.assertTrue(m1 is not None) 2053 self.assertTrue(m1.GetNumAtoms() == 12) 2054 self.assertTrue(m1.GetNumConformers() == 1) 2055 2056 with open(fileN, 'r') as blockFile: 2057 block = blockFile.read() 2058 m1 = Chem.MolFromTPLBlock(block) 2059 self.assertTrue(m1 is not None) 2060 self.assertTrue(m1.GetNumAtoms() == 12) 2061 self.assertTrue(m1.GetNumConformers() == 2) 2062 2063 def test44TplFileWriting(self): 2064 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2065 'cmpd2.tpl') 2066 m1 = Chem.MolFromTPLFile(fileN) 2067 self.assertTrue(m1 is not None) 2068 self.assertTrue(m1.GetNumAtoms() == 12) 2069 self.assertTrue(m1.GetNumConformers() == 2) 2070 2071 block = Chem.MolToTPLBlock(m1) 2072 m1 = Chem.MolFromTPLBlock(block) 2073 self.assertTrue(m1 is not None) 2074 self.assertTrue(m1.GetNumAtoms() == 12) 2075 self.assertTrue(m1.GetNumConformers() == 2) 2076 2077 def test45RingInfo(self): 2078 """ test the RingInfo class 2079 2080 """ 2081 smi = 'CNC' 2082 m = Chem.MolFromSmiles(smi) 2083 ri = m.GetRingInfo() 2084 self.assertTrue(ri) 2085 self.assertTrue(ri.NumRings() == 0) 2086 self.assertFalse(ri.IsAtomInRingOfSize(0, 3)) 2087 self.assertFalse(ri.IsAtomInRingOfSize(1, 3)) 2088 self.assertFalse(ri.IsAtomInRingOfSize(2, 3)) 2089 self.assertFalse(ri.IsBondInRingOfSize(1, 3)) 2090 self.assertFalse(ri.IsBondInRingOfSize(2, 3)) 2091 if hasattr(Chem, 'FindRingFamilies'): 2092 self.assertEquals(ri.AtomRingFamilies(), ()) 2093 if hasattr(Chem, 'FindRingFamilies'): 2094 self.assertEquals(ri.BondRingFamilies(), ()) 2095 2096 smi = 'C1CC2C1C2' 2097 m = Chem.MolFromSmiles(smi) 2098 ri = m.GetRingInfo() 2099 self.assertTrue(ri) 2100 self.assertEquals(ri.NumRings(), 2) 2101 self.assertFalse(ri.IsAtomInRingOfSize(0, 3)) 2102 self.assertTrue(ri.IsAtomInRingOfSize(0, 4)) 2103 self.assertFalse(ri.IsBondInRingOfSize(0, 3)) 2104 self.assertTrue(ri.IsBondInRingOfSize(0, 4)) 2105 self.assertTrue(ri.IsAtomInRingOfSize(2, 4)) 2106 self.assertTrue(ri.IsAtomInRingOfSize(2, 3)) 2107 self.assertTrue(ri.IsBondInRingOfSize(2, 3)) 2108 self.assertTrue(ri.IsBondInRingOfSize(2, 4)) 2109 2110 if hasattr(Chem, 'FindRingFamilies'): 2111 ri = m.GetRingInfo() 2112 self.assertFalse(ri.AreRingFamiliesInitialized()) 2113 Chem.FindRingFamilies(m) 2114 ri = m.GetRingInfo() 2115 self.assertTrue(ri.AreRingFamiliesInitialized()) 2116 self.assertEquals(ri.NumRingFamilies(), 2) 2117 self.assertEquals(sorted(ri.AtomRingFamilies()), [(0, 1, 2, 3), (2, 3, 4)]) 2118 self.assertEquals(sorted(ri.BondRingFamilies()), [(0, 1, 2, 4), (2, 3, 5)]) 2119 2120 def test46ReplaceCore(self): 2121 """ test the ReplaceCore functionality 2122 2123 """ 2124 2125 core = Chem.MolFromSmiles('C=O') 2126 2127 smi = 'CCC=O' 2128 m = Chem.MolFromSmiles(smi) 2129 r = Chem.ReplaceCore(m, core) 2130 self.assertTrue(r) 2131 self.assertEqual(Chem.MolToSmiles(r, True), '[1*]CC') 2132 2133 smi = 'C1CC(=O)CC1' 2134 m = Chem.MolFromSmiles(smi) 2135 r = Chem.ReplaceCore(m, core) 2136 self.assertTrue(r) 2137 self.assertEqual(Chem.MolToSmiles(r, True), '[1*]CCCC[2*]') 2138 2139 smi = 'C1CC(=N)CC1' 2140 m = Chem.MolFromSmiles(smi) 2141 r = Chem.ReplaceCore(m, core) 2142 self.assertFalse(r) 2143 2144 # smiles, smarts, replaceDummies, labelByIndex, useChirality 2145 expected = { 2146 ('C1O[C@@]1(OC)NC', 'C1O[C@]1(*)*', False, False, False): '[1*]OC.[2*]NC', 2147 ('C1O[C@@]1(OC)NC', 'C1O[C@]1(*)*', False, False, True): '[1*]NC.[2*]OC', 2148 ('C1O[C@@]1(OC)NC', 'C1O[C@]1(*)*', False, True, False): '[3*]OC.[4*]NC', 2149 ('C1O[C@@]1(OC)NC', 'C1O[C@]1(*)*', False, True, True): '[3*]NC.[4*]OC', 2150 ('C1O[C@@]1(OC)NC', 'C1O[C@]1(*)*', True, False, False): '[1*]C.[2*]C', 2151 ('C1O[C@@]1(OC)NC', 'C1O[C@]1(*)*', True, False, True): '[1*]C.[2*]C', 2152 ('C1O[C@@]1(OC)NC', 'C1O[C@]1(*)*', True, True, False): '[3*]C.[4*]C', 2153 ('C1O[C@@]1(OC)NC', 'C1O[C@]1(*)*', True, True, True): '[3*]C.[4*]C', 2154 ('C1O[C@]1(OC)NC', 'C1O[C@]1(*)*', False, False, False): '[1*]OC.[2*]NC', 2155 ('C1O[C@]1(OC)NC', 'C1O[C@]1(*)*', False, False, True): '[1*]OC.[2*]NC', 2156 ('C1O[C@]1(OC)NC', 'C1O[C@]1(*)*', False, True, False): '[3*]OC.[4*]NC', 2157 ('C1O[C@]1(OC)NC', 'C1O[C@]1(*)*', False, True, True): '[3*]OC.[4*]NC', 2158 ('C1O[C@]1(OC)NC', 'C1O[C@]1(*)*', True, False, False): '[1*]C.[2*]C', 2159 ('C1O[C@]1(OC)NC', 'C1O[C@]1(*)*', True, False, True): '[1*]C.[2*]C', 2160 ('C1O[C@]1(OC)NC', 'C1O[C@]1(*)*', True, True, False): '[3*]C.[4*]C', 2161 ('C1O[C@]1(OC)NC', 'C1O[C@]1(*)*', True, True, True): '[3*]C.[4*]C', 2162 } 2163 2164 for (smiles, smarts, replaceDummies, labelByIndex, 2165 useChirality), expected_smiles in expected.items(): 2166 mol = Chem.MolFromSmiles(smiles) 2167 core = Chem.MolFromSmarts(smarts) 2168 nm = Chem.ReplaceCore(mol, core, replaceDummies=replaceDummies, labelByIndex=labelByIndex, 2169 useChirality=useChirality) 2170 2171 if Chem.MolToSmiles(nm, True) != expected_smiles: 2172 print( 2173 "ReplaceCore(%r, %r, replaceDummies=%r, labelByIndex=%r, useChirality=%r" % 2174 (smiles, smarts, replaceDummies, labelByIndex, useChirality), file=sys.stderr) 2175 print("expected: %s\ngot: %s" % (expected_smiles, Chem.MolToSmiles(nm, True)), 2176 file=sys.stderr) 2177 self.assertEqual(expected_smiles, Chem.MolToSmiles(nm, True)) 2178 2179 matchVect = mol.GetSubstructMatch(core, useChirality=useChirality) 2180 nm = Chem.ReplaceCore(mol, core, matchVect, replaceDummies=replaceDummies, 2181 labelByIndex=labelByIndex) 2182 if Chem.MolToSmiles(nm, True) != expected_smiles: 2183 print( 2184 "ReplaceCore(%r, %r, %r, replaceDummies=%r, labelByIndex=%rr" % 2185 (smiles, smarts, matchVect, replaceDummies, labelByIndex), file=sys.stderr) 2186 print("expected: %s\ngot: %s" % (expected_smiles, Chem.MolToSmiles(nm, True)), 2187 file=sys.stderr) 2188 self.assertEqual(expected_smiles, Chem.MolToSmiles(nm, True)) 2189 2190 mol = Chem.MolFromSmiles("C") 2191 smarts = Chem.MolFromSmarts("C") 2192 try: 2193 Chem.ReplaceCore(mol, smarts, (3, )) 2194 self.asssertFalse(True) 2195 except: 2196 pass 2197 2198 mol = Chem.MolFromSmiles("C") 2199 smarts = Chem.MolFromSmarts("C") 2200 try: 2201 Chem.ReplaceCore(mol, smarts, (0, 0)) 2202 self.asssertFalse(True) 2203 except: 2204 pass 2205 2206 def test47RWMols(self): 2207 """ test the RWMol class 2208 2209 """ 2210 mol = Chem.MolFromSmiles('C1CCC1') 2211 self.assertTrue(type(mol) == Chem.Mol) 2212 2213 for rwmol in [Chem.EditableMol(mol), Chem.RWMol(mol)]: 2214 self.assertTrue(type(rwmol) in [Chem.EditableMol, Chem.RWMol]) 2215 newAt = Chem.Atom(8) 2216 rwmol.ReplaceAtom(0, newAt) 2217 self.assertTrue(Chem.MolToSmiles(rwmol.GetMol()) == 'C1COC1') 2218 2219 rwmol.RemoveBond(0, 1) 2220 self.assertTrue(Chem.MolToSmiles(rwmol.GetMol()) == 'CCCO') 2221 a = Chem.Atom(7) 2222 idx = rwmol.AddAtom(a) 2223 self.assertEqual(rwmol.GetMol().GetNumAtoms(), 5) 2224 self.assertEqual(idx, 4) 2225 2226 idx = rwmol.AddBond(0, 4, order=Chem.BondType.SINGLE) 2227 self.assertEqual(idx, 4) 2228 2229 self.assertTrue(Chem.MolToSmiles(rwmol.GetMol()) == 'CCCON') 2230 rwmol.AddBond(4, 1, order=Chem.BondType.SINGLE) 2231 self.assertTrue(Chem.MolToSmiles(rwmol.GetMol()) == 'C1CNOC1') 2232 2233 rwmol.RemoveAtom(3) 2234 self.assertTrue(Chem.MolToSmiles(rwmol.GetMol()) == 'CCNO') 2235 2236 # practice shooting ourselves in the foot: 2237 m = Chem.MolFromSmiles('c1ccccc1') 2238 em = Chem.EditableMol(m) 2239 em.RemoveAtom(0) 2240 m2 = em.GetMol() 2241 self.assertRaises(ValueError, lambda: Chem.SanitizeMol(m2)) 2242 m = Chem.MolFromSmiles('c1ccccc1') 2243 em = Chem.EditableMol(m) 2244 em.RemoveBond(0, 1) 2245 m2 = em.GetMol() 2246 self.assertRaises(ValueError, lambda: Chem.SanitizeMol(m2)) 2247 2248 # boundary cases: 2249 2250 # removing non-existent bonds: 2251 m = Chem.MolFromSmiles('c1ccccc1') 2252 em = Chem.EditableMol(m) 2253 em.RemoveBond(0, 2) 2254 m2 = em.GetMol() 2255 Chem.SanitizeMol(m2) 2256 self.assertTrue(Chem.MolToSmiles(m2) == 'c1ccccc1') 2257 2258 # removing non-existent atoms: 2259 m = Chem.MolFromSmiles('c1ccccc1') 2260 em = Chem.EditableMol(m) 2261 self.assertRaises(RuntimeError, lambda: em.RemoveAtom(12)) 2262 2263 # confirm that an RWMol can be constructed without arguments 2264 m = Chem.RWMol() 2265 2266 # test replaceAtom/Bond preserving properties 2267 mol = Chem.MolFromSmiles('C1CCC1') 2268 mol2 = Chem.MolFromSmiles('C1CCC1') 2269 mol.GetAtomWithIdx(0).SetProp("foo", "bar") 2270 mol.GetBondWithIdx(0).SetProp("foo", "bar") 2271 newBond = mol2.GetBondWithIdx(0) 2272 self.assertTrue(type(mol) == Chem.Mol) 2273 2274 for rwmol in [Chem.EditableMol(mol), Chem.RWMol(mol)]: 2275 newAt = Chem.Atom(8) 2276 rwmol.ReplaceAtom(0, newAt) 2277 self.assertTrue(Chem.MolToSmiles(rwmol.GetMol()) == 'C1COC1') 2278 self.assertFalse(rwmol.GetMol().GetAtomWithIdx(0).HasProp("foo")) 2279 2280 for rwmol in [Chem.EditableMol(mol), Chem.RWMol(mol)]: 2281 newAt = Chem.Atom(8) 2282 rwmol.ReplaceAtom(0, newAt, preserveProps=True) 2283 self.assertTrue(Chem.MolToSmiles(rwmol.GetMol()) == 'C1COC1') 2284 self.assertTrue(rwmol.GetMol().GetAtomWithIdx(0).HasProp("foo")) 2285 self.assertEqual(rwmol.GetMol().GetAtomWithIdx(0).GetProp("foo"), "bar") 2286 2287 for rwmol in [Chem.EditableMol(mol), Chem.RWMol(mol)]: 2288 rwmol.ReplaceBond(0, newBond) 2289 self.assertTrue(Chem.MolToSmiles(rwmol.GetMol()) == 'C1CCC1') 2290 self.assertFalse(rwmol.GetMol().GetBondWithIdx(0).HasProp("foo")) 2291 2292 for rwmol in [Chem.EditableMol(mol), Chem.RWMol(mol)]: 2293 rwmol.ReplaceBond(0, newBond, preserveProps=True) 2294 self.assertTrue(Chem.MolToSmiles(rwmol.GetMol()) == 'C1CCC1') 2295 self.assertTrue(rwmol.GetMol().GetBondWithIdx(0).HasProp("foo")) 2296 self.assertEqual(rwmol.GetMol().GetBondWithIdx(0).GetProp("foo"), "bar") 2297 2298 def test47SmartsPieces(self): 2299 """ test the GetAtomSmarts and GetBondSmarts functions 2300 2301 """ 2302 m = Chem.MolFromSmarts("[C,N]C") 2303 self.assertTrue(m.GetAtomWithIdx(0).GetSmarts() == '[C,N]') 2304 self.assertTrue(m.GetAtomWithIdx(1).GetSmarts() == 'C') 2305 self.assertEqual(m.GetBondBetweenAtoms(0, 1).GetSmarts(), '') 2306 2307 m = Chem.MolFromSmarts("[$(C=O)]-O") 2308 self.assertTrue(m.GetAtomWithIdx(0).GetSmarts() == '[$(C=O)]') 2309 self.assertTrue(m.GetAtomWithIdx(1).GetSmarts() == 'O') 2310 self.assertTrue(m.GetBondBetweenAtoms(0, 1).GetSmarts() == '-') 2311 2312 m = Chem.MolFromSmiles("CO") 2313 self.assertTrue(m.GetAtomWithIdx(0).GetSmarts() == 'C') 2314 self.assertTrue(m.GetAtomWithIdx(1).GetSmarts() == 'O') 2315 self.assertTrue(m.GetBondBetweenAtoms(0, 1).GetSmarts() == '') 2316 self.assertTrue(m.GetBondBetweenAtoms(0, 1).GetSmarts(allBondsExplicit=True) == '-') 2317 2318 m = Chem.MolFromSmiles("C=O") 2319 self.assertTrue(m.GetAtomWithIdx(0).GetSmarts() == 'C') 2320 self.assertTrue(m.GetAtomWithIdx(1).GetSmarts() == 'O') 2321 self.assertTrue(m.GetBondBetweenAtoms(0, 1).GetSmarts() == '=') 2322 2323 m = Chem.MolFromSmiles('C[C@H](F)[15NH3+]') 2324 self.assertEqual(m.GetAtomWithIdx(0).GetSmarts(), 'C') 2325 self.assertEqual(m.GetAtomWithIdx(0).GetSmarts(allHsExplicit=True), '[CH3]') 2326 self.assertEqual(m.GetAtomWithIdx(3).GetSmarts(), '[15NH3+]') 2327 self.assertEqual(m.GetAtomWithIdx(3).GetSmarts(allHsExplicit=True), '[15NH3+]') 2328 2329 def test48Issue1928819(self): 2330 """ test a crash involving looping directly over mol suppliers 2331 """ 2332 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2333 'NCI_aids_few.sdf') 2334 ms = [x for x in Chem.SDMolSupplier(fileN)] 2335 self.assertEqual(len(ms), 16) 2336 count = 0 2337 for m in Chem.SDMolSupplier(fileN): 2338 count += 1 2339 self.assertEqual(count, 16) 2340 2341 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2342 'fewSmi.csv') 2343 count = 0 2344 for m in Chem.SmilesMolSupplier(fileN, titleLine=False, smilesColumn=1, delimiter=','): 2345 count += 1 2346 self.assertEqual(count, 10) 2347 2348 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2349 'acd_few.tdt') 2350 count = 0 2351 for m in Chem.TDTMolSupplier(fileN): 2352 count += 1 2353 self.assertEqual(count, 10) 2354 2355 def test49Issue1932365(self): 2356 """ test aromatic Se and Te from smiles/smarts 2357 """ 2358 m = Chem.MolFromSmiles('c1ccc[se]1') 2359 self.assertTrue(m) 2360 self.assertTrue(m.GetAtomWithIdx(0).GetIsAromatic()) 2361 self.assertTrue(m.GetAtomWithIdx(4).GetIsAromatic()) 2362 m = Chem.MolFromSmiles('c1ccc[te]1') 2363 self.assertTrue(m) 2364 self.assertTrue(m.GetAtomWithIdx(0).GetIsAromatic()) 2365 self.assertTrue(m.GetAtomWithIdx(4).GetIsAromatic()) 2366 m = Chem.MolFromSmiles('C1=C[Se]C=C1') 2367 self.assertTrue(m) 2368 self.assertTrue(m.GetAtomWithIdx(0).GetIsAromatic()) 2369 self.assertTrue(m.GetAtomWithIdx(2).GetIsAromatic()) 2370 m = Chem.MolFromSmiles('C1=C[Te]C=C1') 2371 self.assertTrue(m) 2372 self.assertTrue(m.GetAtomWithIdx(0).GetIsAromatic()) 2373 self.assertTrue(m.GetAtomWithIdx(2).GetIsAromatic()) 2374 2375 p = Chem.MolFromSmarts('[se]') 2376 self.assertTrue(Chem.MolFromSmiles('c1ccc[se]1').HasSubstructMatch(p)) 2377 self.assertFalse(Chem.MolFromSmiles('C1=CCC[Se]1').HasSubstructMatch(p)) 2378 2379 p = Chem.MolFromSmarts('[te]') 2380 self.assertTrue(Chem.MolFromSmiles('c1ccc[te]1').HasSubstructMatch(p)) 2381 self.assertFalse(Chem.MolFromSmiles('C1=CCC[Te]1').HasSubstructMatch(p)) 2382 2383 def test50Issue1968608(self): 2384 """ test sf.net issue 1968608 2385 """ 2386 smarts = Chem.MolFromSmarts("[r5]") 2387 mol = Chem.MolFromSmiles("N12CCC36C1CC(C(C2)=CCOC4CC5=O)C4C3N5c7ccccc76") 2388 count = len(mol.GetSubstructMatches(smarts, uniquify=0)) 2389 self.assertTrue(count == 9) 2390 2391 def test51RadicalHandling(self): 2392 """ test handling of atoms with radicals 2393 """ 2394 mol = Chem.MolFromSmiles("[C]C") 2395 self.assertTrue(mol) 2396 atom = mol.GetAtomWithIdx(0) 2397 self.assertTrue(atom.GetNumRadicalElectrons() == 3) 2398 self.assertTrue(atom.GetNoImplicit()) 2399 atom.SetNoImplicit(False) 2400 atom.SetNumRadicalElectrons(1) 2401 mol.UpdatePropertyCache() 2402 self.assertTrue(atom.GetNumRadicalElectrons() == 1) 2403 self.assertTrue(atom.GetNumImplicitHs() == 2) 2404 2405 mol = Chem.MolFromSmiles("[c]1ccccc1") 2406 self.assertTrue(mol) 2407 atom = mol.GetAtomWithIdx(0) 2408 self.assertTrue(atom.GetNumRadicalElectrons() == 1) 2409 self.assertTrue(atom.GetNoImplicit()) 2410 2411 mol = Chem.MolFromSmiles("[n]1ccccc1") 2412 self.assertTrue(mol) 2413 atom = mol.GetAtomWithIdx(0) 2414 self.assertTrue(atom.GetNumRadicalElectrons() == 0) 2415 self.assertTrue(atom.GetNoImplicit()) 2416 2417 def test52MolFrags(self): 2418 """ test GetMolFrags functionality 2419 """ 2420 mol = Chem.MolFromSmiles("C.CC") 2421 self.assertTrue(mol) 2422 fs = Chem.GetMolFrags(mol) 2423 self.assertTrue(len(fs) == 2) 2424 self.assertTrue(len(fs[0]) == 1) 2425 self.assertTrue(tuple(fs[0]) == (0, )) 2426 self.assertTrue(len(fs[1]) == 2) 2427 self.assertTrue(tuple(fs[1]) == (1, 2)) 2428 2429 fs = Chem.GetMolFrags(mol, True) 2430 self.assertTrue(len(fs) == 2) 2431 self.assertTrue(fs[0].GetNumAtoms() == 1) 2432 self.assertTrue(fs[1].GetNumAtoms() == 2) 2433 2434 mol = Chem.MolFromSmiles("CCC") 2435 self.assertTrue(mol) 2436 fs = Chem.GetMolFrags(mol) 2437 self.assertTrue(len(fs) == 1) 2438 self.assertTrue(len(fs[0]) == 3) 2439 self.assertTrue(tuple(fs[0]) == (0, 1, 2)) 2440 fs = Chem.GetMolFrags(mol, True) 2441 self.assertTrue(len(fs) == 1) 2442 self.assertTrue(fs[0].GetNumAtoms() == 3) 2443 2444 mol = Chem.MolFromSmiles("CO") 2445 em = Chem.EditableMol(mol) 2446 em.RemoveBond(0, 1) 2447 nm = em.GetMol() 2448 fs = Chem.GetMolFrags(nm, asMols=True) 2449 self.assertEqual([x.GetNumAtoms(onlyExplicit=False) for x in fs], [5, 3]) 2450 fs = Chem.GetMolFrags(nm, asMols=True, sanitizeFrags=False) 2451 self.assertEqual([x.GetNumAtoms(onlyExplicit=False) for x in fs], [4, 2]) 2452 2453 mol = Chem.MolFromSmiles("CC.CCC") 2454 fs = Chem.GetMolFrags(mol, asMols=True) 2455 self.assertEqual([x.GetNumAtoms() for x in fs], [2, 3]) 2456 frags = [] 2457 fragsMolAtomMapping = [] 2458 fs = Chem.GetMolFrags(mol, asMols=True, frags=frags, fragsMolAtomMapping=fragsMolAtomMapping) 2459 self.assertEqual(mol.GetNumAtoms(onlyExplicit=True), len(frags)) 2460 fragsCheck = [] 2461 for i, f in enumerate(fs): 2462 fragsCheck.extend([i] * f.GetNumAtoms(onlyExplicit=True)) 2463 self.assertEqual(frags, fragsCheck) 2464 fragsMolAtomMappingCheck = [] 2465 i = 0 2466 for f in fs: 2467 n = f.GetNumAtoms(onlyExplicit=True) 2468 fragsMolAtomMappingCheck.append(tuple(range(i, i + n))) 2469 i += n 2470 self.assertEqual(fragsMolAtomMapping, fragsMolAtomMappingCheck) 2471 2472 def test53Matrices(self): 2473 """ test adjacency and distance matrices 2474 2475 """ 2476 m = Chem.MolFromSmiles('CC=C') 2477 d = Chem.GetDistanceMatrix(m, 0) 2478 self.assertTrue(feq(d[0, 1], 1.0)) 2479 self.assertTrue(feq(d[0, 2], 2.0)) 2480 self.assertTrue(feq(d[1, 0], 1.0)) 2481 self.assertTrue(feq(d[2, 0], 2.0)) 2482 a = Chem.GetAdjacencyMatrix(m, 0) 2483 self.assertTrue(a[0, 1] == 1) 2484 self.assertTrue(a[0, 2] == 0) 2485 self.assertTrue(a[1, 2] == 1) 2486 self.assertTrue(a[1, 0] == 1) 2487 self.assertTrue(a[2, 0] == 0) 2488 2489 m = Chem.MolFromSmiles('C1CC1') 2490 d = Chem.GetDistanceMatrix(m, 0) 2491 self.assertTrue(feq(d[0, 1], 1.0)) 2492 self.assertTrue(feq(d[0, 2], 1.0)) 2493 a = Chem.GetAdjacencyMatrix(m, 0) 2494 self.assertTrue(a[0, 1] == 1) 2495 self.assertTrue(a[0, 2] == 1) 2496 self.assertTrue(a[1, 2] == 1) 2497 2498 m = Chem.MolFromSmiles('CC.C') 2499 d = Chem.GetDistanceMatrix(m, 0) 2500 self.assertTrue(feq(d[0, 1], 1.0)) 2501 self.assertTrue(d[0, 2] > 1000) 2502 self.assertTrue(d[1, 2] > 1000) 2503 a = Chem.GetAdjacencyMatrix(m, 0) 2504 self.assertTrue(a[0, 1] == 1) 2505 self.assertTrue(a[0, 2] == 0) 2506 self.assertTrue(a[1, 2] == 0) 2507 2508 def test54Mol2Parser(self): 2509 """ test the mol2 parser 2510 """ 2511 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2512 'pyrazole_pyridine.mol2') 2513 m = Chem.MolFromMol2File(fileN) 2514 self.assertTrue(m.GetNumAtoms() == 5) 2515 self.assertTrue(Chem.MolToSmiles(m) == 'c1cn[nH]c1', Chem.MolToSmiles(m)) 2516 2517 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2518 '3505.mol2') 2519 m = Chem.MolFromMol2File(fileN) 2520 self.assertTrue(m.GetBondBetweenAtoms(3, 12) is not None) 2521 self.assertEqual(m.GetBondBetweenAtoms(3, 12).GetBondType(), Chem.BondType.SINGLE) 2522 self.assertEqual(m.GetAtomWithIdx(12).GetFormalCharge(), 0) 2523 2524 m = Chem.MolFromMol2File(fileN, cleanupSubstructures=False) 2525 self.assertTrue(m.GetBondBetweenAtoms(3, 12) is not None) 2526 self.assertEqual(m.GetBondBetweenAtoms(3, 12).GetBondType(), Chem.BondType.DOUBLE) 2527 self.assertEqual(m.GetAtomWithIdx(12).GetFormalCharge(), 1) 2528 2529 def test55LayeredFingerprint(self): 2530 m1 = Chem.MolFromSmiles('CC(C)C') 2531 fp1 = Chem.LayeredFingerprint(m1) 2532 self.assertEqual(len(fp1), 2048) 2533 atomCounts = [0] * m1.GetNumAtoms() 2534 fp2 = Chem.LayeredFingerprint(m1, atomCounts=atomCounts) 2535 self.assertEqual(fp1, fp2) 2536 self.assertEqual(atomCounts, [4, 7, 4, 4]) 2537 2538 fp2 = Chem.LayeredFingerprint(m1, atomCounts=atomCounts) 2539 self.assertEqual(fp1, fp2) 2540 self.assertEqual(atomCounts, [8, 14, 8, 8]) 2541 2542 pbv = DataStructs.ExplicitBitVect(2048) 2543 fp3 = Chem.LayeredFingerprint(m1, setOnlyBits=pbv) 2544 self.assertEqual(fp3.GetNumOnBits(), 0) 2545 2546 fp3 = Chem.LayeredFingerprint(m1, setOnlyBits=fp2) 2547 self.assertEqual(fp3, fp2) 2548 2549 m2 = Chem.MolFromSmiles('CC') 2550 fp4 = Chem.LayeredFingerprint(m2) 2551 atomCounts = [0] * m1.GetNumAtoms() 2552 fp3 = Chem.LayeredFingerprint(m1, setOnlyBits=fp4, atomCounts=atomCounts) 2553 self.assertEqual(atomCounts, [1, 3, 1, 1]) 2554 2555 m2 = Chem.MolFromSmiles('CCC') 2556 fp4 = Chem.LayeredFingerprint(m2) 2557 atomCounts = [0] * m1.GetNumAtoms() 2558 fp3 = Chem.LayeredFingerprint(m1, setOnlyBits=fp4, atomCounts=atomCounts) 2559 self.assertEqual(atomCounts, [3, 6, 3, 3]) 2560 2561 def test56LazySDMolSupplier(self): 2562 if not hasattr(Chem, 'CompressedSDMolSupplier'): 2563 return 2564 2565 self.assertRaises(ValueError, lambda: Chem.CompressedSDMolSupplier('nosuchfile.sdf.gz')) 2566 2567 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2568 'NCI_aids_few.sdf.gz') 2569 sdSup = Chem.CompressedSDMolSupplier(fileN) 2570 molNames = [ 2571 "48", "78", "128", "163", "164", "170", "180", "186", "192", "203", "210", "211", "213", 2572 "220", "229", "256" 2573 ] 2574 2575 chgs192 = {8: 1, 11: 1, 15: -1, 18: -1, 20: 1, 21: 1, 23: -1, 25: -1} 2576 i = 0 2577 for mol in sdSup: 2578 self.assertTrue(mol) 2579 self.assertTrue(mol.GetProp("_Name") == molNames[i]) 2580 i += 1 2581 if (mol.GetProp("_Name") == "192"): 2582 # test parsed charges on one of the molecules 2583 for id in chgs192.keys(): 2584 self.assertTrue(mol.GetAtomWithIdx(id).GetFormalCharge() == chgs192[id]) 2585 self.assertEqual(i, 16) 2586 2587 sdSup = Chem.CompressedSDMolSupplier(fileN) 2588 ns = [mol.GetProp("_Name") for mol in sdSup] 2589 self.assertTrue(ns == molNames) 2590 2591 sdSup = Chem.CompressedSDMolSupplier(fileN, 0) 2592 for mol in sdSup: 2593 self.assertTrue(not mol.HasProp("numArom")) 2594 2595 def test57AddRecursiveQuery(self): 2596 q1 = Chem.MolFromSmiles('CC') 2597 q2 = Chem.MolFromSmiles('CO') 2598 Chem.AddRecursiveQuery(q1, q2, 1) 2599 2600 m1 = Chem.MolFromSmiles('OCC') 2601 self.assertTrue(m1.HasSubstructMatch(q2)) 2602 self.assertTrue(m1.HasSubstructMatch(q1)) 2603 self.assertTrue(m1.HasSubstructMatch(q1)) 2604 self.assertTrue(m1.GetSubstructMatch(q1) == (2, 1)) 2605 2606 q3 = Chem.MolFromSmiles('CS') 2607 Chem.AddRecursiveQuery(q1, q3, 1) 2608 2609 self.assertFalse(m1.HasSubstructMatch(q3)) 2610 self.assertFalse(m1.HasSubstructMatch(q1)) 2611 2612 m2 = Chem.MolFromSmiles('OC(S)C') 2613 self.assertTrue(m2.HasSubstructMatch(q1)) 2614 self.assertTrue(m2.GetSubstructMatch(q1) == (3, 1)) 2615 2616 m3 = Chem.MolFromSmiles('SCC') 2617 self.assertTrue(m3.HasSubstructMatch(q3)) 2618 self.assertFalse(m3.HasSubstructMatch(q1)) 2619 2620 q1 = Chem.MolFromSmiles('CC') 2621 Chem.AddRecursiveQuery(q1, q2, 1) 2622 Chem.AddRecursiveQuery(q1, q3, 1, False) 2623 self.assertTrue(m3.HasSubstructMatch(q1)) 2624 self.assertTrue(m3.GetSubstructMatch(q1) == (2, 1)) 2625 2626 def test58Issue2983794(self): 2627 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'Wrap', 'test_data', 2628 'issue2983794.sdf') 2629 m1 = Chem.MolFromMolFile(fileN) 2630 self.assertTrue(m1) 2631 em = Chem.EditableMol(m1) 2632 em.RemoveAtom(0) 2633 m2 = em.GetMol() 2634 Chem.Kekulize(m2) 2635 2636 def test59Issue3007178(self): 2637 m = Chem.MolFromSmiles('CCC') 2638 a = m.GetAtomWithIdx(0) 2639 m = None 2640 self.assertEqual(Chem.MolToSmiles(a.GetOwningMol()), 'CCC') 2641 a = None 2642 m = Chem.MolFromSmiles('CCC') 2643 b = m.GetBondWithIdx(0) 2644 m = None 2645 self.assertEqual(Chem.MolToSmiles(b.GetOwningMol()), 'CCC') 2646 2647 def test60SmilesWriterClose(self): 2648 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2649 'fewSmi.csv') 2650 smiSup = Chem.SmilesMolSupplier(fileN, delimiter=",", smilesColumn=1, nameColumn=0, titleLine=0) 2651 ms = [x for x in smiSup] 2652 2653 ofile = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'Wrap', 'test_data', 2654 'outSmiles.txt') 2655 writer = Chem.SmilesWriter(ofile) 2656 for mol in ms: 2657 writer.write(mol) 2658 writer.close() 2659 2660 newsup = Chem.SmilesMolSupplier(ofile) 2661 newms = [x for x in newsup] 2662 self.assertEqual(len(ms), len(newms)) 2663 2664 def test61PathToSubmol(self): 2665 m = Chem.MolFromSmiles('CCCCCC1C(O)CC(O)N1C=CCO') 2666 env = Chem.FindAtomEnvironmentOfRadiusN(m, 2, 11) 2667 self.assertEqual(len(env), 8) 2668 amap = {} 2669 submol = Chem.PathToSubmol(m, env, atomMap=amap) 2670 self.assertEqual(submol.GetNumAtoms(), len(amap.keys())) 2671 self.assertEqual(submol.GetNumAtoms(), 9) 2672 smi = Chem.MolToSmiles(submol, rootedAtAtom=amap[11]) 2673 self.assertEqual(smi[0], 'N') 2674 refsmi = Chem.MolToSmiles(Chem.MolFromSmiles('N(C=C)(C(C)C)C(O)C')) 2675 csmi = Chem.MolToSmiles(Chem.MolFromSmiles(smi)) 2676 self.assertEqual(refsmi, csmi) 2677 2678 def test62SmilesAndSmartsReplacements(self): 2679 mol = Chem.MolFromSmiles('C{branch}C', replacements={'{branch}': 'C1(CC1)'}) 2680 self.assertEqual(mol.GetNumAtoms(), 5) 2681 mol = Chem.MolFromSmarts('C{branch}C', replacements={'{branch}': 'C1(CC1)'}) 2682 self.assertEqual(mol.GetNumAtoms(), 5) 2683 mol = Chem.MolFromSmiles('C{branch}C{acid}', replacements={ 2684 '{branch}': 'C1(CC1)', 2685 '{acid}': "C(=O)O" 2686 }) 2687 self.assertEqual(mol.GetNumAtoms(), 8) 2688 2689 def test63Issue3313539(self): 2690 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2691 'rgroups1.mol') 2692 m = Chem.MolFromMolFile(fileN) 2693 self.assertTrue(m is not None) 2694 at = m.GetAtomWithIdx(3) 2695 self.assertTrue(at is not None) 2696 self.assertTrue(at.HasProp('_MolFileRLabel')) 2697 p = at.GetProp('_MolFileRLabel') 2698 self.assertEqual(p, '2') 2699 self.assertEqual(Chem.GetAtomRLabel(at), 2) 2700 2701 at = m.GetAtomWithIdx(4) 2702 self.assertTrue(at is not None) 2703 self.assertTrue(at.HasProp('_MolFileRLabel')) 2704 p = at.GetProp('_MolFileRLabel') 2705 self.assertEqual(p, '1') 2706 self.assertEqual(Chem.GetAtomRLabel(at), 1) 2707 2708 def test64MoleculeCleanup(self): 2709 m = Chem.MolFromSmiles('CN(=O)=O', False) 2710 self.assertTrue(m) 2711 self.assertTrue(m.GetAtomWithIdx(1).GetFormalCharge()==0 and \ 2712 m.GetAtomWithIdx(2).GetFormalCharge()==0 and \ 2713 m.GetAtomWithIdx(3).GetFormalCharge()==0) 2714 self.assertTrue(m.GetBondBetweenAtoms(1,3).GetBondType()==Chem.BondType.DOUBLE and \ 2715 m.GetBondBetweenAtoms(1,2).GetBondType()==Chem.BondType.DOUBLE ) 2716 Chem.Cleanup(m) 2717 m.UpdatePropertyCache() 2718 self.assertTrue(m.GetAtomWithIdx(1).GetFormalCharge()==1 and \ 2719 (m.GetAtomWithIdx(2).GetFormalCharge()==-1 or \ 2720 m.GetAtomWithIdx(3).GetFormalCharge()==-1)) 2721 self.assertTrue(m.GetBondBetweenAtoms(1,3).GetBondType()==Chem.BondType.SINGLE or \ 2722 m.GetBondBetweenAtoms(1,2).GetBondType()==Chem.BondType.SINGLE ) 2723 2724 def test65StreamSupplier(self): 2725 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2726 'NCI_aids_few.sdf.gz') 2727 molNames = [ 2728 "48", "78", "128", "163", "164", "170", "180", "186", "192", "203", "210", "211", "213", 2729 "220", "229", "256" 2730 ] 2731 inf = gzip.open(fileN) 2732 if 0: 2733 sb = Chem.streambuf(inf) 2734 suppl = Chem.ForwardSDMolSupplier(sb) 2735 else: 2736 suppl = Chem.ForwardSDMolSupplier(inf) 2737 2738 i = 0 2739 while not suppl.atEnd(): 2740 mol = next(suppl) 2741 self.assertTrue(mol) 2742 self.assertTrue(mol.GetProp("_Name") == molNames[i]) 2743 i += 1 2744 self.assertEqual(i, 16) 2745 2746 # make sure we have object ownership preserved 2747 inf = gzip.open(fileN) 2748 suppl = Chem.ForwardSDMolSupplier(inf) 2749 inf = None 2750 i = 0 2751 while not suppl.atEnd(): 2752 mol = next(suppl) 2753 self.assertTrue(mol) 2754 self.assertTrue(mol.GetProp("_Name") == molNames[i]) 2755 i += 1 2756 self.assertEqual(i, 16) 2757 2758 @unittest.skipIf(not hasattr(Chem, 'MaeMolSupplier'), "not build with MAEParser support") 2759 def testMaeStreamSupplier(self): 2760 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2761 'NCI_aids_few.maegz') 2762 molNames = [ 2763 "48", "78", "128", "163", "164", "170", "180", "186", "192", "203", "210", "211", "213", 2764 "220", "229", "256" 2765 ] 2766 inf = gzip.open(fileN) 2767 suppl = Chem.MaeMolSupplier(inf) 2768 2769 i = 0 2770 while not suppl.atEnd(): 2771 mol = next(suppl) 2772 self.assertTrue(mol) 2773 self.assertTrue(mol.GetProp("_Name") == molNames[i]) 2774 i += 1 2775 self.assertEqual(i, 16) 2776 2777 # make sure we have object ownership preserved 2778 inf = gzip.open(fileN) 2779 suppl = Chem.MaeMolSupplier(inf) 2780 inf = None 2781 i = 0 2782 while not suppl.atEnd(): 2783 mol = next(suppl) 2784 self.assertTrue(mol) 2785 self.assertTrue(mol.GetProp("_Name") == molNames[i]) 2786 i += 1 2787 self.assertEqual(i, 16) 2788 2789 @unittest.skipIf(not hasattr(Chem, 'MaeMolSupplier'), "not build with MAEParser support") 2790 def testMaeFileSupplier(self): 2791 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2792 'NCI_aids_few.mae') 2793 molNames = [ 2794 "48", "78", "128", "163", "164", "170", "180", "186", "192", "203", "210", "211", "213", 2795 "220", "229", "256" 2796 ] 2797 suppl = Chem.MaeMolSupplier(fileN) 2798 2799 i = 0 2800 while not suppl.atEnd(): 2801 mol = next(suppl) 2802 self.assertTrue(mol) 2803 self.assertTrue(mol.GetProp("_Name") == molNames[i]) 2804 i += 1 2805 self.assertEqual(i, 16) 2806 2807 @unittest.skipIf(not hasattr(Chem, 'MaeMolSupplier'), "not build with MAEParser support") 2808 def testMaeFileSupplierException(self): 2809 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2810 'bad_ppty.mae') 2811 err_msg_substr = "Bad format for property" 2812 2813 ok = False 2814 suppl = Chem.MaeMolSupplier(fileN) 2815 for i in range(5): 2816 try: 2817 mol = next(suppl) 2818 except RuntimeError as e: 2819 self.assertEqual(i, 1) 2820 self.assertTrue(err_msg_substr in str(e)) 2821 ok = True 2822 break 2823 else: 2824 self.assertTrue(mol) 2825 self.assertTrue(mol.HasProp("_Name")) 2826 self.assertTrue(mol.GetNumAtoms() == 1) 2827 2828 self.assertFalse(suppl.atEnd()) 2829 self.assertTrue(ok) 2830 2831 def test66StreamSupplierIter(self): 2832 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2833 'NCI_aids_few.sdf.gz') 2834 inf = gzip.open(fileN) 2835 if 0: 2836 sb = Chem.streambuf(inf) 2837 suppl = Chem.ForwardSDMolSupplier(sb) 2838 else: 2839 suppl = Chem.ForwardSDMolSupplier(inf) 2840 2841 molNames = [ 2842 "48", "78", "128", "163", "164", "170", "180", "186", "192", "203", "210", "211", "213", 2843 "220", "229", "256" 2844 ] 2845 i = 0 2846 for mol in suppl: 2847 self.assertTrue(mol) 2848 self.assertTrue(mol.GetProp("_Name") == molNames[i]) 2849 i += 1 2850 self.assertEqual(i, 16) 2851 2852 def test67StreamSupplierStringIO(self): 2853 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2854 'NCI_aids_few.sdf.gz') 2855 from io import BytesIO 2856 sio = BytesIO(gzip.open(fileN).read()) 2857 suppl = Chem.ForwardSDMolSupplier(sio) 2858 molNames = [ 2859 "48", "78", "128", "163", "164", "170", "180", "186", "192", "203", "210", "211", "213", 2860 "220", "229", "256" 2861 ] 2862 i = 0 2863 for mol in suppl: 2864 self.assertTrue(mol) 2865 self.assertTrue(mol.GetProp("_Name") == molNames[i]) 2866 i += 1 2867 self.assertEqual(i, 16) 2868 2869 def test68ForwardSupplierUsingFilename(self): 2870 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2871 'NCI_aids_few.sdf') 2872 suppl = Chem.ForwardSDMolSupplier(fileN) 2873 molNames = [ 2874 "48", "78", "128", "163", "164", "170", "180", "186", "192", "203", "210", "211", "213", 2875 "220", "229", "256" 2876 ] 2877 i = 0 2878 for mol in suppl: 2879 self.assertTrue(mol) 2880 self.assertTrue(mol.GetProp("_Name") == molNames[i]) 2881 i += 1 2882 self.assertEqual(i, 16) 2883 2884 self.assertRaises(IOError, lambda: Chem.ForwardSDMolSupplier('nosuchfile.sdf')) 2885 2886 def test69StreamSupplierStreambuf(self): 2887 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2888 'NCI_aids_few.sdf.gz') 2889 sb = rdBase.streambuf(gzip.open(fileN)) 2890 suppl = Chem.ForwardSDMolSupplier(sb) 2891 2892 molNames = [ 2893 "48", "78", "128", "163", "164", "170", "180", "186", "192", "203", "210", "211", "213", 2894 "220", "229", "256" 2895 ] 2896 i = 0 2897 for mol in suppl: 2898 self.assertTrue(mol) 2899 self.assertTrue(mol.GetProp("_Name") == molNames[i]) 2900 i += 1 2901 self.assertEqual(i, 16) 2902 2903 def test70StreamSDWriter(self): 2904 from io import BytesIO, StringIO 2905 2906 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2907 'NCI_aids_few.sdf.gz') 2908 inf = gzip.open(fileN) 2909 suppl = Chem.ForwardSDMolSupplier(inf) 2910 osio = StringIO() 2911 w = Chem.SDWriter(osio) 2912 molNames = [ 2913 "48", "78", "128", "163", "164", "170", "180", "186", "192", "203", "210", "211", "213", 2914 "220", "229", "256" 2915 ] 2916 i = 0 2917 for mol in suppl: 2918 self.assertTrue(mol) 2919 self.assertTrue(mol.GetProp("_Name") == molNames[i]) 2920 w.write(mol) 2921 i += 1 2922 self.assertEqual(i, 16) 2923 w.flush() 2924 w = None 2925 txt = osio.getvalue().encode() 2926 isio = BytesIO(txt) 2927 suppl = Chem.ForwardSDMolSupplier(isio) 2928 i = 0 2929 for mol in suppl: 2930 self.assertTrue(mol) 2931 self.assertTrue(mol.GetProp("_Name") == molNames[i]) 2932 i += 1 2933 self.assertEqual(i, 16) 2934 2935 def test71StreamSmilesWriter(self): 2936 from io import StringIO 2937 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2938 'esters.sdf') 2939 suppl = Chem.ForwardSDMolSupplier(fileN) 2940 osio = StringIO() 2941 w = Chem.SmilesWriter(osio) 2942 ms = [x for x in suppl] 2943 w.SetProps(ms[0].GetPropNames()) 2944 i = 0 2945 for mol in ms: 2946 self.assertTrue(mol) 2947 w.write(mol) 2948 i += 1 2949 self.assertEqual(i, 6) 2950 w.flush() 2951 w = None 2952 txt = osio.getvalue() 2953 self.assertEqual(txt.count('ID'), 1) 2954 self.assertEqual(txt.count('\n'), 7) 2955 2956 def test72StreamTDTWriter(self): 2957 from io import StringIO 2958 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 2959 'esters.sdf') 2960 suppl = Chem.ForwardSDMolSupplier(fileN) 2961 osio = StringIO() 2962 w = Chem.TDTWriter(osio) 2963 ms = [x for x in suppl] 2964 w.SetProps(ms[0].GetPropNames()) 2965 i = 0 2966 for mol in ms: 2967 self.assertTrue(mol) 2968 w.write(mol) 2969 i += 1 2970 self.assertEqual(i, 6) 2971 w.flush() 2972 w = None 2973 txt = osio.getvalue() 2974 self.assertEqual(txt.count('ID'), 6) 2975 self.assertEqual(txt.count('NAME'), 6) 2976 2977 def test73SanitizationOptions(self): 2978 m = Chem.MolFromSmiles('c1ccccc1', sanitize=False) 2979 res = Chem.SanitizeMol(m, catchErrors=True) 2980 self.assertEqual(res, 0) 2981 2982 m = Chem.MolFromSmiles('c1cccc1', sanitize=False) 2983 res = Chem.SanitizeMol(m, catchErrors=True) 2984 self.assertEqual(res, Chem.SanitizeFlags.SANITIZE_KEKULIZE) 2985 2986 m = Chem.MolFromSmiles('CC(C)(C)(C)C', sanitize=False) 2987 res = Chem.SanitizeMol(m, catchErrors=True) 2988 self.assertEqual(res, Chem.SanitizeFlags.SANITIZE_PROPERTIES) 2989 2990 m = Chem.MolFromSmiles('c1cccc1', sanitize=False) 2991 res = Chem.SanitizeMol( 2992 m, sanitizeOps=Chem.SanitizeFlags.SANITIZE_ALL ^ Chem.SanitizeFlags.SANITIZE_KEKULIZE, 2993 catchErrors=True) 2994 self.assertEqual(res, Chem.SanitizeFlags.SANITIZE_NONE) 2995 2996 def test74Issue3510149(self): 2997 mol = Chem.MolFromSmiles("CCC1CNCC1CC") 2998 atoms = mol.GetAtoms() 2999 mol = None 3000 for atom in atoms: 3001 idx = atom.GetIdx() 3002 p = atom.GetOwningMol().GetNumAtoms() 3003 3004 mol = Chem.MolFromSmiles("CCC1CNCC1CC") 3005 bonds = mol.GetBonds() 3006 mol = None 3007 for bond in bonds: 3008 idx = bond.GetIdx() 3009 p = atom.GetOwningMol().GetNumAtoms() 3010 3011 mol = Chem.MolFromSmiles("CCC1CNCC1CC") 3012 bond = mol.GetBondBetweenAtoms(0, 1) 3013 mol = None 3014 idx = bond.GetBeginAtomIdx() 3015 p = bond.GetOwningMol().GetNumAtoms() 3016 3017 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 3018 'NCI_aids_few.sdf') 3019 sdSup = Chem.SDMolSupplier(fileN) 3020 mol = next(sdSup) 3021 nats = mol.GetNumAtoms() 3022 conf = mol.GetConformer() 3023 mol = None 3024 self.assertEqual(nats, conf.GetNumAtoms()) 3025 conf.GetOwningMol().GetProp("_Name") 3026 3027 def test75AllBondsExplicit(self): 3028 m = Chem.MolFromSmiles("CCC") 3029 smi = Chem.MolToSmiles(m) 3030 self.assertEqual(smi, "CCC") 3031 smi = Chem.MolToSmiles(m, allBondsExplicit=True) 3032 self.assertEqual(smi, "C-C-C") 3033 3034 m = Chem.MolFromSmiles("c1ccccc1") 3035 smi = Chem.MolToSmiles(m) 3036 self.assertEqual(smi, "c1ccccc1") 3037 smi = Chem.MolToSmiles(m, allBondsExplicit=True) 3038 self.assertEqual(smi, "c1:c:c:c:c:c:1") 3039 3040 def test76VeryLargeMolecule(self): 3041 # this is sf.net issue 3524984 3042 smi = '[C@H](F)(Cl)' + 'c1cc[nH]c1' * 500 + '[C@H](F)(Cl)' 3043 m = Chem.MolFromSmiles(smi) 3044 self.assertTrue(m) 3045 self.assertEqual(m.GetNumAtoms(), 2506) 3046 scs = Chem.FindMolChiralCenters(m) 3047 self.assertEqual(len(scs), 2) 3048 3049 def test77MolFragmentToSmiles(self): 3050 smi = "OC1CC1CC" 3051 m = Chem.MolFromSmiles(smi) 3052 fsmi = Chem.MolFragmentToSmiles(m, [1, 2, 3]) 3053 self.assertEqual(fsmi, "C1CC1") 3054 fsmi = Chem.MolFragmentToSmiles(m, [1, 2, 3], bondsToUse=[1, 2, 5]) 3055 self.assertEqual(fsmi, "C1CC1") 3056 fsmi = Chem.MolFragmentToSmiles(m, [1, 2, 3], bondsToUse=[1, 2]) 3057 self.assertEqual(fsmi, "CCC") 3058 fsmi = Chem.MolFragmentToSmiles(m, [1, 2, 3], atomSymbols=["", "[A]", "[C]", "[B]", "", ""]) 3059 self.assertEqual(fsmi, "[A]1[B][C]1") 3060 fsmi = Chem.MolFragmentToSmiles(m, [1, 2, 3], bondSymbols=["", "%", "%", "", "", "%"]) 3061 self.assertEqual(fsmi, "C1%C%C%1") 3062 3063 smi = "c1ccccc1C" 3064 m = Chem.MolFromSmiles(smi) 3065 fsmi = Chem.MolFragmentToSmiles(m, range(6)) 3066 self.assertEqual(fsmi, "c1ccccc1") 3067 Chem.Kekulize(m) 3068 fsmi = Chem.MolFragmentToSmiles(m, range(6), kekuleSmiles=True) 3069 self.assertEqual(fsmi, "C1=CC=CC=C1") 3070 fsmi = Chem.MolFragmentToSmiles(m, range(6), atomSymbols=["[C]"] * 7, kekuleSmiles=True) 3071 self.assertEqual(fsmi, "[C]1=[C][C]=[C][C]=[C]1") 3072 3073 self.assertRaises(ValueError, lambda: Chem.MolFragmentToSmiles(m, [])) 3074 3075 def test78AtomAndBondProps(self): 3076 m = Chem.MolFromSmiles('c1ccccc1') 3077 at = m.GetAtomWithIdx(0) 3078 self.assertFalse(at.HasProp('foo')) 3079 at.SetProp('foo', 'bar') 3080 self.assertTrue(at.HasProp('foo')) 3081 self.assertEqual(at.GetProp('foo'), 'bar') 3082 bond = m.GetBondWithIdx(0) 3083 self.assertFalse(bond.HasProp('foo')) 3084 bond.SetProp('foo', 'bar') 3085 self.assertTrue(bond.HasProp('foo')) 3086 self.assertEqual(bond.GetProp('foo'), 'bar') 3087 3088 def test79AddRecursiveStructureQueries(self): 3089 qs = {'carbonyl': Chem.MolFromSmiles('CO'), 'amine': Chem.MolFromSmiles('CN')} 3090 q = Chem.MolFromSmiles('CCC') 3091 q.GetAtomWithIdx(0).SetProp('query', 'carbonyl,amine') 3092 Chem.MolAddRecursiveQueries(q, qs, 'query') 3093 m = Chem.MolFromSmiles('CCCO') 3094 self.assertTrue(m.HasSubstructMatch(q)) 3095 m = Chem.MolFromSmiles('CCCN') 3096 self.assertTrue(m.HasSubstructMatch(q)) 3097 m = Chem.MolFromSmiles('CCCC') 3098 self.assertFalse(m.HasSubstructMatch(q)) 3099 3100 def test80ParseMolQueryDefFile(self): 3101 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'ChemTransforms', 'testData', 3102 'query_file1.txt') 3103 d = Chem.ParseMolQueryDefFile(fileN, standardize=False) 3104 self.assertTrue('CarboxylicAcid' in d) 3105 m = Chem.MolFromSmiles('CC(=O)O') 3106 self.assertTrue(m.HasSubstructMatch(d['CarboxylicAcid'])) 3107 self.assertFalse(m.HasSubstructMatch(d['CarboxylicAcid.Aromatic'])) 3108 3109 d = Chem.ParseMolQueryDefFile(fileN) 3110 self.assertTrue('carboxylicacid' in d) 3111 self.assertFalse('CarboxylicAcid' in d) 3112 3113 def test81Issue275(self): 3114 smi = Chem.MolToSmiles(Chem.MurckoDecompose( 3115 Chem.MolFromSmiles('CCCCC[C@H]1CC[C@H](C(=O)O)CC1'))) 3116 self.assertEqual(smi, 'C1CCCCC1') 3117 3118 def test82Issue288(self): 3119 m = Chem.MolFromSmiles('CC*') 3120 m.GetAtomWithIdx(2).SetProp('molAtomMapNumber', '30') 3121 3122 smi = Chem.MolToSmiles(m) 3123 self.assertEqual(smi, 'CC[*:30]') 3124 # try newer api 3125 m = Chem.MolFromSmiles('CC*') 3126 m.GetAtomWithIdx(2).SetAtomMapNum(30) 3127 smi = Chem.MolToSmiles(m) 3128 self.assertEqual(smi, 'CC[*:30]') 3129 3130 def test83GitHubIssue19(self): 3131 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 3132 'empty2.sdf') 3133 with self.assertRaises(OSError): 3134 sdSup = Chem.SDMolSupplier(fileN) 3135 3136 sdSup = Chem.SDMolSupplier() 3137 sdSup.SetData('') 3138 self.assertTrue(sdSup.atEnd()) 3139 self.assertRaises(IndexError, lambda: sdSup[0]) 3140 3141 sdSup.SetData('') 3142 self.assertRaises(IndexError, lambda: sdSup[0]) 3143 self.assertEqual(len(sdSup), 0) 3144 3145 def test84PDBBasics(self): 3146 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 3147 '1CRN.pdb') 3148 m = Chem.MolFromPDBFile(fileN, proximityBonding=False) 3149 self.assertEqual(m.GetNumAtoms(), 327) 3150 self.assertEqual(m.GetNumBonds(), 3) 3151 m = Chem.MolFromPDBFile(fileN) 3152 self.assertTrue(m is not None) 3153 self.assertEqual(m.GetNumAtoms(), 327) 3154 self.assertEqual(m.GetNumBonds(), 337) 3155 self.assertTrue(m.GetAtomWithIdx(0).GetPDBResidueInfo()) 3156 self.assertEqual(m.GetAtomWithIdx(0).GetPDBResidueInfo().GetName(), " N ") 3157 self.assertEqual(m.GetAtomWithIdx(0).GetPDBResidueInfo().GetResidueName(), "THR") 3158 self.assertAlmostEqual(m.GetAtomWithIdx(0).GetPDBResidueInfo().GetTempFactor(), 13.79, 2) 3159 m = Chem.MolFromPDBBlock(Chem.MolToPDBBlock(m)) 3160 self.assertEqual(m.GetNumAtoms(), 327) 3161 self.assertEqual(m.GetNumBonds(), 337) 3162 self.assertTrue(m.GetAtomWithIdx(0).GetPDBResidueInfo()) 3163 self.assertEqual(m.GetAtomWithIdx(0).GetPDBResidueInfo().GetName(), " N ") 3164 self.assertEqual(m.GetAtomWithIdx(0).GetPDBResidueInfo().GetResidueName(), "THR") 3165 self.assertAlmostEqual(m.GetAtomWithIdx(0).GetPDBResidueInfo().GetTempFactor(), 13.79, 2) 3166 # test multivalent Hs 3167 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 3168 '2c92_hypervalentH.pdb') 3169 mol = Chem.MolFromPDBFile(fileN, sanitize=False, removeHs=False) 3170 atom = mol.GetAtomWithIdx(84) 3171 self.assertEqual(atom.GetAtomicNum(), 1) # is it H 3172 self.assertEqual(atom.GetDegree(), 1) # H should have 1 bond 3173 for n in atom.GetNeighbors(): # Check if neighbor is from the same residue 3174 self.assertEqual(atom.GetPDBResidueInfo().GetResidueName(), 3175 n.GetPDBResidueInfo().GetResidueName()) 3176 # test unbinding metals (ZN) 3177 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 3178 '1ps3_zn.pdb') 3179 mol = Chem.MolFromPDBFile(fileN, sanitize=False, removeHs=False) 3180 atom = mol.GetAtomWithIdx(40) 3181 self.assertEqual(atom.GetAtomicNum(), 30) # is it Zn 3182 self.assertEqual(atom.GetDegree(), 4) # Zn should have 4 zero-order bonds 3183 self.assertEqual(atom.GetExplicitValence(), 0) 3184 bonds_order = [bond.GetBondType() for bond in atom.GetBonds()] 3185 self.assertEqual(bonds_order, [Chem.BondType.ZERO] * atom.GetDegree()) 3186 3187 # test metal bonds without proximity bonding 3188 mol = Chem.MolFromPDBFile(fileN, sanitize=False, removeHs=False, proximityBonding=False) 3189 atom = mol.GetAtomWithIdx(40) 3190 self.assertEqual(atom.GetAtomicNum(), 30) # is it Zn 3191 self.assertEqual(atom.GetDegree(), 4) # Zn should have 4 zero-order bonds 3192 self.assertEqual(atom.GetExplicitValence(), 0) 3193 bonds_order = [bond.GetBondType() for bond in atom.GetBonds()] 3194 self.assertEqual(bonds_order, [Chem.BondType.ZERO] * atom.GetDegree()) 3195 # test unbinding HOHs 3196 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 3197 '2vnf_bindedHOH.pdb') 3198 mol = Chem.MolFromPDBFile(fileN, sanitize=False, removeHs=False) 3199 atom = mol.GetAtomWithIdx(10) 3200 self.assertEqual(atom.GetPDBResidueInfo().GetResidueName(), 'HOH') 3201 self.assertEqual(atom.GetDegree(), 0) # HOH should have no bonds 3202 # test metal bonding in ligand 3203 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 3204 '2dej_APW.pdb') 3205 mol = Chem.MolFromPDBFile(fileN, sanitize=False, removeHs=False) 3206 atom = mol.GetAtomWithIdx(6) 3207 self.assertEqual(atom.GetAtomicNum(), 12) 3208 self.assertEqual(atom.GetDegree(), 2) 3209 atom = mol.GetAtomWithIdx(35) 3210 self.assertEqual(atom.GetPDBResidueInfo().GetResidueName(), 'HOH') 3211 self.assertEqual(atom.GetDegree(), 0) 3212 3213 def test85AtomCopying(self): 3214 """Can a copied atom be added to a molecule?""" 3215 import copy 3216 m = Chem.MolFromSmiles('C1CC1') 3217 a = m.GetAtomWithIdx(0) 3218 a_copy1 = copy.copy(a) 3219 a_copy2 = Chem.Atom(a) 3220 m = None 3221 a = None 3222 3223 def assert_is_valid_atom(a): 3224 new_m = Chem.RWMol() 3225 new_m.AddAtom(a) 3226 # This will not match if the owning mol is unset for a_copy, 3227 # or if there has been a clean up. 3228 self.assertEqual(new_m.GetAtomWithIdx(0).GetIdx(), 0) 3229 3230 assert_is_valid_atom(a_copy1) 3231 assert_is_valid_atom(a_copy2) 3232 3233 def test85MolCopying(self): 3234 m = Chem.MolFromSmiles('C1CC1[C@H](F)Cl') 3235 m.SetProp('foo', 'bar') 3236 m2 = Chem.Mol(m) 3237 self.assertEqual(Chem.MolToSmiles(m, True), Chem.MolToSmiles(m2, True)) 3238 self.assertTrue(m2.HasProp('foo')) 3239 self.assertEqual(m2.GetProp('foo'), 'bar') 3240 ri = m2.GetRingInfo() 3241 self.assertTrue(ri) 3242 self.assertEqual(ri.NumRings(), 1) 3243 3244 def test85MolCopying2(self): 3245 import copy 3246 m1 = Chem.MolFromSmiles('CC') 3247 m1.SetProp('Foo', 'bar') 3248 m1.foo = [1] 3249 m2 = copy.copy(m1) 3250 m3 = copy.copy(m2) 3251 m4 = copy.deepcopy(m1) 3252 m5 = copy.deepcopy(m2) 3253 m6 = copy.deepcopy(m4) 3254 3255 self.assertEqual(m1.GetProp('Foo'), 'bar') 3256 self.assertEqual(m2.GetProp('Foo'), 'bar') 3257 self.assertEqual(m3.GetProp('Foo'), 'bar') 3258 self.assertEqual(m4.GetProp('Foo'), 'bar') 3259 self.assertEqual(m5.GetProp('Foo'), 'bar') 3260 self.assertEqual(m6.GetProp('Foo'), 'bar') 3261 3262 m2.foo.append(4) 3263 self.assertEqual(m1.foo, [1, 4]) 3264 self.assertEqual(m2.foo, [1, 4]) 3265 self.assertEqual(m3.foo, [1, 4]) 3266 self.assertEqual(m4.foo, [1]) 3267 self.assertEqual(m5.foo, [1]) 3268 self.assertEqual(m6.foo, [1]) 3269 3270 m7 = Chem.RWMol(m1) 3271 self.assertFalse(hasattr(m7, 'foo')) 3272 m7.foo = [1] 3273 m8 = copy.copy(m7) 3274 m9 = copy.deepcopy(m7) 3275 m8.foo.append(4) 3276 self.assertEqual(m7.GetProp('Foo'), 'bar') 3277 self.assertEqual(m8.GetProp('Foo'), 'bar') 3278 self.assertEqual(m9.GetProp('Foo'), 'bar') 3279 self.assertEqual(m8.foo, [1, 4]) 3280 self.assertEqual(m9.foo, [1]) 3281 3282 def test86MolRenumbering(self): 3283 import random 3284 m = Chem.MolFromSmiles('C[C@H]1CC[C@H](C/C=C/[C@H](F)Cl)CC1') 3285 cSmi = Chem.MolToSmiles(m, True) 3286 for i in range(m.GetNumAtoms()): 3287 ans = list(range(m.GetNumAtoms())) 3288 random.shuffle(ans) 3289 m2 = Chem.RenumberAtoms(m, ans) 3290 nSmi = Chem.MolToSmiles(m2, True) 3291 self.assertEqual(cSmi, nSmi) 3292 3293 def test87FragmentOnBonds(self): 3294 m = Chem.MolFromSmiles('CC1CC(O)C1CCC1CC1') 3295 bis = m.GetSubstructMatches(Chem.MolFromSmarts('[!R][R]')) 3296 bs = [] 3297 labels = [] 3298 for bi in bis: 3299 b = m.GetBondBetweenAtoms(bi[0], bi[1]) 3300 if b.GetBeginAtomIdx() == bi[0]: 3301 labels.append((10, 1)) 3302 else: 3303 labels.append((1, 10)) 3304 bs.append(b.GetIdx()) 3305 nm = Chem.FragmentOnBonds(m, bs) 3306 frags = Chem.GetMolFrags(nm) 3307 self.assertEqual(len(frags), 5) 3308 self.assertEqual(frags, 3309 ((0, 12), (1, 2, 3, 5, 11, 14, 16), (4, 13), (6, 7, 15, 18), (8, 9, 10, 17))) 3310 smi = Chem.MolToSmiles(nm, True) 3311 self.assertEqual(smi, '*C1CC([4*])C1[6*].[1*]C.[3*]O.[5*]CC[8*].[7*]C1CC1') 3312 3313 nm = Chem.FragmentOnBonds(m, bs, dummyLabels=labels) 3314 frags = Chem.GetMolFrags(nm) 3315 self.assertEqual(len(frags), 5) 3316 self.assertEqual(frags, 3317 ((0, 12), (1, 2, 3, 5, 11, 14, 16), (4, 13), (6, 7, 15, 18), (8, 9, 10, 17))) 3318 smi = Chem.MolToSmiles(nm, True) 3319 self.assertEqual(smi, '[1*]C.[1*]CC[1*].[1*]O.[10*]C1CC([10*])C1[10*].[10*]C1CC1') 3320 3321 m = Chem.MolFromSmiles('CCC(=O)CC(=O)C') 3322 bis = m.GetSubstructMatches(Chem.MolFromSmarts('C=O')) 3323 bs = [] 3324 for bi in bis: 3325 b = m.GetBondBetweenAtoms(bi[0], bi[1]) 3326 bs.append(b.GetIdx()) 3327 bts = [Chem.BondType.DOUBLE] * len(bs) 3328 nm = Chem.FragmentOnBonds(m, bs, bondTypes=bts) 3329 frags = Chem.GetMolFrags(nm) 3330 self.assertEqual(len(frags), 3) 3331 smi = Chem.MolToSmiles(nm, True) 3332 self.assertEqual(smi, '[2*]=O.[3*]=C(CC)CC(=[6*])C.[5*]=O') 3333 3334 # github issue 430: 3335 m = Chem.MolFromSmiles('OCCCCN') 3336 self.assertRaises(ValueError, lambda: Chem.FragmentOnBonds(m, ())) 3337 3338 def test88QueryAtoms(self): 3339 from rdkit.Chem import rdqueries 3340 m = Chem.MolFromSmiles('c1nc(C)n(CC)c1') 3341 3342 qa = rdqueries.ExplicitDegreeEqualsQueryAtom(3) 3343 l = tuple([x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)]) 3344 self.assertEqual(l, (2, 4)) 3345 3346 qa.ExpandQuery(rdqueries.AtomNumEqualsQueryAtom(6, negate=True)) 3347 l = tuple([x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)]) 3348 self.assertEqual(l, (4, )) 3349 3350 qa = rdqueries.ExplicitDegreeEqualsQueryAtom(3) 3351 qa.ExpandQuery(rdqueries.AtomNumEqualsQueryAtom(6, negate=True), 3352 how=Chem.CompositeQueryType.COMPOSITE_OR) 3353 l = tuple([x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)]) 3354 self.assertEqual(l, (1, 2, 4)) 3355 3356 qa = rdqueries.ExplicitDegreeEqualsQueryAtom(3) 3357 qa.ExpandQuery(rdqueries.AtomNumEqualsQueryAtom(6, negate=True), 3358 how=Chem.CompositeQueryType.COMPOSITE_XOR) 3359 l = tuple([x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)]) 3360 self.assertEqual(l, (1, 2)) 3361 3362 qa = rdqueries.ExplicitDegreeGreaterQueryAtom(2) 3363 l = tuple([x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)]) 3364 self.assertEqual(l, (2, 4)) 3365 3366 qa = rdqueries.ExplicitDegreeLessQueryAtom(2) 3367 l = tuple([x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)]) 3368 self.assertEqual(l, (3, 6)) 3369 3370 m = Chem.MolFromSmiles('N[CH][CH]') 3371 qa = rdqueries.NumRadicalElectronsGreaterQueryAtom(0) 3372 l = tuple([x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)]) 3373 self.assertEqual(l, (1, 2)) 3374 qa = rdqueries.NumRadicalElectronsGreaterQueryAtom(1) 3375 l = tuple([x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)]) 3376 self.assertEqual(l, (2, )) 3377 3378 m = Chem.MolFromSmiles('F[C@H](Cl)C') 3379 qa = rdqueries.HasChiralTagQueryAtom() 3380 l = tuple([x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)]) 3381 self.assertEqual(l, (1, )) 3382 qa = rdqueries.MissingChiralTagQueryAtom() 3383 l = tuple([x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)]) 3384 self.assertEqual(l, ()) 3385 3386 m = Chem.MolFromSmiles('F[CH](Cl)C') 3387 qa = rdqueries.HasChiralTagQueryAtom() 3388 l = tuple([x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)]) 3389 self.assertEqual(l, ()) 3390 qa = rdqueries.MissingChiralTagQueryAtom() 3391 l = tuple([x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)]) 3392 self.assertEqual(l, (1, )) 3393 3394 m = Chem.MolFromSmiles('CNCON') 3395 qa = rdqueries.NumHeteroatomNeighborsEqualsQueryAtom(2) 3396 l = tuple([x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)]) 3397 self.assertEqual(l, (2, )) 3398 qa = rdqueries.NumHeteroatomNeighborsGreaterQueryAtom(0) 3399 l = tuple([x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)]) 3400 self.assertEqual(l, (0, 2, 3, 4)) 3401 3402 def test89UnicodeInput(self): 3403 m = Chem.MolFromSmiles(u'c1ccccc1') 3404 self.assertTrue(m is not None) 3405 self.assertEqual(m.GetNumAtoms(), 6) 3406 m = Chem.MolFromSmarts(u'c1ccccc1') 3407 self.assertTrue(m is not None) 3408 self.assertEqual(m.GetNumAtoms(), 6) 3409 3410 def test90FragmentOnSomeBonds(self): 3411 m = Chem.MolFromSmiles('OCCCCN') 3412 pieces = Chem.FragmentOnSomeBonds(m, (0, 2, 4), 2) 3413 self.assertEqual(len(pieces), 3) 3414 3415 frags = Chem.GetMolFrags(pieces[0]) 3416 self.assertEqual(len(frags), 3) 3417 self.assertEqual(len(frags[0]), 2) 3418 self.assertEqual(len(frags[1]), 4) 3419 self.assertEqual(len(frags[2]), 4) 3420 3421 frags = Chem.GetMolFrags(pieces[1]) 3422 self.assertEqual(len(frags), 3) 3423 self.assertEqual(len(frags[0]), 2) 3424 self.assertEqual(len(frags[1]), 6) 3425 self.assertEqual(len(frags[2]), 2) 3426 3427 frags = Chem.GetMolFrags(pieces[2]) 3428 self.assertEqual(len(frags), 3) 3429 self.assertEqual(len(frags[0]), 4) 3430 self.assertEqual(len(frags[1]), 4) 3431 self.assertEqual(len(frags[2]), 2) 3432 3433 pieces, cpa = Chem.FragmentOnSomeBonds(m, (0, 2, 4), 2, returnCutsPerAtom=True) 3434 self.assertEqual(len(pieces), 3) 3435 self.assertEqual(len(cpa), 3) 3436 self.assertEqual(len(cpa[0]), m.GetNumAtoms()) 3437 3438 # github issue 430: 3439 m = Chem.MolFromSmiles('OCCCCN') 3440 self.assertRaises(ValueError, lambda: Chem.FragmentOnSomeBonds(m, ())) 3441 3442 pieces = Chem.FragmentOnSomeBonds(m, (0, 2, 4), 0) 3443 self.assertEqual(len(pieces), 0) 3444 3445 def test91RankAtoms(self): 3446 m = Chem.MolFromSmiles('ONCS.ONCS') 3447 ranks = Chem.CanonicalRankAtoms(m, breakTies=False) 3448 self.assertEqual(list(ranks[0:4]), list(ranks[4:])) 3449 3450 m = Chem.MolFromSmiles("c1ccccc1") 3451 ranks = Chem.CanonicalRankAtoms(m, breakTies=False) 3452 for x in ranks: 3453 self.assertEqual(x, 0) 3454 3455 m = Chem.MolFromSmiles("C1NCN1") 3456 ranks = Chem.CanonicalRankAtoms(m, breakTies=False) 3457 self.assertEqual(ranks[0], ranks[2]) 3458 self.assertEqual(ranks[1], ranks[3]) 3459 3460 def test92RankAtomsInFragment(self): 3461 m = Chem.MolFromSmiles('ONCS.ONCS') 3462 ranks = Chem.CanonicalRankAtomsInFragment(m, [0, 1, 2, 3], [0, 1, 2]) 3463 3464 ranks2 = Chem.CanonicalRankAtomsInFragment(m, [4, 5, 6, 7], [3, 4, 5]) 3465 self.assertEqual(list(ranks[0:4]), list(ranks2[4:])) 3466 self.assertEqual(list(ranks[4:]), [-1] * 4) 3467 self.assertEqual(list(ranks2[0:4]), [-1] * 4) 3468 3469 # doc tests 3470 mol = Chem.MolFromSmiles('C1NCN1.C1NCN1') 3471 self.assertEqual( 3472 list(Chem.CanonicalRankAtomsInFragment(mol, atomsToUse=range(0, 4), breakTies=False)), 3473 [4, 6, 4, 6, -1, -1, -1, -1]) 3474 self.assertNotEqual( 3475 list(Chem.CanonicalRankAtomsInFragment(mol, atomsToUse=range(0, 4), breakTies=True)), 3476 [4, 6, 4, 6, -1, -1, -1, -1]) 3477 self.assertEqual( 3478 list(Chem.CanonicalRankAtomsInFragment(mol, atomsToUse=range(4, 8), breakTies=False)), 3479 [-1, -1, -1, -1, 4, 6, 4, 6]) 3480 self.assertNotEqual( 3481 list(Chem.CanonicalRankAtomsInFragment(mol, atomsToUse=range(4, 8), breakTies=True)), 3482 [-1, -1, -1, -1, 4, 6, 4, 6]) 3483 3484 def test93RWMolsAsROMol(self): 3485 """ test the RWMol class as a proper ROMol 3486 3487 """ 3488 mol = Chem.MolFromSmiles('C1CCC1') 3489 self.assertTrue(type(mol) == Chem.Mol) 3490 rwmol = Chem.RWMol(mol) 3491 self.assertEqual(Chem.MolToSmiles(rwmol, True), Chem.MolToSmiles(rwmol.GetMol())) 3492 newAt = Chem.Atom(8) 3493 rwmol.ReplaceAtom(0, newAt) 3494 self.assertEqual(Chem.MolToSmiles(rwmol, True), Chem.MolToSmiles(rwmol.GetMol())) 3495 3496 def test94CopyWithConfs(self): 3497 """ test copying Mols with some conformers 3498 3499 """ 3500 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 3501 'cmpd2.tpl') 3502 m1 = Chem.MolFromTPLFile(fileN) 3503 self.assertTrue(m1 is not None) 3504 self.assertEqual(m1.GetNumAtoms(), 12) 3505 self.assertEqual(m1.GetNumConformers(), 2) 3506 self.assertEqual(m1.GetConformer(0).GetNumAtoms(), 12) 3507 self.assertEqual(m1.GetConformer(1).GetNumAtoms(), 12) 3508 3509 m2 = Chem.Mol(m1) 3510 self.assertEqual(m2.GetNumAtoms(), 12) 3511 self.assertEqual(m2.GetNumConformers(), 2) 3512 self.assertEqual(m2.GetConformer(0).GetNumAtoms(), 12) 3513 self.assertEqual(m2.GetConformer(1).GetNumAtoms(), 12) 3514 3515 m2 = Chem.Mol(m1, False, 0) 3516 self.assertEqual(m2.GetNumAtoms(), 12) 3517 self.assertEqual(m2.GetNumConformers(), 1) 3518 self.assertEqual(m2.GetConformer(0).GetNumAtoms(), 12) 3519 3520 m2 = Chem.Mol(m1, False, 1) 3521 self.assertEqual(m2.GetNumAtoms(), 12) 3522 self.assertEqual(m2.GetNumConformers(), 1) 3523 self.assertEqual(m2.GetConformer(1).GetNumAtoms(), 12) 3524 3525 m2 = Chem.Mol(m1, True) 3526 self.assertTrue(m2.GetNumAtoms() == 12) 3527 self.assertTrue(m2.GetNumConformers() == 0) 3528 3529 m2 = Chem.RWMol(m1) 3530 self.assertEqual(m2.GetNumAtoms(), 12) 3531 self.assertEqual(m2.GetNumConformers(), 2) 3532 self.assertEqual(m2.GetConformer(0).GetNumAtoms(), 12) 3533 self.assertEqual(m2.GetConformer(1).GetNumAtoms(), 12) 3534 3535 m2 = Chem.RWMol(m1, False, 0) 3536 self.assertEqual(m2.GetNumAtoms(), 12) 3537 self.assertEqual(m2.GetNumConformers(), 1) 3538 self.assertEqual(m2.GetConformer(0).GetNumAtoms(), 12) 3539 3540 m2 = Chem.RWMol(m1, False, 1) 3541 self.assertEqual(m2.GetNumAtoms(), 12) 3542 self.assertEqual(m2.GetNumConformers(), 1) 3543 self.assertEqual(m2.GetConformer(1).GetNumAtoms(), 12) 3544 3545 m2 = Chem.RWMol(m1, True) 3546 self.assertTrue(m2.GetNumAtoms() == 12) 3547 self.assertTrue(m2.GetNumConformers() == 0) 3548 3549 def testAtomPropQueries(self): 3550 """ test the property queries 3551 """ 3552 from rdkit.Chem import rdqueries 3553 3554 m = Chem.MolFromSmiles("C" * 14) 3555 atoms = m.GetAtoms() 3556 atoms[0].SetProp("hah", "hah") 3557 atoms[1].SetIntProp("bar", 1) 3558 atoms[2].SetIntProp("bar", 2) 3559 atoms[3].SetBoolProp("baz", True) 3560 atoms[4].SetBoolProp("baz", False) 3561 atoms[5].SetProp("boo", "hoo") 3562 atoms[6].SetProp("boo", "-urns") 3563 atoms[7].SetDoubleProp("boot", 1.0) 3564 atoms[8].SetDoubleProp("boot", 4.0) 3565 atoms[9].SetDoubleProp("number", 4.0) 3566 atoms[10].SetIntProp("number", 4) 3567 3568 tests = ((rdqueries.HasIntPropWithValueQueryAtom, "bar", { 3569 1: [1], 3570 2: [2] 3571 }), (rdqueries.HasBoolPropWithValueQueryAtom, "baz", { 3572 True: [3], 3573 False: [4] 3574 }), (rdqueries.HasStringPropWithValueQueryAtom, "boo", { 3575 "hoo": [5], 3576 "-urns": [6] 3577 }), (rdqueries.HasDoublePropWithValueQueryAtom, "boot", { 3578 1.0: [7], 3579 4.0: [8] 3580 })) 3581 3582 for query, name, lookups in tests: 3583 for t, v in lookups.items(): 3584 q = query(name, t) 3585 self.assertEqual(v, [x.GetIdx() for x in m.GetAtomsMatchingQuery(q)]) 3586 q = query(name, t, negate=True) 3587 self.assertEqual(sorted(set(range(14)) - set(v)), 3588 [x.GetIdx() for x in m.GetAtomsMatchingQuery(q)]) 3589 3590 # check tolerances 3591 self.assertEqual([ 3592 x.GetIdx() for x in m.GetAtomsMatchingQuery( 3593 rdqueries.HasDoublePropWithValueQueryAtom("boot", 1.0, tolerance=3.)) 3594 ], [7, 8]) 3595 3596 # numbers are numbers?, i.e. int!=double 3597 self.assertEqual([ 3598 x.GetIdx() 3599 for x in m.GetAtomsMatchingQuery(rdqueries.HasIntPropWithValueQueryAtom("number", 4)) 3600 ], [10]) 3601 3602 def testBondPropQueries(self): 3603 """ test the property queries 3604 """ 3605 from rdkit.Chem import rdqueries 3606 3607 m = Chem.MolFromSmiles("C" * 14) 3608 bonds = m.GetBonds() 3609 bonds[0].SetProp("hah", "hah") 3610 bonds[1].SetIntProp("bar", 1) 3611 bonds[2].SetIntProp("bar", 2) 3612 bonds[3].SetBoolProp("baz", True) 3613 bonds[4].SetBoolProp("baz", False) 3614 bonds[5].SetProp("boo", "hoo") 3615 bonds[6].SetProp("boo", "-urns") 3616 bonds[7].SetDoubleProp("boot", 1.0) 3617 bonds[8].SetDoubleProp("boot", 4.0) 3618 bonds[9].SetDoubleProp("number", 4.0) 3619 bonds[10].SetIntProp("number", 4) 3620 3621 tests = ((rdqueries.HasIntPropWithValueQueryBond, "bar", { 3622 1: [1], 3623 2: [2] 3624 }), (rdqueries.HasBoolPropWithValueQueryBond, "baz", { 3625 True: [3], 3626 False: [4] 3627 }), (rdqueries.HasStringPropWithValueQueryBond, "boo", { 3628 "hoo": [5], 3629 "-urns": [6] 3630 }), (rdqueries.HasDoublePropWithValueQueryBond, "boot", { 3631 1.0: [7], 3632 4.0: [8] 3633 })) 3634 3635 for query, name, lookups in tests: 3636 for t, v in lookups.items(): 3637 q = query(name, t) 3638 self.assertEqual(v, [x.GetIdx() for x in m.GetBonds() if q.Match(x)]) 3639 q = query(name, t, negate=True) 3640 self.assertEqual(sorted(set(range(13)) - set(v)), 3641 [x.GetIdx() for x in m.GetBonds() if q.Match(x)]) 3642 3643 # check tolerances 3644 q = rdqueries.HasDoublePropWithValueQueryBond("boot", 1.0, tolerance=3.) 3645 self.assertEqual([x.GetIdx() for x in m.GetBonds() if q.Match(x)], [7, 8]) 3646 3647 # numbers are numbers?, i.e. int!=double 3648 q = rdqueries.HasIntPropWithValueQueryBond("number", 4) 3649 self.assertEqual([x.GetIdx() for x in m.GetBonds() if q.Match(x)], [10]) 3650 3651 def testGetShortestPath(self): 3652 """ test the GetShortestPath() wrapper 3653 """ 3654 smi = "CC(OC1C(CCCC3)C3C(CCCC2)C2C1OC(C)=O)=O" 3655 m = Chem.MolFromSmiles(smi) 3656 path = Chem.GetShortestPath(m, 1, 20) 3657 self.assertEqual(path, (1, 2, 3, 16, 17, 18, 20)) 3658 3659 def testGithub497(self): 3660 with tempfile.TemporaryFile() as tmp, gzip.open(tmp) as outf: 3661 with self.assertRaises(ValueError): 3662 w = Chem.SDWriter(outf) 3663 3664 def testGithub498(self): 3665 if (sys.version_info < (3, 0)): 3666 mode = 'w+' 3667 else: 3668 mode = 'wt+' 3669 m = Chem.MolFromSmiles('C') 3670 with tempfile.NamedTemporaryFile() as tmp, gzip.open(tmp, mode) as outf: 3671 w = Chem.SDWriter(outf) 3672 w.write(m) 3673 w.close() 3674 3675 def testReplaceBond(self): 3676 origmol = Chem.RWMol(Chem.MolFromSmiles("CC")) 3677 bonds = list(origmol.GetBonds()) 3678 self.assertEqual(len(bonds), 1) 3679 singlebond = bonds[0] 3680 self.assertEqual(singlebond.GetBondType(), Chem.BondType.SINGLE) 3681 3682 # this is the only way we create a bond, is take it from another molecule 3683 doublebonded = Chem.MolFromSmiles("C=C") 3684 doublebond = list(doublebonded.GetBonds())[0] 3685 3686 # make sure replacing the bond changes the smiles 3687 self.assertEqual(Chem.MolToSmiles(origmol), "CC") 3688 origmol.ReplaceBond(singlebond.GetIdx(), doublebond) 3689 Chem.SanitizeMol(origmol) 3690 3691 self.assertEqual(Chem.MolToSmiles(origmol), "C=C") 3692 3693 def testAdjustQueryProperties(self): 3694 m = Chem.MolFromSmarts('C1CCC1*') 3695 am = Chem.AdjustQueryProperties(m) 3696 self.assertTrue(Chem.MolFromSmiles('C1CCC1C').HasSubstructMatch(m)) 3697 self.assertTrue(Chem.MolFromSmiles('C1CCC1C').HasSubstructMatch(am)) 3698 self.assertTrue(Chem.MolFromSmiles('C1CC(C)C1C').HasSubstructMatch(m)) 3699 self.assertFalse(Chem.MolFromSmiles('C1CC(C)C1C').HasSubstructMatch(am)) 3700 3701 m = Chem.MolFromSmiles('C1CCC1*') 3702 am = Chem.AdjustQueryProperties(m) 3703 self.assertFalse(Chem.MolFromSmiles('C1CCC1C').HasSubstructMatch(m)) 3704 self.assertTrue(Chem.MolFromSmiles('C1CCC1C').HasSubstructMatch(am)) 3705 qps = Chem.AdjustQueryParameters() 3706 qps.makeDummiesQueries = False 3707 am = Chem.AdjustQueryProperties(m, qps) 3708 self.assertFalse(Chem.MolFromSmiles('C1CCC1C').HasSubstructMatch(am)) 3709 3710 m = Chem.MolFromSmiles('C1=CC=CC=C1', sanitize=False) 3711 am = Chem.AdjustQueryProperties(m) 3712 self.assertTrue(Chem.MolFromSmiles('c1ccccc1').HasSubstructMatch(am)) 3713 qp = Chem.AdjustQueryParameters() 3714 qp.aromatizeIfPossible = False 3715 am = Chem.AdjustQueryProperties(m, qp) 3716 self.assertFalse(Chem.MolFromSmiles('c1ccccc1').HasSubstructMatch(am)) 3717 3718 m = Chem.MolFromSmiles('C1CCC1OC') 3719 qps = Chem.AdjustQueryParameters() 3720 qps.makeAtomsGeneric = True 3721 am = Chem.AdjustQueryProperties(m, qps) 3722 self.assertEqual(Chem.MolToSmarts(am), '*1-*-*-*-1-*-*') 3723 qps.makeAtomsGenericFlags = Chem.ADJUST_IGNORERINGS 3724 am = Chem.AdjustQueryProperties(m, qps) 3725 self.assertEqual(Chem.MolToSmarts(am), '[#6&D2]1-[#6&D2]-[#6&D2]-[#6&D3]-1-*-*') 3726 3727 qps = Chem.AdjustQueryParameters() 3728 qps.makeBondsGeneric = True 3729 am = Chem.AdjustQueryProperties(m, qps) 3730 self.assertEqual(Chem.MolToSmarts(am), '[#6&D2]1~[#6&D2]~[#6&D2]~[#6&D3]~1~[#8]~[#6]') 3731 qps.makeBondsGenericFlags = Chem.ADJUST_IGNORERINGS 3732 am = Chem.AdjustQueryProperties(m, qps) 3733 self.assertEqual(Chem.MolToSmarts(am), '[#6&D2]1-[#6&D2]-[#6&D2]-[#6&D3]-1~[#8]~[#6]') 3734 3735 def testMolFragmentSmarts(self): 3736 m = Chem.MolFromSmiles('C1CCC1OC') 3737 self.assertEqual(Chem.MolFragmentToSmarts(m, [0, 1, 2]), '[#6]-[#6]-[#6]') 3738 # if bondsToUse is honored, the ring won't show up 3739 self.assertEqual(Chem.MolFragmentToSmarts(m, [0, 1, 2, 3], bondsToUse=[0, 1, 2, 3]), 3740 '[#6]-[#6]-[#6]-[#6]') 3741 3742 # Does MolFragmentToSmarts accept output of AdjustQueryProperties? 3743 qps = Chem.AdjustQueryParameters() 3744 qps.makeAtomsGeneric = True 3745 am = Chem.AdjustQueryProperties(m, qps) 3746 self.assertEqual(Chem.MolFragmentToSmarts(am, [0, 1, 2]), '*-*-*') 3747 3748 def testAdjustQueryPropertiesgithubIssue1474(self): 3749 core = Chem.MolFromSmiles('[*:1]C1N([*:2])C([*:3])O1') 3750 core.GetAtomWithIdx(0).SetProp('foo', 'bar') 3751 core.GetAtomWithIdx(1).SetProp('foo', 'bar') 3752 3753 ap = Chem.AdjustQueryProperties(core) 3754 self.assertEqual(ap.GetAtomWithIdx(0).GetPropsAsDict()["foo"], "bar") 3755 self.assertEqual(ap.GetAtomWithIdx(1).GetPropsAsDict()["foo"], "bar") 3756 3757 def testGithubIssue579(self): 3758 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 3759 'NCI_aids_few.sdf.gz') 3760 inf = gzip.open(fileN) 3761 suppl = Chem.ForwardSDMolSupplier(inf) 3762 m0 = next(suppl) 3763 self.assertIsNot(m0, None) 3764 inf.close() 3765 del suppl 3766 3767 def testSequenceBasics(self): 3768 " very basic round-tripping of the sequence reader/writer support " 3769 helm = 'PEPTIDE1{C.Y.I.Q.N.C.P.L.G}$$$$' 3770 seq = 'CYIQNCPLG' 3771 fasta = '>\nCYIQNCPLG\n' 3772 smi = 'CC[C@H](C)[C@H](NC(=O)[C@H](Cc1ccc(O)cc1)NC(=O)[C@@H](N)CS)C(=O)N[C@@H](CCC(N)=O)C(=O)N[C@@H](CC(N)=O)C(=O)N[C@@H](CS)C(=O)N1CCC[C@H]1C(=O)N[C@@H](CC(C)C)C(=O)NCC(=O)O' 3773 3774 m = Chem.MolFromSequence(seq) 3775 self.assertTrue(m is not None) 3776 self.assertEqual(Chem.MolToSequence(m), seq) 3777 self.assertEqual(Chem.MolToHELM(m), helm) 3778 self.assertEqual(Chem.MolToFASTA(m), fasta) 3779 self.assertEqual(Chem.MolToSmiles(m, isomericSmiles=True), smi) 3780 3781 m = Chem.MolFromHELM(helm) 3782 self.assertTrue(m is not None) 3783 self.assertEqual(Chem.MolToSequence(m), seq) 3784 self.assertEqual(Chem.MolToHELM(m), helm) 3785 self.assertEqual(Chem.MolToFASTA(m), fasta) 3786 self.assertEqual(Chem.MolToSmiles(m, isomericSmiles=True), smi) 3787 3788 m = Chem.MolFromFASTA(fasta) 3789 self.assertTrue(m is not None) 3790 self.assertEqual(Chem.MolToSequence(m), seq) 3791 self.assertEqual(Chem.MolToHELM(m), helm) 3792 self.assertEqual(Chem.MolToFASTA(m), fasta) 3793 self.assertEqual(Chem.MolToSmiles(m, isomericSmiles=True), smi) 3794 3795 seq = "CGCGAATTACCGCG" 3796 m = Chem.MolFromSequence(seq, flavor=6) # DNA 3797 self.assertEqual(Chem.MolToSequence(m), 'CGCGAATTACCGCG') 3798 self.assertEqual( 3799 Chem.MolToHELM(m), 3800 'RNA1{[dR](C)P.[dR](G)P.[dR](C)P.[dR](G)P.[dR](A)P.[dR](A)P.[dR](T)P.[dR](T)P.[dR](A)P.[dR](C)P.[dR](C)P.[dR](G)P.[dR](C)P.[dR](G)}$$$$' 3801 ) 3802 seq = "CGCGAAUUACCGCG" 3803 m = Chem.MolFromSequence(seq, flavor=2) # RNA 3804 self.assertEqual(Chem.MolToSequence(m), 'CGCGAAUUACCGCG') 3805 self.assertEqual( 3806 Chem.MolToHELM(m), 3807 'RNA1{R(C)P.R(G)P.R(C)P.R(G)P.R(A)P.R(A)P.R(U)P.R(U)P.R(A)P.R(C)P.R(C)P.R(G)P.R(C)P.R(G)}$$$$' 3808 ) 3809 m = Chem.MolFromSequence(seq, flavor=3) # RNA - 5' cap 3810 self.assertEqual(Chem.MolToSequence(m), 'CGCGAAUUACCGCG') 3811 self.assertEqual( 3812 Chem.MolToHELM(m), 3813 'RNA1{P.R(C)P.R(G)P.R(C)P.R(G)P.R(A)P.R(A)P.R(U)P.R(U)P.R(A)P.R(C)P.R(C)P.R(G)P.R(C)P.R(G)}$$$$' 3814 ) 3815 3816 def testResMolSupplier(self): 3817 mol = Chem.MolFromSmiles('CC') 3818 resMolSuppl = Chem.ResonanceMolSupplier(mol) 3819 del resMolSuppl 3820 resMolSuppl = Chem.ResonanceMolSupplier(mol) 3821 self.assertEqual(resMolSuppl.GetNumConjGrps(), 0) 3822 self.assertEqual(len(resMolSuppl), 1) 3823 self.assertEqual(resMolSuppl.GetNumConjGrps(), 0) 3824 3825 mol = Chem.MolFromSmiles('NC(=[NH2+])c1ccc(cc1)C(=O)[O-]') 3826 totalFormalCharge = getTotalFormalCharge(mol) 3827 3828 resMolSuppl = Chem.ResonanceMolSupplier(mol) 3829 self.assertFalse(resMolSuppl.GetIsEnumerated()) 3830 self.assertEqual(len(resMolSuppl), 4) 3831 self.assertTrue(resMolSuppl.GetIsEnumerated()) 3832 3833 resMolSuppl = Chem.ResonanceMolSupplier(mol) 3834 self.assertFalse(resMolSuppl.GetIsEnumerated()) 3835 resMolSuppl.Enumerate() 3836 self.assertTrue(resMolSuppl.GetIsEnumerated()) 3837 self.assertTrue((resMolSuppl[0].GetBondBetweenAtoms(0, 1).GetBondType() \ 3838 != resMolSuppl[1].GetBondBetweenAtoms(0, 1).GetBondType()) 3839 or (resMolSuppl[0].GetBondBetweenAtoms(9, 10).GetBondType() \ 3840 != resMolSuppl[1].GetBondBetweenAtoms(9, 10).GetBondType())) 3841 3842 resMolSuppl = Chem.ResonanceMolSupplier(mol, Chem.KEKULE_ALL) 3843 self.assertEqual(len(resMolSuppl), 8) 3844 bondTypeSet = set() 3845 # check that we actually have two alternate Kekule structures 3846 bondTypeSet.add(resMolSuppl[0].GetBondBetweenAtoms(3, 4).GetBondType()) 3847 bondTypeSet.add(resMolSuppl[1].GetBondBetweenAtoms(3, 4).GetBondType()) 3848 self.assertEqual(len(bondTypeSet), 2) 3849 3850 bondTypeDict = {} 3851 resMolSuppl = Chem.ResonanceMolSupplier(mol, 3852 Chem.ALLOW_INCOMPLETE_OCTETS \ 3853 | Chem.UNCONSTRAINED_CATIONS \ 3854 | Chem.UNCONSTRAINED_ANIONS) 3855 self.assertEqual(len(resMolSuppl), 32) 3856 for i in range(len(resMolSuppl)): 3857 resMol = resMolSuppl[i] 3858 self.assertEqual(getTotalFormalCharge(resMol), totalFormalCharge) 3859 while (not resMolSuppl.atEnd()): 3860 resMol = next(resMolSuppl) 3861 self.assertEqual(getTotalFormalCharge(resMol), totalFormalCharge) 3862 resMolSuppl.reset() 3863 cmpFormalChargeBondOrder(self, resMolSuppl[0], next(resMolSuppl)) 3864 3865 resMolSuppl = Chem.ResonanceMolSupplier(mol, 3866 Chem.ALLOW_INCOMPLETE_OCTETS \ 3867 | Chem.UNCONSTRAINED_CATIONS \ 3868 | Chem.UNCONSTRAINED_ANIONS, 10) 3869 self.assertEqual(len(resMolSuppl), 10) 3870 3871 crambinPdb = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 3872 '1CRN.pdb') 3873 mol = Chem.MolFromPDBFile(crambinPdb) 3874 resMolSuppl = Chem.ResonanceMolSupplier(mol) 3875 self.assertEqual(len(resMolSuppl), 1) 3876 resMolSuppl = Chem.ResonanceMolSupplier(mol, Chem.KEKULE_ALL) 3877 self.assertEqual(len(resMolSuppl), 8) 3878 3879 def testSubstructMatchAcetate(self): 3880 mol = Chem.MolFromSmiles('CC(=O)[O-]') 3881 query = Chem.MolFromSmarts('C(=O)[O-]') 3882 3883 resMolSuppl = Chem.ResonanceMolSupplier(mol) 3884 matches = mol.GetSubstructMatches(query) 3885 self.assertEqual(len(matches), 1) 3886 self.assertEqual(matches, ((1, 2, 3), )) 3887 matches = mol.GetSubstructMatches(query, uniquify=True) 3888 self.assertEqual(len(matches), 1) 3889 self.assertEqual(matches, ((1, 2, 3), )) 3890 matches = mol.GetSubstructMatches(query, uniquify=False) 3891 self.assertEqual(len(matches), 1) 3892 self.assertEqual(matches, ((1, 2, 3), )) 3893 matches = resMolSuppl.GetSubstructMatches(query) 3894 self.assertEqual(len(matches), 2) 3895 self.assertEqual(matches, ((1, 2, 3), (1, 3, 2))) 3896 matches = resMolSuppl.GetSubstructMatches(query, uniquify=True) 3897 self.assertEqual(len(matches), 1) 3898 self.assertEqual(matches, ((1, 2, 3), )) 3899 matches = resMolSuppl.GetSubstructMatches(query, uniquify=False) 3900 self.assertEqual(len(matches), 2) 3901 self.assertEqual(matches, ((1, 2, 3), (1, 3, 2))) 3902 query = Chem.MolFromSmarts('C(~O)~O') 3903 matches = mol.GetSubstructMatches(query, uniquify=False) 3904 self.assertEqual(len(matches), 2) 3905 self.assertEqual(matches, ((1, 2, 3), (1, 3, 2))) 3906 matches = mol.GetSubstructMatches(query, uniquify=True) 3907 self.assertEqual(len(matches), 1) 3908 self.assertEqual(matches, ((1, 2, 3), )) 3909 matches = resMolSuppl.GetSubstructMatches(query, uniquify=False) 3910 self.assertEqual(len(matches), 2) 3911 self.assertEqual(matches, ((1, 2, 3), (1, 3, 2))) 3912 matches = resMolSuppl.GetSubstructMatches(query, uniquify=True) 3913 self.assertEqual(len(matches), 1) 3914 self.assertEqual(matches, ((1, 2, 3), )) 3915 3916 def testSubstructMatchDMAP(self): 3917 mol = Chem.MolFromSmiles('C(C)Nc1cc[nH+]cc1') 3918 query = Chem.MolFromSmarts('[#7+]') 3919 3920 resMolSuppl = Chem.ResonanceMolSupplier(mol) 3921 matches = mol.GetSubstructMatches(query, False, False, False) 3922 self.assertEqual(len(matches), 1) 3923 p = matches[0] 3924 self.assertEqual(p[0], 6) 3925 matches = resMolSuppl.GetSubstructMatches(query, False, False, False) 3926 self.assertEqual(len(matches), 2) 3927 v = [] 3928 p = matches[0] 3929 v.append(p[0]) 3930 p = matches[1] 3931 v.append(p[0]) 3932 v.sort() 3933 self.assertEqual(v[0], 2) 3934 self.assertEqual(v[1], 6) 3935 3936 def testCrambin(self): 3937 crambinPdb = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 3938 '1CRN.pdb') 3939 crambin = Chem.MolFromPDBFile(crambinPdb) 3940 res = [] 3941 # protonate NH2 3942 res.append(Chem.MolFromSmarts('[Nh2][Ch;Ch2]')) 3943 # protonate Arg 3944 res.append(Chem.MolFromSmarts('[Nh][C]([Nh2])=[Nh]')) 3945 setResidueFormalCharge(crambin, res, 1) 3946 res = [] 3947 # deprotonate COOH 3948 res.append(Chem.MolFromSmarts('C(=O)[Oh]')) 3949 setResidueFormalCharge(crambin, res, -1) 3950 res = [] 3951 resMolSupplST = Chem.ResonanceMolSupplier(crambin) 3952 # crambin has 2 Arg (3 resonance structures each); 1 Asp, 1 Glu 3953 # and 1 terminal COO- (2 resonance structures each) 3954 # so possible resonance structures are 3^2 * 2^3 = 72 3955 self.assertEqual(len(resMolSupplST), 72) 3956 self.assertEqual(resMolSupplST.GetNumConjGrps(), 56) 3957 carboxylateQuery = Chem.MolFromSmarts('C(=O)[O-]') 3958 guanidiniumQuery = Chem.MolFromSmarts('NC(=[NH2+])N') 3959 matches = crambin.GetSubstructMatches(carboxylateQuery) 3960 self.assertEqual(len(matches), 3) 3961 matches = crambin.GetSubstructMatches(carboxylateQuery, uniquify=False) 3962 self.assertEqual(len(matches), 3) 3963 matches = crambin.GetSubstructMatches(guanidiniumQuery) 3964 self.assertEqual(len(matches), 0) 3965 matches = crambin.GetSubstructMatches(guanidiniumQuery, uniquify=False) 3966 self.assertEqual(len(matches), 0) 3967 matches = resMolSupplST.GetSubstructMatches(carboxylateQuery) 3968 self.assertEqual(len(matches), 6) 3969 self.assertEqual(matches, ((166, 167, 168), (166, 168, 167), (298, 299, 300), (298, 300, 299), 3970 (320, 321, 326), (320, 326, 321))) 3971 matches = resMolSupplST.GetSubstructMatches(carboxylateQuery, uniquify=True) 3972 self.assertEqual(len(matches), 3) 3973 self.assertEqual(matches, ((166, 167, 168), (298, 299, 300), (320, 321, 326))) 3974 matches = resMolSupplST.GetSubstructMatches(guanidiniumQuery) 3975 self.assertEqual(len(matches), 8) 3976 self.assertEqual(matches, ((66, 67, 68, 69), (66, 67, 69, 68), (68, 67, 69, 66), 3977 (69, 67, 68, 66), (123, 124, 125, 126), (123, 124, 126, 125), 3978 (125, 124, 126, 123), (126, 124, 125, 123))) 3979 matches = resMolSupplST.GetSubstructMatches(guanidiniumQuery, uniquify=True) 3980 self.assertEqual(len(matches), 2) 3981 self.assertEqual(matches, ((66, 67, 69, 68), (123, 124, 126, 125))) 3982 btList2ST = getBtList2(resMolSupplST) 3983 self.assertTrue(btList2ST) 3984 resMolSupplMT = Chem.ResonanceMolSupplier(crambin) 3985 resMolSupplMT.SetNumThreads(0) 3986 self.assertEqual(len(resMolSupplST), len(resMolSupplMT)) 3987 btList2MT = getBtList2(resMolSupplMT) 3988 self.assertTrue(btList2MT) 3989 self.assertEqual(len(btList2ST), len(btList2MT)) 3990 for i in range(len(btList2ST)): 3991 for j in range(len(btList2ST)): 3992 self.assertEqual(btList2ST[i][j], btList2MT[i][j]) 3993 for suppl in [resMolSupplST, resMolSupplMT]: 3994 matches = suppl.GetSubstructMatches(carboxylateQuery, numThreads=0) 3995 self.assertEqual(len(matches), 6) 3996 self.assertEqual(matches, ((166, 167, 168), (166, 168, 167), (298, 299, 300), (298, 300, 299), 3997 (320, 321, 326), (320, 326, 321))) 3998 matches = suppl.GetSubstructMatches(carboxylateQuery, uniquify=True, numThreads=0) 3999 self.assertEqual(len(matches), 3) 4000 self.assertEqual(matches, ((166, 167, 168), (298, 299, 300), (320, 321, 326))) 4001 matches = suppl.GetSubstructMatches(guanidiniumQuery, numThreads=0) 4002 self.assertEqual(len(matches), 8) 4003 self.assertEqual(matches, ((66, 67, 68, 69), (66, 67, 69, 68), (68, 67, 69, 66), 4004 (69, 67, 68, 66), (123, 124, 125, 126), (123, 124, 126, 125), 4005 (125, 124, 126, 123), (126, 124, 125, 123))) 4006 matches = suppl.GetSubstructMatches(guanidiniumQuery, uniquify=True, numThreads=0) 4007 self.assertEqual(len(matches), 2) 4008 self.assertEqual(matches, ((66, 67, 69, 68), (123, 124, 126, 125))) 4009 4010 def testGitHub1166(self): 4011 mol = Chem.MolFromSmiles('NC(=[NH2+])c1ccc(cc1)C(=O)[O-]') 4012 resMolSuppl = Chem.ResonanceMolSupplier(mol, Chem.KEKULE_ALL) 4013 self.assertEqual(len(resMolSuppl), 8) 4014 # check that formal charges on odd indices are in the same position 4015 # as on even indices 4016 for i in range(0, len(resMolSuppl), 2): 4017 self.assertEqual(resMolSuppl[i].GetNumAtoms(), resMolSuppl[i + 1].GetNumAtoms()) 4018 for atomIdx in range(resMolSuppl[i].GetNumAtoms()): 4019 self.assertEqual(resMolSuppl[i].GetAtomWithIdx(atomIdx).GetFormalCharge(), 4020 resMolSuppl[i + 1].GetAtomWithIdx(atomIdx).GetFormalCharge()) 4021 # check that bond orders are alternate on aromatic bonds between 4022 # structures on odd indices and structures on even indices 4023 self.assertEqual(resMolSuppl[i].GetNumBonds(), resMolSuppl[i + 1].GetNumBonds()) 4024 for bondIdx in range(resMolSuppl[i].GetNumBonds()): 4025 self.assertTrue( 4026 ((not resMolSuppl[i].GetBondWithIdx(bondIdx).GetIsAromatic()) and 4027 (not resMolSuppl[i + 1].GetBondWithIdx(bondIdx).GetIsAromatic()) and 4028 (resMolSuppl[i].GetBondWithIdx(bondIdx).GetBondType() 4029 == resMolSuppl[i + 1].GetBondWithIdx(bondIdx).GetBondType())) 4030 or (resMolSuppl[i].GetBondWithIdx(bondIdx).GetIsAromatic() 4031 and resMolSuppl[i + 1].GetBondWithIdx(bondIdx).GetIsAromatic() and (int( 4032 round(resMolSuppl[i].GetBondWithIdx(bondIdx).GetBondTypeAsDouble() + 4033 resMolSuppl[i + 1].GetBondWithIdx(bondIdx).GetBondTypeAsDouble())) == 3))) 4034 4035 def testConjGrpPerception(self): 4036 mol1 = Chem.MolFromMolBlock("""\ 4037 4038 RDKit 2D 4039 4040 14 15 0 0 0 0 0 0 0 0999 V2000 4041 3.7539 -1.2744 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4042 2.4317 -0.5660 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4043 1.1571 -1.3568 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4044 -0.1651 -0.6484 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4045 -1.4397 -1.4393 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4046 -1.3921 -2.9385 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 4047 -2.7619 -0.7309 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4048 -2.8095 0.7684 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4049 -4.1316 1.4768 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 4050 -1.5349 1.5592 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4051 -0.2127 0.8508 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4052 1.0619 1.6417 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 4053 2.3841 0.9333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4054 3.6587 1.7241 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4055 1 2 1 0 4056 2 3 4 0 4057 3 4 4 0 4058 4 5 4 0 4059 5 6 1 0 4060 5 7 4 0 4061 7 8 4 0 4062 8 9 1 0 4063 8 10 4 0 4064 10 11 4 0 4065 11 12 4 0 4066 12 13 4 0 4067 13 14 1 0 4068 13 2 4 0 4069 11 4 4 0 4070M END 4071$$$$ 4072""") 4073 mol2 = Chem.MolFromMolBlock("""\ 4074 4075 RDKit 2D 4076 4077 14 15 0 0 0 0 0 0 0 0999 V2000 4078 1.0619 -1.6417 0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0 4079 -0.2127 -0.8508 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4080 -1.5349 -1.5592 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4081 -2.8095 -0.7684 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4082 -2.7619 0.7309 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4083 -1.4397 1.4393 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4084 -0.1651 0.6484 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4085 1.1571 1.3568 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4086 2.4317 0.5660 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4087 3.7539 1.2744 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4088 2.3841 -0.9333 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4089 3.6587 -1.7241 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4090 -4.1316 -1.4768 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 4091 -1.3921 2.9385 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 4092 1 2 4 0 4093 3 4 4 0 4094 4 5 4 0 4095 5 6 4 0 4096 2 3 4 0 4097 2 7 4 0 4098 7 8 4 0 4099 8 9 4 0 4100 9 10 1 0 4101 9 11 4 0 4102 11 12 1 0 4103 11 1 4 0 4104 6 7 4 0 4105 4 13 1 0 4106 6 14 1 0 4107M END 4108$$$$ 4109""") 4110 resMolSuppl1 = Chem.ResonanceMolSupplier(mol1, Chem.KEKULE_ALL) 4111 self.assertEqual(len(resMolSuppl1), 3) 4112 resMolSuppl2 = Chem.ResonanceMolSupplier(mol2, Chem.KEKULE_ALL) 4113 self.assertEqual(len(resMolSuppl2), 3) 4114 4115 def testGitHub2597(self): 4116 4117 class MyBrokenCallBack(Chem.ResonanceMolSupplier): 4118 4119 def __call__(self): 4120 return True 4121 4122 class MyBrokenCallBack2(Chem.ResonanceMolSupplierCallback): 4123 pass 4124 4125 class ExceedNumStructures(Chem.ResonanceMolSupplierCallback): 4126 4127 def __init__(self, parent): 4128 super().__init__() 4129 self._parent = parent 4130 4131 def __call__(self): 4132 self._parent.assertEqual(self.GetNumConjGrps(), 1) 4133 return (self.GetNumStructures(0) < 12) 4134 4135 class ExceedNumDiverseStructures(Chem.ResonanceMolSupplierCallback): 4136 4137 def __init__(self, parent): 4138 super().__init__() 4139 self._parent = parent 4140 4141 def __call__(self): 4142 self._parent.assertEqual(self.GetNumConjGrps(), 1) 4143 return (self.GetNumDiverseStructures(0) < 8) 4144 4145 class ExceedTimeout(Chem.ResonanceMolSupplierCallback): 4146 4147 def __init__(self, parent): 4148 super().__init__() 4149 self.start_time = None 4150 self.timeout = timedelta(seconds=3) 4151 self._parent = parent 4152 4153 def __call__(self): 4154 if (self.start_time is None): 4155 self.start_time = datetime.now() 4156 return (datetime.now() - self.start_time < self.timeout) 4157 4158 mol = Chem.MolFromSmiles( 4159 "ClC1=NC(NC2=CC=CC3=C2C(=O)C2=CC=CC=C2C3=O)=NC(NC2=CC=CC3=C2C(=O)C2=CC=CC=C2C3=O)=N1") 4160 resMolSuppl = Chem.ResonanceMolSupplier(mol) 4161 self.assertEqual(len(resMolSuppl), 1) 4162 resMolSuppl = Chem.ResonanceMolSupplier(mol, Chem.KEKULE_ALL) 4163 4164 self.assertEqual(len(resMolSuppl), 32) 4165 resMolSuppl = Chem.ResonanceMolSupplier(mol, Chem.ALLOW_CHARGE_SEPARATION, 10) 4166 self.assertEqual(len(resMolSuppl), 10) 4167 self.assertFalse(resMolSuppl.WasCanceled()) 4168 resMolSuppl = Chem.ResonanceMolSupplier(mol, Chem.ALLOW_CHARGE_SEPARATION) 4169 callback = resMolSuppl.GetProgressCallback() 4170 self.assertIsNone(callback) 4171 resMolSuppl.SetProgressCallback(ExceedNumStructures(self)) 4172 callback = resMolSuppl.GetProgressCallback() 4173 self.assertTrue(isinstance(callback, ExceedNumStructures)) 4174 resMolSuppl.SetProgressCallback(None) 4175 callback = resMolSuppl.GetProgressCallback() 4176 self.assertIsNone(callback) 4177 resMolSuppl.SetProgressCallback(ExceedNumStructures(self)) 4178 self.assertEqual(len(resMolSuppl), 12) 4179 self.assertTrue(resMolSuppl.WasCanceled()) 4180 resMolSuppl = Chem.ResonanceMolSupplier(mol, Chem.ALLOW_CHARGE_SEPARATION) 4181 with self.assertRaises(TypeError): 4182 resMolSuppl.SetProgressCallback(MyBrokenCallBack()) 4183 with self.assertRaises(AttributeError): 4184 resMolSuppl.SetProgressCallback(MyBrokenCallBack2()) 4185 resMolSuppl.SetProgressCallback(ExceedNumDiverseStructures(self)) 4186 self.assertEqual(len(resMolSuppl), 9) 4187 self.assertTrue(resMolSuppl.WasCanceled()) 4188 resMolSuppl = Chem.ResonanceMolSupplier( 4189 mol, Chem.UNCONSTRAINED_CATIONS | Chem.UNCONSTRAINED_ANIONS | Chem.KEKULE_ALL) 4190 resMolSuppl.SetProgressCallback(ExceedTimeout(self)) 4191 resMolSuppl.Enumerate() 4192 print(len(resMolSuppl)) 4193 self.assertTrue(resMolSuppl.WasCanceled()) 4194 4195 def testAtomBondProps(self): 4196 m = Chem.MolFromSmiles('c1ccccc1') 4197 for atom in m.GetAtoms(): 4198 d = atom.GetPropsAsDict() 4199 self.assertEqual(set(d.keys()), set(['_CIPRank', '__computedProps'])) 4200 self.assertEqual(d['_CIPRank'], 0) 4201 self.assertEqual(list(d['__computedProps']), ['_CIPRank']) 4202 4203 for bond in m.GetBonds(): 4204 self.assertEqual(bond.GetPropsAsDict(), {}) 4205 4206 def testSDProps(self): 4207 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 4208 'NCI_aids_few.sdf') 4209 #fileN = "../FileParsers/test_data/NCI_aids_few.sdf" 4210 sddata = [ 4211 { 4212 '_MolFileInfo': 'BBtclserve11129916382D 0 0.00000 0.00000 48', 4213 'NSC': 48, 4214 'NCI_AIDS_Antiviral_Screen_IC50': '2.00E-04\tM\t=\t2.46E-05\t3', 4215 '_Name': 48, 4216 'CAS_RN': '15716-70-8', 4217 '_MolFileComments': '15716-70-8', 4218 'NCI_AIDS_Antiviral_Screen_EC50': '2.00E-04\tM\t>\t2.00E-04\t3', 4219 'NCI_AIDS_Antiviral_Screen_Conclusion': 'CI' 4220 }, 4221 { 4222 '_MolFileInfo': 'BBtclserve11129916382D 0 0.00000 0.00000 78', 4223 'NSC': 78, 4224 'NCI_AIDS_Antiviral_Screen_IC50': '2.00E-04\tM\t=\t9.80E-05\t3', 4225 '_Name': 78, 4226 'CAS_RN': '6290-84-2', 4227 '_MolFileComments': '6290-84-2', 4228 'NCI_AIDS_Antiviral_Screen_EC50': '2.00E-04\tM\t>\t2.00E-04\t3', 4229 'NCI_AIDS_Antiviral_Screen_Conclusion': 'CI' 4230 }, 4231 { 4232 '_MolFileInfo': 'BBtclserve11129916382D 0 0.00000 0.00000 128', 4233 'NSC': 128, 4234 'NCI_AIDS_Antiviral_Screen_IC50': '2.00E-04\tM\t=\t4.60E-05\t4', 4235 '_Name': 128, 4236 'CAS_RN': '5395-10-8', 4237 '_MolFileComments': '5395-10-8', 4238 'NCI_AIDS_Antiviral_Screen_EC50': '2.00E-04\tM\t>\t2.00E-04\t4', 4239 'NCI_AIDS_Antiviral_Screen_Conclusion': 'CI' 4240 }, 4241 { 4242 '_MolFileInfo': 'BBtclserve11129916382D 0 0.00000 0.00000 163', 4243 'NSC': 163, 4244 'NCI_AIDS_Antiviral_Screen_IC50': '6.75E-04\tM\t>\t6.75E-04\t2', 4245 '_Name': 163, 4246 'CAS_RN': '81-11-8', 4247 '_MolFileComments': '81-11-8', 4248 'NCI_AIDS_Antiviral_Screen_EC50': '6.75E-04\tM\t>\t6.75E-04\t2', 4249 'NCI_AIDS_Antiviral_Screen_Conclusion': 'CI' 4250 }, 4251 { 4252 '_MolFileInfo': 'BBtclserve11129916382D 0 0.00000 0.00000 164', 4253 'NSC': 164, 4254 'NCI_AIDS_Antiviral_Screen_IC50': '2.00E-04\tM\t>\t2.00E-04\t2', 4255 '_Name': 164, 4256 'CAS_RN': '5325-43-9', 4257 '_MolFileComments': '5325-43-9', 4258 'NCI_AIDS_Antiviral_Screen_EC50': '2.00E-04\tM\t>\t2.00E-04\t2', 4259 'NCI_AIDS_Antiviral_Screen_Conclusion': 'CI' 4260 }, 4261 { 4262 '_MolFileInfo': 'BBtclserve11129916382D 0 0.00000 0.00000 170', 4263 'NSC': 170, 4264 '_Name': 170, 4265 'CAS_RN': '999-99-9', 4266 '_MolFileComments': '999-99-9', 4267 'NCI_AIDS_Antiviral_Screen_EC50': '9.47E-04\tM\t>\t9.47E-04\t1', 4268 'NCI_AIDS_Antiviral_Screen_Conclusion': 'CI' 4269 }, 4270 { 4271 '_MolFileInfo': 'BBtclserve11129916382D 0 0.00000 0.00000 180', 4272 'NSC': 180, 4273 'NCI_AIDS_Antiviral_Screen_IC50': 4274 '6.46E-04\tM\t=\t5.80E-04\t2\n1.81E-03\tM\t=\t6.90E-04\t2', 4275 '_Name': 180, 4276 'CAS_RN': '69-72-7', 4277 '_MolFileComments': '69-72-7', 4278 'NCI_AIDS_Antiviral_Screen_EC50': 4279 '6.46E-04\tM\t>\t6.46E-04\t2\n1.81E-03\tM\t>\t1.81E-03\t2', 4280 'NCI_AIDS_Antiviral_Screen_Conclusion': 'CI' 4281 }, 4282 { 4283 '_MolFileInfo': 'BBtclserve11129916382D 0 0.00000 0.00000 186', 4284 'NSC': 186, 4285 'NCI_AIDS_Antiviral_Screen_IC50': '1.44E-04\tM\t=\t2.49E-05\t2', 4286 '_Name': 186, 4287 'CAS_RN': '518-75-2', 4288 '_MolFileComments': '518-75-2', 4289 'NCI_AIDS_Antiviral_Screen_EC50': '1.44E-04\tM\t>\t1.44E-04\t2', 4290 'NCI_AIDS_Antiviral_Screen_Conclusion': 'CI' 4291 }, 4292 { 4293 '_MolFileInfo': 'BBtclserve11129916382D 0 0.00000 0.00000 192', 4294 'NSC': 192, 4295 'NCI_AIDS_Antiviral_Screen_IC50': '2.00E-04\tM\t=\t3.38E-06\t2', 4296 '_Name': 192, 4297 'CAS_RN': '2217-55-2', 4298 '_MolFileComments': '2217-55-2', 4299 'NCI_AIDS_Antiviral_Screen_EC50': '2.00E-04\tM\t>\t2.00E-04\t2', 4300 'NCI_AIDS_Antiviral_Screen_Conclusion': 'CI' 4301 }, 4302 { 4303 '_MolFileInfo': 'BBtclserve11129916382D 0 0.00000 0.00000 203', 4304 'NSC': 203, 4305 '_Name': 203, 4306 'CAS_RN': '1155-00-6', 4307 '_MolFileComments': '1155-00-6', 4308 'NCI_AIDS_Antiviral_Screen_Conclusion': 'CI' 4309 }, 4310 { 4311 '_MolFileInfo': 'BBtclserve11129916382D 0 0.00000 0.00000 210', 4312 'NSC': 210, 4313 'NCI_AIDS_Antiviral_Screen_IC50': '1.33E-03\tM\t>\t1.33E-03\t2', 4314 '_Name': 210, 4315 'CAS_RN': '5325-75-7', 4316 '_MolFileComments': '5325-75-7', 4317 'NCI_AIDS_Antiviral_Screen_EC50': '1.33E-03\tM\t>\t1.33E-03\t2', 4318 'NCI_AIDS_Antiviral_Screen_Conclusion': 'CI' 4319 }, 4320 { 4321 '_MolFileInfo': 'BBtclserve11129916382D 0 0.00000 0.00000 211', 4322 'NSC': 211, 4323 'NCI_AIDS_Antiviral_Screen_IC50': 4324 '2.00E-04\tM\t>\t2.00E-04\t8\n2.00E-03\tM\t=\t1.12E-03\t2', 4325 '_Name': 211, 4326 'CAS_RN': '5325-76-8', 4327 '_MolFileComments': '5325-76-8', 4328 'NCI_AIDS_Antiviral_Screen_EC50': 4329 '2.00E-04\tM\t>\t7.42E-05\t8\n2.00E-03\tM\t=\t6.35E-05\t2', 4330 'NCI_AIDS_Antiviral_Screen_Conclusion': 'CM' 4331 }, 4332 { 4333 '_MolFileInfo': 'BBtclserve11129916382D 0 0.00000 0.00000 213', 4334 'NSC': 213, 4335 'NCI_AIDS_Antiviral_Screen_IC50': '2.00E-04\tM\t>\t2.00E-04\t4', 4336 '_Name': 213, 4337 'CAS_RN': '119-80-2', 4338 '_MolFileComments': '119-80-2', 4339 'NCI_AIDS_Antiviral_Screen_EC50': '2.00E-04\tM\t>\t2.00E-04\t4', 4340 'NCI_AIDS_Antiviral_Screen_Conclusion': 'CI' 4341 }, 4342 { 4343 '_MolFileInfo': 'BBtclserve11129916382D 0 0.00000 0.00000 220', 4344 'NSC': 220, 4345 'NCI_AIDS_Antiviral_Screen_IC50': '2.00E-04\tM\t>\t2.00E-04\t4', 4346 '_Name': 220, 4347 'CAS_RN': '5325-83-7', 4348 '_MolFileComments': '5325-83-7', 4349 'NCI_AIDS_Antiviral_Screen_EC50': '2.00E-04\tM\t>\t2.00E-04\t4', 4350 'NCI_AIDS_Antiviral_Screen_Conclusion': 'CI' 4351 }, 4352 { 4353 '_MolFileInfo': 'BBtclserve11129916382D 0 0.00000 0.00000 229', 4354 'NSC': 229, 4355 'NCI_AIDS_Antiviral_Screen_IC50': '2.00E-04\tM\t>\t2.00E-04\t2', 4356 '_Name': 229, 4357 'CAS_RN': '5325-88-2', 4358 '_MolFileComments': '5325-88-2', 4359 'NCI_AIDS_Antiviral_Screen_EC50': '2.00E-04\tM\t>\t2.00E-04\t2', 4360 'NCI_AIDS_Antiviral_Screen_Conclusion': 'CI' 4361 }, 4362 { 4363 '_MolFileInfo': 'BBtclserve11129916382D 0 0.00000 0.00000 256', 4364 'NSC': 256, 4365 'NCI_AIDS_Antiviral_Screen_IC50': '2.00E-04\tM\t>\t2.00E-04\t4', 4366 '_Name': 256, 4367 'CAS_RN': '5326-06-7', 4368 '_MolFileComments': '5326-06-7', 4369 'NCI_AIDS_Antiviral_Screen_EC50': '2.00E-04\tM\t>\t2.00E-04\t4', 4370 'NCI_AIDS_Antiviral_Screen_Conclusion': 'CI' 4371 }, 4372 ] 4373 sdSup = Chem.SDMolSupplier(fileN) 4374 for i, mol in enumerate(sdSup): 4375 self.assertEqual(mol.GetPropsAsDict(includePrivate=True), sddata[i]) 4376 4377 def testGetSetProps(self): 4378 m = Chem.MolFromSmiles("CC") 4379 errors = { 4380 "int": "key `foo` exists but does not result in an integer value", 4381 "double": "key `foo` exists but does not result in a double value", 4382 "bool": "key `foo` exists but does not result in a True or False value" 4383 } 4384 4385 for ob in [m, list(m.GetAtoms())[0], list(m.GetBonds())[0]]: 4386 ob.SetDoubleProp("foo", 2.0) 4387 with self.assertRaises(ValueError) as e: 4388 ob.GetBoolProp("foo") 4389 self.assertEqual(str(e.exception), errors["bool"]) 4390 4391 with self.assertRaises(ValueError) as e: 4392 ob.GetIntProp("foo") 4393 self.assertEqual(str(e.exception), errors["int"]) 4394 4395 ob.SetBoolProp("foo", True) 4396 with self.assertRaises(ValueError) as e: 4397 ob.GetDoubleProp("foo") 4398 self.assertEqual(str(e.exception), errors["double"]) 4399 4400 with self.assertRaises(ValueError) as e: 4401 ob.GetIntProp("foo") 4402 self.assertEqual(str(e.exception), errors["int"]) 4403 4404 def testInvariantException(self): 4405 m = Chem.MolFromSmiles("C") 4406 try: 4407 m.GetAtomWithIdx(3) 4408 except RuntimeError as e: 4409 import platform 4410 details = str(e) 4411 if platform.system() == 'Windows': 4412 details = details.replace('\\', '/') 4413 self.assertTrue("Code/GraphMol/ROMol.cpp".lower() in details.lower()) 4414 self.assertTrue("Failed Expression: 3 < 1" in details) 4415 self.assertTrue("RDKIT:" in details) 4416 self.assertTrue(__version__ in details) 4417 4418 # this test should probably always be last since it wraps 4419 # the logging stream 4420 def testLogging(self): 4421 from io import StringIO 4422 err = sys.stderr 4423 try: 4424 loggers = [("RDKit ERROR", "1", Chem.LogErrorMsg), ("RDKit WARNING", "2", Chem.LogWarningMsg)] 4425 for msg, v, log in loggers: 4426 sys.stderr = StringIO() 4427 log(v) 4428 self.assertEqual(sys.stderr.getvalue(), "") 4429 4430 Chem.WrapLogs() 4431 for msg, v, log in loggers: 4432 sys.stderr = StringIO() 4433 log(v) 4434 s = sys.stderr.getvalue() 4435 self.assertTrue(msg in s) 4436 finally: 4437 sys.stderr = err 4438 4439 def testGetSDText(self): 4440 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 4441 'NCI_aids_few.sdf') 4442 #fileN = "../FileParsers/test_data/NCI_aids_few.sdf" 4443 sdSup = Chem.SDMolSupplier(fileN) 4444 for m in sdSup: 4445 sdt = Chem.SDWriter.GetText(m) 4446 ts = Chem.SDMolSupplier() 4447 ts.SetData(sdt) 4448 nm = next(ts) 4449 self.assertEqual(Chem.MolToSmiles(m, True), Chem.MolToSmiles(nm, True)) 4450 for pn in m.GetPropNames(): 4451 self.assertTrue(nm.HasProp(pn)) 4452 self.assertEqual(m.GetProp(pn), nm.GetProp(pn)) 4453 4454 def testUnfoldedRDKFingerprint(self): 4455 from rdkit.Chem import AllChem 4456 4457 m = Chem.MolFromSmiles('c1ccccc1N') 4458 fp = AllChem.UnfoldedRDKFingerprintCountBased(m) 4459 fpDict = fp.GetNonzeroElements() 4460 self.assertEqual(len(fpDict.items()), 19) 4461 self.assertTrue(374073638 in fpDict) 4462 self.assertEqual(fpDict[374073638], 6) 4463 self.assertTrue(464351883 in fpDict) 4464 self.assertEqual(fpDict[464351883], 2) 4465 self.assertTrue(1949583554 in fpDict) 4466 self.assertEqual(fpDict[1949583554], 6) 4467 self.assertTrue(4105342207 in fpDict) 4468 self.assertEqual(fpDict[4105342207], 1) 4469 self.assertTrue(794080973 in fpDict) 4470 self.assertEqual(fpDict[794080973], 1) 4471 self.assertTrue(3826517238 in fpDict) 4472 self.assertEqual(fpDict[3826517238], 2) 4473 4474 m = Chem.MolFromSmiles('Cl') 4475 fp = AllChem.UnfoldedRDKFingerprintCountBased(m) 4476 fpDict = fp.GetNonzeroElements() 4477 self.assertEqual(len(fpDict.items()), 0) 4478 4479 m = Chem.MolFromSmiles('CCCO') 4480 aBits = {} 4481 fp = AllChem.UnfoldedRDKFingerprintCountBased(m, bitInfo=aBits) 4482 fpDict = fp.GetNonzeroElements() 4483 self.assertEqual(len(fpDict.items()), 5) 4484 self.assertTrue(1524090560 in fpDict) 4485 self.assertEqual(fpDict[1524090560], 1) 4486 self.assertTrue(1940446997 in fpDict) 4487 self.assertEqual(fpDict[1940446997], 1) 4488 self.assertTrue(3977409745 in fpDict) 4489 self.assertEqual(fpDict[3977409745], 1) 4490 self.assertTrue(4274652475 in fpDict) 4491 self.assertEqual(fpDict[4274652475], 1) 4492 self.assertTrue(4275705116 in fpDict) 4493 self.assertEqual(fpDict[4275705116], 2) 4494 4495 self.assertTrue(1524090560 in aBits) 4496 self.assertEqual(aBits[1524090560], [[1, 2]]) 4497 self.assertTrue(1940446997 in aBits) 4498 self.assertEqual(aBits[1940446997], [[0, 1]]) 4499 self.assertTrue(3977409745 in aBits) 4500 self.assertEqual(aBits[3977409745], [[0, 1, 2]]) 4501 self.assertTrue(4274652475 in aBits) 4502 self.assertEqual(aBits[4274652475], [[2]]) 4503 self.assertTrue(4275705116 in aBits) 4504 self.assertEqual(aBits[4275705116], [[0], [1]]) 4505 4506 def testRDKFingerprintBitInfo(self): 4507 4508 m = Chem.MolFromSmiles('CCCO') 4509 aBits = {} 4510 fp1 = Chem.RDKFingerprint(m, bitInfo=aBits) 4511 self.assertTrue(1183 in aBits) 4512 self.assertEqual(aBits[1183], [[1, 2]]) 4513 self.assertTrue(709 in aBits) 4514 self.assertEqual(aBits[709], [[0, 1]]) 4515 self.assertTrue(1118 in aBits) 4516 self.assertEqual(aBits[1118], [[0, 1, 2]]) 4517 self.assertTrue(562 in aBits) 4518 self.assertEqual(aBits[562], [[2]]) 4519 self.assertTrue(1772 in aBits) 4520 self.assertEqual(aBits[1772], [[0], [1]]) 4521 4522 def testSimpleAromaticity(self): 4523 m = Chem.MolFromSmiles('c1ccccc1') 4524 self.assertTrue(m.GetBondWithIdx(0).GetIsAromatic()) 4525 self.assertTrue(m.GetAtomWithIdx(0).GetIsAromatic()) 4526 Chem.Kekulize(m, True) 4527 self.assertFalse(m.GetBondWithIdx(0).GetIsAromatic()) 4528 self.assertFalse(m.GetAtomWithIdx(0).GetIsAromatic()) 4529 Chem.SetAromaticity(m, Chem.AROMATICITY_SIMPLE) 4530 self.assertTrue(m.GetBondWithIdx(0).GetIsAromatic()) 4531 self.assertTrue(m.GetAtomWithIdx(0).GetIsAromatic()) 4532 4533 m = Chem.MolFromSmiles('c1c[nH]cc1') 4534 self.assertTrue(m.GetBondWithIdx(0).GetIsAromatic()) 4535 self.assertTrue(m.GetAtomWithIdx(0).GetIsAromatic()) 4536 Chem.Kekulize(m, True) 4537 self.assertFalse(m.GetBondWithIdx(0).GetIsAromatic()) 4538 self.assertFalse(m.GetAtomWithIdx(0).GetIsAromatic()) 4539 Chem.SetAromaticity(m, Chem.AROMATICITY_SIMPLE) 4540 self.assertTrue(m.GetBondWithIdx(0).GetIsAromatic()) 4541 self.assertTrue(m.GetAtomWithIdx(0).GetIsAromatic()) 4542 4543 m = Chem.MolFromSmiles('c1cccoocc1') 4544 self.assertTrue(m.GetBondWithIdx(0).GetIsAromatic()) 4545 self.assertTrue(m.GetAtomWithIdx(0).GetIsAromatic()) 4546 Chem.Kekulize(m, True) 4547 self.assertFalse(m.GetBondWithIdx(0).GetIsAromatic()) 4548 self.assertFalse(m.GetAtomWithIdx(0).GetIsAromatic()) 4549 Chem.SetAromaticity(m, Chem.AROMATICITY_SIMPLE) 4550 self.assertFalse(m.GetBondWithIdx(0).GetIsAromatic()) 4551 self.assertFalse(m.GetAtomWithIdx(0).GetIsAromatic()) 4552 4553 m = Chem.MolFromSmiles('c1ooc1') 4554 self.assertTrue(m.GetBondWithIdx(0).GetIsAromatic()) 4555 self.assertTrue(m.GetAtomWithIdx(0).GetIsAromatic()) 4556 Chem.Kekulize(m, True) 4557 self.assertFalse(m.GetBondWithIdx(0).GetIsAromatic()) 4558 self.assertFalse(m.GetAtomWithIdx(0).GetIsAromatic()) 4559 Chem.SetAromaticity(m, Chem.AROMATICITY_SIMPLE) 4560 self.assertFalse(m.GetBondWithIdx(0).GetIsAromatic()) 4561 self.assertFalse(m.GetAtomWithIdx(0).GetIsAromatic()) 4562 4563 m = Chem.MolFromSmiles('C1=CC2=CC=CC=CC2=C1') 4564 self.assertTrue(m.GetBondWithIdx(0).GetIsAromatic()) 4565 self.assertTrue(m.GetAtomWithIdx(0).GetIsAromatic()) 4566 Chem.Kekulize(m, True) 4567 self.assertFalse(m.GetBondWithIdx(0).GetIsAromatic()) 4568 self.assertFalse(m.GetAtomWithIdx(0).GetIsAromatic()) 4569 Chem.SetAromaticity(m, Chem.AROMATICITY_SIMPLE) 4570 self.assertFalse(m.GetBondWithIdx(0).GetIsAromatic()) 4571 self.assertFalse(m.GetAtomWithIdx(0).GetIsAromatic()) 4572 4573 def testGithub955(self): 4574 m = Chem.MolFromSmiles("CCC") 4575 m.GetAtomWithIdx(0).SetProp("foo", "1") 4576 self.assertEqual(list(m.GetAtomWithIdx(0).GetPropNames()), ["foo"]) 4577 m.GetBondWithIdx(0).SetProp("foo", "1") 4578 self.assertEqual(list(m.GetBondWithIdx(0).GetPropNames()), ["foo"]) 4579 4580 def testMDLProps(self): 4581 m = Chem.MolFromSmiles("CCC") 4582 m.GetAtomWithIdx(0).SetAtomMapNum(1) 4583 Chem.SetAtomAlias(m.GetAtomWithIdx(1), "foo") 4584 Chem.SetAtomValue(m.GetAtomWithIdx(1), "bar") 4585 4586 m = Chem.MolFromMolBlock(Chem.MolToMolBlock(m)) 4587 self.assertEqual(m.GetAtomWithIdx(0).GetAtomMapNum(), 1) 4588 self.assertEqual(Chem.GetAtomAlias(m.GetAtomWithIdx(1)), "foo") 4589 self.assertEqual(Chem.GetAtomValue(m.GetAtomWithIdx(1)), "bar") 4590 4591 def testSmilesProps(self): 4592 m = Chem.MolFromSmiles("C") 4593 Chem.SetSupplementalSmilesLabel(m.GetAtomWithIdx(0), 'xxx') 4594 self.assertEqual(Chem.MolToSmiles(m), "Cxxx") 4595 4596 def testGithub1051(self): 4597 # just need to test that this exists: 4598 self.assertTrue(Chem.BondDir.EITHERDOUBLE) 4599 4600 def testGithub1041(self): 4601 a = Chem.Atom(6) 4602 self.assertRaises(RuntimeError, lambda: a.GetOwningMol()) 4603 self.assertRaises(RuntimeError, lambda: a.GetNeighbors()) 4604 self.assertRaises(RuntimeError, lambda: a.GetBonds()) 4605 self.assertRaises(RuntimeError, lambda: a.IsInRing()) 4606 self.assertRaises(RuntimeError, lambda: a.IsInRingSize(4)) 4607 4608 def testSmilesParseParams(self): 4609 smi = "CCC |$foo;;bar$| ourname" 4610 m = Chem.MolFromSmiles(smi) 4611 self.assertTrue(m is not None) 4612 ps = Chem.SmilesParserParams() 4613 ps.allowCXSMILES = False 4614 m = Chem.MolFromSmiles(smi, ps) 4615 self.assertTrue(m is None) 4616 ps.allowCXSMILES = True 4617 ps.parseName = True 4618 m = Chem.MolFromSmiles(smi, ps) 4619 self.assertTrue(m is not None) 4620 self.assertTrue(m.GetAtomWithIdx(0).HasProp('atomLabel')) 4621 self.assertEqual(m.GetAtomWithIdx(0).GetProp('atomLabel'), "foo") 4622 self.assertTrue(m.HasProp('_Name')) 4623 self.assertEqual(m.GetProp('_Name'), "ourname") 4624 self.assertEqual(m.GetProp("_CXSMILES_Data"), "|$foo;;bar$|") 4625 4626 def testWriteCXSmiles(self): 4627 smi = "CCC |$foo;;bar$|" 4628 ps = Chem.SmilesParserParams() 4629 ps.allowCXSMILES = True 4630 m = Chem.MolFromSmiles(smi, ps) 4631 self.assertTrue(m is not None) 4632 self.assertTrue(m.GetAtomWithIdx(0).HasProp('atomLabel')) 4633 self.assertEqual(m.GetAtomWithIdx(0).GetProp('atomLabel'), "foo") 4634 self.assertEqual(Chem.MolToCXSmiles(m), 'CCC |$foo;;bar$|') 4635 4636 smi = "Cl.CCC |$;foo;;bar$|" 4637 m = Chem.MolFromSmiles(smi, ps) 4638 self.assertTrue(m is not None) 4639 self.assertTrue(m.GetAtomWithIdx(1).HasProp('atomLabel')) 4640 self.assertEqual(m.GetAtomWithIdx(1).GetProp('atomLabel'), "foo") 4641 self.assertEqual(Chem.MolFragmentToCXSmiles(m, atomsToUse=(1, 2, 3)), 'CCC |$foo;;bar$|') 4642 4643 def testPickleProps(self): 4644 import pickle 4645 m = Chem.MolFromSmiles('C1=CN=CC=C1') 4646 m.SetProp("_Name", "Name") 4647 for atom in m.GetAtoms(): 4648 atom.SetProp("_foo", "bar" + str(atom.GetIdx())) 4649 atom.SetProp("foo", "baz" + str(atom.GetIdx())) 4650 4651 Chem.SetDefaultPickleProperties(Chem.PropertyPickleOptions.AllProps) 4652 pkl = pickle.dumps(m) 4653 m2 = pickle.loads(pkl) 4654 smi1 = Chem.MolToSmiles(m) 4655 smi2 = Chem.MolToSmiles(m2) 4656 self.assertTrue(smi1 == smi2) 4657 self.assertEqual(m2.GetProp("_Name"), "Name") 4658 for atom in m2.GetAtoms(): 4659 self.assertEqual(atom.GetProp("_foo"), "bar" + str(atom.GetIdx())) 4660 self.assertEqual(atom.GetProp("foo"), "baz" + str(atom.GetIdx())) 4661 4662 Chem.SetDefaultPickleProperties(Chem.PropertyPickleOptions.AtomProps) 4663 pkl = pickle.dumps(m) 4664 m2 = pickle.loads(pkl) 4665 smi1 = Chem.MolToSmiles(m) 4666 smi2 = Chem.MolToSmiles(m2) 4667 self.assertTrue(smi1 == smi2) 4668 self.assertFalse(m2.HasProp("_Name")) 4669 for atom in m2.GetAtoms(): 4670 self.assertFalse(atom.HasProp("_foo")) 4671 self.assertEqual(atom.GetProp("foo"), "baz" + str(atom.GetIdx())) 4672 4673 Chem.SetDefaultPickleProperties(Chem.PropertyPickleOptions.NoProps) 4674 pkl = pickle.dumps(m) 4675 m2 = pickle.loads(pkl) 4676 smi1 = Chem.MolToSmiles(m) 4677 smi2 = Chem.MolToSmiles(m2) 4678 self.assertTrue(smi1 == smi2) 4679 self.assertFalse(m2.HasProp("_Name")) 4680 for atom in m2.GetAtoms(): 4681 self.assertFalse(atom.HasProp("_foo")) 4682 self.assertFalse(atom.HasProp("foo")) 4683 4684 Chem.SetDefaultPickleProperties(Chem.PropertyPickleOptions.MolProps 4685 | Chem.PropertyPickleOptions.PrivateProps) 4686 pkl = pickle.dumps(m) 4687 m2 = pickle.loads(pkl) 4688 smi1 = Chem.MolToSmiles(m) 4689 smi2 = Chem.MolToSmiles(m2) 4690 self.assertTrue(smi1 == smi2) 4691 self.assertEqual(m2.GetProp("_Name"), "Name") 4692 for atom in m2.GetAtoms(): 4693 self.assertFalse(atom.HasProp("_foo")) 4694 self.assertFalse(atom.HasProp("foo")) 4695 4696 def testGithub1352(self): 4697 self.assertTrue('SP' in Chem.HybridizationType.names) 4698 self.assertTrue('S' in Chem.HybridizationType.names) 4699 m = Chem.MolFromSmiles('CC(=O)O.[Na]') 4700 self.assertEqual(m.GetAtomWithIdx(0).GetHybridization().name, 'SP3') 4701 self.assertEqual(m.GetAtomWithIdx(4).GetHybridization().name, 'S') 4702 4703 def testGithub1366(self): 4704 mol = Chem.MolFromSmiles('*C*') 4705 mol = Chem.RWMol(mol) 4706 ats = iter(mol.GetAtoms()) 4707 atom = next(ats) 4708 mol.RemoveAtom(atom.GetIdx()) 4709 self.assertRaises(RuntimeError, next, ats) 4710 4711 mol = Chem.MolFromSmiles('*C*') 4712 mol = Chem.RWMol(mol) 4713 bonds = iter(mol.GetBonds()) 4714 bond = next(bonds) 4715 mol.RemoveBond(bond.GetBeginAtomIdx(), bond.GetEndAtomIdx()) 4716 self.assertRaises(RuntimeError, next, bonds) 4717 4718 def testGithub1478(self): 4719 data = """ 4720 MJ150720 4721 4722 8 8 0 0 0 0 0 0 0 0999 V2000 4723 -0.4242 -1.4883 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 4724 0.2901 -1.0758 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4725 1.0046 0.9865 0.0000 A 0 0 0 0 0 0 0 0 0 0 0 0 4726 1.0046 0.1614 0.0000 A 0 0 0 0 0 0 0 0 0 0 0 0 4727 0.2901 -0.2508 0.0000 A 0 0 0 0 0 0 0 0 0 0 0 0 4728 -0.4243 0.1614 0.0000 A 0 0 0 0 0 0 0 0 0 0 0 0 4729 -0.4243 0.9865 0.0000 A 0 0 0 0 0 0 0 0 0 0 0 0 4730 0.2901 1.3990 0.0000 A 0 0 0 0 0 0 0 0 0 0 0 0 4731 7 6 4 0 0 0 0 4732 8 7 4 0 0 0 0 4733 6 5 4 0 0 0 0 4734 5 4 4 0 0 0 0 4735 5 2 1 0 0 0 0 4736 4 3 4 0 0 0 0 4737 8 3 4 0 0 0 0 4738 2 1 2 0 0 0 0 4739M END 4740""" 4741 pattern = Chem.MolFromMolBlock(data) 4742 m = Chem.MolFromSmiles("c1ccccc1C=O") 4743 self.assertTrue(m.HasSubstructMatch(pattern)) 4744 4745 def testGithub1320(self): 4746 import pickle 4747 mol = Chem.MolFromSmiles('N[C@@H](C)O') 4748 mol2 = pickle.loads(pickle.dumps(mol)) 4749 self.assertEqual(Chem.MolToSmiles(mol, isomericSmiles=True), 4750 Chem.MolToSmiles(mol2, isomericSmiles=True)) 4751 Chem.SetDefaultPickleProperties(Chem.PropertyPickleOptions.AtomProps 4752 | Chem.PropertyPickleOptions.BondProps 4753 | Chem.PropertyPickleOptions.MolProps 4754 | Chem.PropertyPickleOptions.PrivateProps 4755 | Chem.PropertyPickleOptions.ComputedProps) 4756 mol3 = pickle.loads(pickle.dumps(mol)) 4757 4758 for a1, a2 in zip(mol.GetAtoms(), mol3.GetAtoms()): 4759 d1 = a1.GetPropsAsDict() 4760 d2 = a2.GetPropsAsDict() 4761 if "__computedProps" in d1: 4762 c1 = list(d1["__computedProps"]) 4763 c2 = list(d2["__computedProps"]) 4764 del d1["__computedProps"] 4765 del d2["__computedProps"] 4766 self.assertEqual(c1, c2) 4767 4768 assert d1 == d2 4769 4770 for a1, a2 in zip(mol.GetBonds(), mol3.GetBonds()): 4771 d1 = a1.GetPropsAsDict() 4772 d2 = a2.GetPropsAsDict() 4773 if "__computedProps" in d1: 4774 c1 = list(d1["__computedProps"]) 4775 c2 = list(d2["__computedProps"]) 4776 del d1["__computedProps"] 4777 del d2["__computedProps"] 4778 self.assertEqual(c1, c2) 4779 4780 assert d1 == d2 4781 4782 self.assertEqual(Chem.MolToSmiles(mol, isomericSmiles=True), 4783 Chem.MolToSmiles(mol3, isomericSmiles=True)) 4784 4785 def testOldPropPickles(self): 4786 data = 'crdkit.Chem.rdchem\nMol\np0\n(S\'\\xef\\xbe\\xad\\xde\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00)\\x00\\x00\\x00-\\x00\\x00\\x00\\x80\\x01\\x06\\x00`\\x00\\x00\\x00\\x01\\x03\\x07\\x00`\\x00\\x00\\x00\\x02\\x01\\x06 4\\x00\\x00\\x00\\x01\\x01\\x04\\x06\\x00`\\x00\\x00\\x00\\x01\\x03\\x06\\x00(\\x00\\x00\\x00\\x03\\x04\\x08\\x00(\\x00\\x00\\x00\\x03\\x02\\x07\\x00h\\x00\\x00\\x00\\x03\\x02\\x01\\x06 4\\x00\\x00\\x00\\x02\\x01\\x04\\x06\\x00(\\x00\\x00\\x00\\x03\\x04\\x08\\x00(\\x00\\x00\\x00\\x03\\x02\\x07\\x00(\\x00\\x00\\x00\\x03\\x03\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06 4\\x00\\x00\\x00\\x01\\x01\\x04\\x08\\x00(\\x00\\x00\\x00\\x03\\x02\\x06@(\\x00\\x00\\x00\\x03\\x04\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06 4\\x00\\x00\\x00\\x01\\x01\\x04\\x06\\x00(\\x00\\x00\\x00\\x03\\x04\\x08\\x00(\\x00\\x00\\x00\\x03\\x02\\x07\\x00h\\x00\\x00\\x00\\x03\\x02\\x01\\x06 4\\x00\\x00\\x00\\x02\\x01\\x04\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06@(\\x00\\x00\\x00\\x03\\x04\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@h\\x00\\x00\\x00\\x03\\x03\\x01\\x06@(\\x00\\x00\\x00\\x03\\x04\\x06\\x00`\\x00\\x00\\x00\\x03\\x01\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x06\\x00`\\x00\\x00\\x00\\x02\\x02\\x0b\\x00\\x01\\x00\\x01\\x02\\x00\\x02\\x03\\x00\\x02\\x04\\x00\\x04\\x05(\\x02\\x04\\x06 \\x06\\x07\\x00\\x07\\x08\\x00\\x08\\t(\\x02\\x08\\n \\n\\x0b\\x00\\x0b\\x0c\\x00\\x0c\\r\\x00\\r\\x0e \\x0e\\x0fh\\x0c\\x0f\\x10h\\x0c\\x10\\x11h\\x0c\\x11\\x12h\\x0c\\x12\\x13h\\x0c\\x0c\\x14\\x00\\x14\\x15\\x00\\x15\\x16\\x00\\x16\\x17(\\x02\\x16\\x18 \\x18\\x19\\x00\\x19\\x1a\\x00\\x1a\\x1b\\x00\\x1b\\x1c\\x00\\x1c\\x1d\\x00\\x1d\\x1eh\\x0c\\x1e\\x1fh\\x0c\\x1f h\\x0c !h\\x0c!"h\\x0c\\x07#\\x00#$\\x00$%\\x00%&\\x00&\\\'\\x00\\\'(\\x00\\x15\\n\\x00"\\x19\\x00(#\\x00\\x13\\x0eh\\x0c"\\x1dh\\x0c\\x14\\x05\\x05\\x0b\\n\\x15\\x14\\x0c\\x06\\x0f\\x10\\x11\\x12\\x13\\x0e\\x06\\x1a\\x1b\\x1c\\x1d"\\x19\\x06\\x1e\\x1f !"\\x1d\\x06$%&\\\'(#\\x17\\x00\\x00\\x00\\x00\\x12\\x03\\x00\\x00\\x00\\x07\\x00\\x00\\x00numArom\\x01\\x02\\x00\\x00\\x00\\x0f\\x00\\x00\\x00_StereochemDone\\x01\\x01\\x00\\x00\\x00\\x03\\x00\\x00\\x00foo\\x00\\x03\\x00\\x00\\x00bar\\x13:\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x12\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x000\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x1d\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x001\\x04\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x15\\x00\\x00\\x00\\x12\\x00\\x00\\x00_ChiralityPossible\\x01\\x01\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPCode\\x00\\x01\\x00\\x00\\x00S\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x002\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x003\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x1a\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x004\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02"\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x005\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x1f\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x006\\x04\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x16\\x00\\x00\\x00\\x12\\x00\\x00\\x00_ChiralityPossible\\x01\\x01\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPCode\\x00\\x01\\x00\\x00\\x00S\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x007\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x1c\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x008\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02$\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x01\\x00\\x00\\x009\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02 \\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0010\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x13\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0011\\x04\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x18\\x00\\x00\\x00\\x12\\x00\\x00\\x00_ChiralityPossible\\x01\\x01\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPCode\\x00\\x01\\x00\\x00\\x00S\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0012\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02!\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0013\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x19\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0014\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x0f\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0015\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x0b\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0016\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x08\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0017\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x0b\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0018\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x0f\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0019\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x07\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0020\\x04\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x17\\x00\\x00\\x00\\x12\\x00\\x00\\x00_ChiralityPossible\\x01\\x01\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPCode\\x00\\x01\\x00\\x00\\x00S\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0021\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x1b\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0022\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02#\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0023\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x1e\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0024\\x04\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x14\\x00\\x00\\x00\\x12\\x00\\x00\\x00_ChiralityPossible\\x01\\x01\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPCode\\x00\\x01\\x00\\x00\\x00R\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0025\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x06\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0026\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x03\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0027\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x05\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0028\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x10\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0029\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x0c\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0030\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\t\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0031\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\n\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0032\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\r\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0033\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x11\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0034\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x0e\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0035\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x04\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0036\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x02\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0037\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x01\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0038\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x02\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0039\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00_CIPRank\\x02\\x04\\x00\\x00\\x00\\x05\\x00\\x00\\x00myidx\\x00\\x02\\x00\\x00\\x0040\\x13\\x16\'\np1\ntp2\nRp3\n.' 4787 import pickle 4788 # bonds were broken in v1 4789 m2 = pickle.loads(data.encode("utf-8"), encoding='bytes') 4790 4791 self.assertEqual(m2.GetProp("foo"), "bar") 4792 for atom in m2.GetAtoms(): 4793 self.assertEqual(atom.GetProp("myidx"), str(atom.GetIdx())) 4794 4795 self.assertEqual( 4796 Chem.MolToSmiles(m2, True), 4797 Chem.MolToSmiles( 4798 Chem.MolFromSmiles( 4799 "CN[C@@H](C)C(=O)N[C@H](C(=O)N1C[C@@H](Oc2ccccc2)C[C@H]1C(=O)N[C@@H]1CCCc2ccccc21)C1CCCCC1" 4800 ), True)) 4801 4802 def testGithub1461(self): 4803 # this is simple, it should throw a precondition and not seg fault 4804 m = Chem.RWMol() 4805 try: 4806 m.AddBond(0, 1, Chem.BondType.SINGLE) 4807 self.assertFalse(True) # shouldn't get here 4808 except RuntimeError: 4809 pass 4810 4811 def testMolBundles1(self): 4812 b = Chem.MolBundle() 4813 smis = ('CC(Cl)(F)CC(F)(Br)', 'C[C@](Cl)(F)C[C@H](F)(Br)', 'C[C@](Cl)(F)C[C@@H](F)(Br)') 4814 for smi in smis: 4815 b.AddMol(Chem.MolFromSmiles(smi)) 4816 self.assertEqual(len(b), 3) 4817 self.assertEqual(b.Size(), 3) 4818 self.assertRaises(IndexError, lambda: b[4]) 4819 self.assertEqual(Chem.MolToSmiles(b[1], isomericSmiles=True), 4820 Chem.MolToSmiles(Chem.MolFromSmiles(smis[1]), isomericSmiles=True)) 4821 self.assertTrue(b.HasSubstructMatch(Chem.MolFromSmiles('CC(Cl)(F)CC(F)(Br)'), 4822 useChirality=True)) 4823 self.assertTrue( 4824 b.HasSubstructMatch(Chem.MolFromSmiles('C[C@](Cl)(F)C[C@@H](F)(Br)'), useChirality=True)) 4825 self.assertTrue( 4826 b.HasSubstructMatch(Chem.MolFromSmiles('C[C@@](Cl)(F)C[C@@H](F)(Br)'), useChirality=False)) 4827 self.assertFalse( 4828 b.HasSubstructMatch(Chem.MolFromSmiles('C[C@@](Cl)(F)C[C@@H](F)(Br)'), useChirality=True)) 4829 4830 self.assertEqual( 4831 len(b.GetSubstructMatch(Chem.MolFromSmiles('CC(Cl)(F)CC(F)(Br)'), useChirality=True)), 8) 4832 self.assertEqual( 4833 len(b.GetSubstructMatch(Chem.MolFromSmiles('C[C@](Cl)(F)C[C@@H](F)(Br)'), useChirality=True)), 4834 8) 4835 self.assertEqual( 4836 len(b.GetSubstructMatch(Chem.MolFromSmiles('C[C@@](Cl)(F)C[C@@H](F)(Br)'), 4837 useChirality=False)), 8) 4838 self.assertEqual( 4839 len(b.GetSubstructMatch(Chem.MolFromSmiles('C[C@@](Cl)(F)C[C@@H](F)(Br)'), 4840 useChirality=True)), 0) 4841 4842 self.assertEqual( 4843 len(b.GetSubstructMatches(Chem.MolFromSmiles('CC(Cl)(F)CC(F)(Br)'), useChirality=True)), 1) 4844 self.assertEqual( 4845 len(b.GetSubstructMatches(Chem.MolFromSmiles('C[C@](Cl)(F)C[C@@H](F)(Br)'), 4846 useChirality=True)), 1) 4847 self.assertEqual( 4848 len( 4849 b.GetSubstructMatches(Chem.MolFromSmiles('C[C@@](Cl)(F)C[C@@H](F)(Br)'), 4850 useChirality=False)), 1) 4851 self.assertEqual( 4852 len( 4853 b.GetSubstructMatches(Chem.MolFromSmiles('C[C@@](Cl)(F)C[C@@H](F)(Br)'), 4854 useChirality=True)), 0) 4855 self.assertEqual( 4856 len(b.GetSubstructMatches(Chem.MolFromSmiles('CC(Cl)(F)CC(F)(Br)'), useChirality=True)[0]), 8) 4857 self.assertEqual( 4858 len( 4859 b.GetSubstructMatches(Chem.MolFromSmiles('C[C@](Cl)(F)C[C@@H](F)(Br)'), 4860 useChirality=True)[0]), 8) 4861 self.assertEqual( 4862 len( 4863 b.GetSubstructMatches(Chem.MolFromSmiles('C[C@@](Cl)(F)C[C@@H](F)(Br)'), 4864 useChirality=False)[0]), 8) 4865 4866 def testMolBundles2(self): 4867 b = Chem.MolBundle() 4868 smis = ('Fc1c(Cl)cccc1', 'Fc1cc(Cl)ccc1', 'Fc1ccc(Cl)cc1') 4869 for smi in smis: 4870 b.AddMol(Chem.MolFromSmiles(smi)) 4871 self.assertEqual(len(b), 3) 4872 self.assertEqual(b.Size(), 3) 4873 self.assertTrue(Chem.MolFromSmiles('Fc1c(Cl)cccc1').HasSubstructMatch(b)) 4874 self.assertTrue(Chem.MolFromSmiles('Fc1cc(Cl)ccc1').HasSubstructMatch(b)) 4875 self.assertTrue(Chem.MolFromSmiles('Fc1c(Cl)cccc1C').HasSubstructMatch(b)) 4876 self.assertTrue(Chem.MolFromSmiles('Fc1cc(Cl)ccc1C').HasSubstructMatch(b)) 4877 self.assertFalse(Chem.MolFromSmiles('Fc1c(Br)cccc1').HasSubstructMatch(b)) 4878 4879 self.assertEqual(len(Chem.MolFromSmiles('Fc1c(Cl)cccc1').GetSubstructMatch(b)), 8) 4880 self.assertEqual(len(Chem.MolFromSmiles('Fc1c(Cl)cccc1').GetSubstructMatches(b)), 1) 4881 self.assertEqual(len(Chem.MolFromSmiles('Fc1c(Cl)cccc1').GetSubstructMatches(b)[0]), 8) 4882 self.assertEqual(len(Chem.MolFromSmiles('Fc1ccc(Cl)cc1').GetSubstructMatches(b)), 1) 4883 self.assertEqual( 4884 len(Chem.MolFromSmiles('Fc1ccc(Cl)cc1').GetSubstructMatches(b, uniquify=False)), 2) 4885 4886 self.assertEqual(len(Chem.MolFromSmiles('Fc1c(C)cccc1').GetSubstructMatch(b)), 0) 4887 self.assertEqual(len(Chem.MolFromSmiles('Fc1c(C)cccc1').GetSubstructMatches(b)), 0) 4888 4889 def testMolBundles3(self): 4890 smis = ('CCC', 'CCO', 'CCN') 4891 b = Chem.FixedMolSizeMolBundle() 4892 for smi in smis: 4893 b.AddMol(Chem.MolFromSmiles(smi)) 4894 self.assertEqual(len(b), 3) 4895 self.assertEqual(b.Size(), 3) 4896 with self.assertRaises(ValueError): 4897 b.AddMol(Chem.MolFromSmiles('CCCC')) 4898 4899 b = Chem.MolBundle() 4900 for smi in smis: 4901 b.AddMol(Chem.MolFromSmiles(smi)) 4902 self.assertEqual(len(b), 3) 4903 self.assertEqual(b.Size(), 3) 4904 b.AddMol(Chem.MolFromSmiles('CCCC')) 4905 self.assertEqual(b.Size(), 4) 4906 4907 def testGithub1622(self): 4908 nonaromatics = ( 4909 "C1=C[N]C=C1", # radicals are not two electron donors 4910 "O=C1C=CNC=C1", # exocyclic double bonds don't steal electrons 4911 "C1=CS(=O)C=C1", # not sure how to classify this example from the 4912 # OEChem docs 4913 "C1#CC=CC=C1" # benzyne 4914 # 5-membered heterocycles 4915 "C1=COC=C1", # furan 4916 "C1=CSC=C1", # thiophene 4917 "C1=CNC=C1", #pyrrole 4918 "C1=COC=N1", # oxazole 4919 "C1=CSC=N1", # thiazole 4920 "C1=CNC=N1", # imidazole 4921 "C1=CNN=C1", # pyrazole 4922 "C1=CON=C1", # isoxazole 4923 "C1=CSN=C1", # isothiazole 4924 "C1=CON=N1", # 1,2,3-oxadiazole 4925 "C1=CNN=N1", # 1,2,3-triazole 4926 "N1=CSC=N1", # 1,3,4-thiadiazole 4927 # not outside the second rows 4928 "C1=CC=C[Si]=C1", 4929 "C1=CC=CC=P1", 4930 # 5-membered heterocycles outside the second row 4931 "C1=C[Se]C=C1", 4932 'C1=C[Te]C=C1') 4933 for smi in nonaromatics: 4934 m = Chem.MolFromSmiles(smi, sanitize=False) 4935 Chem.SanitizeMol(m, Chem.SANITIZE_ALL ^ Chem.SANITIZE_SETAROMATICITY) 4936 Chem.SetAromaticity(m, Chem.AROMATICITY_MDL) 4937 self.assertFalse(m.GetAtomWithIdx(0).GetIsAromatic()) 4938 aromatics = ( 4939 "C1=CC=CC=C1", # benzene, of course 4940 # hetrocyclics 4941 "N1=CC=CC=C1", # pyridine 4942 "N1=CC=CC=N1", # pyridazine 4943 "N1=CC=CN=C1", # pyrimidine 4944 "N1=CC=NC=C1", # pyrazine 4945 "N1=CN=CN=C1", # 1,3,5-triazine 4946 # polycyclic aromatics 4947 "C1=CC2=CC=CC=CC2=C1", # azulene 4948 "C1=CC=CC2=CC=CC=C12", 4949 "C1=CC2=CC=CC=CC=C12", 4950 "C1=CC=C2C(=C1)N=CC=N2", 4951 "C1=CN=CC2C=CC=CC1=2", 4952 "C1=CC=C2C(=C1)N=C3C=CC=CC3=N2", 4953 "C1=CN=NC2C=CC=CC1=2", 4954 # macrocycle aromatics 4955 "C1=CC=CC=CC=CC=C1", 4956 "C1=CC=CC=CC=CC=CC=CC=CC=CC=C1", 4957 "N1=CN=NC=CC=CC=CC=CC=CC=CC=CC=CC=CC=CC=CC=CC=C1") 4958 for smi in aromatics: 4959 m = Chem.MolFromSmiles(smi, sanitize=False) 4960 Chem.SanitizeMol(m, Chem.SANITIZE_ALL ^ Chem.SANITIZE_SETAROMATICITY) 4961 Chem.SetAromaticity(m, Chem.AROMATICITY_MDL) 4962 self.assertTrue(m.GetAtomWithIdx(0).GetIsAromatic()) 4963 4964 def testMolBlockChirality(self): 4965 m = Chem.MolFromSmiles('C[C@H](Cl)Br') 4966 mb = Chem.MolToMolBlock(m) 4967 m2 = Chem.MolFromMolBlock(mb) 4968 csmi1 = Chem.MolToSmiles(m, isomericSmiles=True) 4969 csmi2 = Chem.MolToSmiles(m2, isomericSmiles=True) 4970 self.assertEqual(csmi1, csmi2) 4971 4972 def testIssue1735(self): 4973 # this shouldn't seg fault... 4974 m = Chem.RWMol() 4975 ranks = Chem.CanonicalRankAtoms(m, breakTies=False) 4976 ranks = Chem.CanonicalRankAtoms(m, breakTies=True) 4977 4978 def testGithub1615(self): 4979 mb = """Issue399a.mol 4980 ChemDraw04050615582D 4981 4982 4 4 0 0 0 0 0 0 0 0999 V2000 4983 -0.7697 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4984 0.0553 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4985 0.7697 0.4125 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 4986 0.7697 -0.4125 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 4987 2 1 1 0 4988 2 3 1 0 4989 3 4 1 0 4990 2 4 1 0 4991M END""" 4992 m = Chem.MolFromMolBlock(mb) 4993 self.assertFalse(m.GetAtomWithIdx(1).HasProp("_CIPCode")) 4994 self.assertEqual(m.GetBondWithIdx(0).GetBondDir(), Chem.BondDir.NONE) 4995 self.assertEqual(m.GetAtomWithIdx(1).GetChiralTag(), Chem.ChiralType.CHI_UNSPECIFIED) 4996 m.GetAtomWithIdx(1).SetChiralTag(Chem.ChiralType.CHI_TETRAHEDRAL_CW) 4997 Chem.AssignStereochemistry(m, force=True) 4998 self.assertTrue(m.GetAtomWithIdx(1).HasProp("_CIPCode")) 4999 self.assertEqual(m.GetAtomWithIdx(1).GetProp("_CIPCode"), "S") 5000 self.assertEqual(m.GetBondWithIdx(0).GetBondDir(), Chem.BondDir.NONE) 5001 Chem.WedgeBond(m.GetBondWithIdx(0), 1, m.GetConformer()) 5002 self.assertEqual(m.GetBondWithIdx(0).GetBondDir(), Chem.BondDir.BEGINWEDGE) 5003 5004 def testSmilesToAtom(self): 5005 a = Chem.AtomFromSmiles("C") 5006 self.assertEqual(a.GetAtomicNum(), 6) 5007 b = Chem.BondFromSmiles("=") 5008 self.assertEqual(b.GetBondType(), Chem.BondType.DOUBLE) 5009 a = Chem.AtomFromSmiles("error") 5010 self.assertIs(a, None) 5011 b = Chem.BondFromSmiles("d") 5012 self.assertIs(b, None) 5013 5014 a = Chem.AtomFromSmarts("C") 5015 self.assertEqual(a.GetAtomicNum(), 6) 5016 b = Chem.BondFromSmarts("=") 5017 self.assertEqual(b.GetBondType(), Chem.BondType.DOUBLE) 5018 a = Chem.AtomFromSmarts("error") 5019 self.assertIs(a, None) 5020 b = Chem.BondFromSmarts("d") 5021 self.assertIs(b, None) 5022 5023 def testSVGParsing(self): 5024 svg = """<?xml version='1.0' encoding='iso-8859-1'?> 5025<svg version='1.1' baseProfile='full' 5026 xmlns='http://www.w3.org/2000/svg' 5027 xmlns:rdkit='http://www.rdkit.org/xml' 5028 xmlns:xlink='http://www.w3.org/1999/xlink' 5029 xml:space='preserve' 5030width='200px' height='200px' > 5031<rect style='opacity:1.0;fill:#FFFFFF;stroke:none' width='200' height='200' x='0' y='0'> </rect> 5032<path d='M 9.09091,89.4974 24.2916,84.7462' style='fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5033<path d='M 24.2916,84.7462 39.4923,79.9949' style='fill:none;fill-rule:evenodd;stroke:#0000FF;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5034<path d='M 86.2908,106.814 75.1709,93.4683 72.0765,96.8285 86.2908,106.814' style='fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5035<path d='M 75.1709,93.4683 57.8622,86.8431 64.051,80.1229 75.1709,93.4683' style='fill:#0000FF;fill-rule:evenodd;stroke:#0000FF;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5036<path d='M 75.1709,93.4683 72.0765,96.8285 57.8622,86.8431 75.1709,93.4683' style='fill:#0000FF;fill-rule:evenodd;stroke:#0000FF;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5037<path d='M 86.2908,106.814 82.1459,125.293' style='fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5038<path d='M 82.1459,125.293 78.0009,143.772' style='fill:none;fill-rule:evenodd;stroke:#00CC00;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5039<path d='M 86.2908,106.814 129.89,93.1862' style='fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5040<path d='M 134.347,94.186 138.492,75.7069' style='fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5041<path d='M 138.492,75.7069 142.637,57.2277' style='fill:none;fill-rule:evenodd;stroke:#FF0000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5042<path d='M 125.432,92.1865 129.577,73.7074' style='fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5043<path d='M 129.577,73.7074 133.722,55.2282' style='fill:none;fill-rule:evenodd;stroke:#FF0000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5044<path d='M 129.89,93.1862 142.557,104.852' style='fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5045<path d='M 142.557,104.852 155.224,116.517' style='fill:none;fill-rule:evenodd;stroke:#FF0000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5046<text x='39.4923' y='83.483' style='font-size:15px;font-style:normal;font-weight:normal;fill-opacity:1;stroke:none;font-family:sans-serif;text-anchor:start;fill:#0000FF' ><tspan>NH</tspan></text> 5047<text x='67.6656' y='158.998' style='font-size:15px;font-style:normal;font-weight:normal;fill-opacity:1;stroke:none;font-family:sans-serif;text-anchor:start;fill:#00CC00' ><tspan>Cl</tspan></text> 5048<text x='132.777' y='56.228' style='font-size:15px;font-style:normal;font-weight:normal;fill-opacity:1;stroke:none;font-family:sans-serif;text-anchor:start;fill:#FF0000' ><tspan>O</tspan></text> 5049<text x='149.782' y='131.743' style='font-size:15px;font-style:normal;font-weight:normal;fill-opacity:1;stroke:none;font-family:sans-serif;text-anchor:start;fill:#FF0000' ><tspan>OH</tspan></text> 5050<text x='89.9952' y='194' style='font-size:12px;font-style:normal;font-weight:normal;fill-opacity:1;stroke:none;font-family:sans-serif;text-anchor:start;fill:#000000' ><tspan>m1</tspan></text> 5051<metadata> 5052<rdkit:mol xmlns:rdkit = "http://www.rdkit.org/xml" version="0.9"> 5053<rdkit:atom idx="1" atom-smiles="[CH3]" drawing-x="9.09091" drawing-y="89.4974" x="-2.78651" y="0.295614" z="0" /> 5054<rdkit:atom idx="2" atom-smiles="[NH]" drawing-x="52.6897" drawing-y="75.8699" x="-1.35482" y="0.743114" z="0" /> 5055<rdkit:atom idx="3" atom-smiles="[C@H]" drawing-x="86.2908" drawing-y="106.814" x="-0.251428" y="-0.273019" z="0" /> 5056<rdkit:atom idx="4" atom-smiles="[Cl]" drawing-x="76.2932" drawing-y="151.385" x="-0.579728" y="-1.73665" z="0" /> 5057<rdkit:atom idx="5" atom-smiles="[C]" drawing-x="129.89" drawing-y="93.1862" x="1.18027" y="0.174481" z="0" /> 5058<rdkit:atom idx="6" atom-smiles="[O]" drawing-x="139.887" drawing-y="48.6148" x="1.50857" y="1.63811" z="0" /> 5059<rdkit:atom idx="7" atom-smiles="[OH]" drawing-x="163.491" drawing-y="124.13" x="2.28366" y="-0.841652" z="0" /> 5060<rdkit:bond idx="1" begin-atom-idx="1" end-atom-idx="2" bond-smiles="-" /> 5061<rdkit:bond idx="2" begin-atom-idx="2" end-atom-idx="3" bond-smiles="-" /> 5062<rdkit:bond idx="3" begin-atom-idx="3" end-atom-idx="4" bond-smiles="-" /> 5063<rdkit:bond idx="4" begin-atom-idx="3" end-atom-idx="5" bond-smiles="-" /> 5064<rdkit:bond idx="5" begin-atom-idx="5" end-atom-idx="6" bond-smiles="=" /> 5065<rdkit:bond idx="6" begin-atom-idx="5" end-atom-idx="7" bond-smiles="-" /> 5066</rdkit:mol></metadata> 5067</svg>""" 5068 mol = Chem.MolFromRDKitSVG(svg) 5069 self.assertEqual(mol.GetNumAtoms(), 7) 5070 self.assertEqual(Chem.MolToSmiles(mol), 'CN[C@H](Cl)C(=O)O') 5071 5072 svg2 = """<?xml version='1.0' encoding='iso-8859-1'?> 5073<svg version='1.1' baseProfile='full' 5074 xmlns='http://www.w3.org/2000/svg' 5075 xmlns:rdkit='http://www.rdkit.org/xml' 5076 xmlns:xlink='http://www.w3.org/1999/xlink' 5077 xml:space='preserve' 5078width='200px' height='200px' > 5079<rect style='opacity:1.0;fill:#FFFFFF;stroke:none' width='200' height='200' x='0' y='0'> </rect> 5080<path d='M 9.09091,89.4974 24.2916,84.7462' style='fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5081<path d='M 24.2916,84.7462 39.4923,79.9949' style='fill:none;fill-rule:evenodd;stroke:#0000FF;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5082<path d='M 86.2908,106.814 75.1709,93.4683 72.0765,96.8285 86.2908,106.814' style='fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5083<path d='M 75.1709,93.4683 57.8622,86.8431 64.051,80.1229 75.1709,93.4683' style='fill:#0000FF;fill-rule:evenodd;stroke:#0000FF;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5084<path d='M 75.1709,93.4683 72.0765,96.8285 57.8622,86.8431 75.1709,93.4683' style='fill:#0000FF;fill-rule:evenodd;stroke:#0000FF;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5085<path d='M 86.2908,106.814 82.1459,125.293' style='fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5086<path d='M 82.1459,125.293 78.0009,143.772' style='fill:none;fill-rule:evenodd;stroke:#00CC00;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5087<path d='M 86.2908,106.814 129.89,93.1862' style='fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5088<path d='M 134.347,94.186 138.492,75.7069' style='fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5089<path d='M 138.492,75.7069 142.637,57.2277' style='fill:none;fill-rule:evenodd;stroke:#FF0000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5090<path d='M 125.432,92.1865 129.577,73.7074' style='fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5091<path d='M 129.577,73.7074 133.722,55.2282' style='fill:none;fill-rule:evenodd;stroke:#FF0000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5092<path d='M 129.89,93.1862 142.557,104.852' style='fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5093<path d='M 142.557,104.852 155.224,116.517' style='fill:none;fill-rule:evenodd;stroke:#FF0000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' /> 5094<text x='39.4923' y='83.483' style='font-size:15px;font-style:normal;font-weight:normal;fill-opacity:1;stroke:none;font-family:sans-serif;text-anchor:start;fill:#0000FF' ><tspan>NH</tspan></text> 5095<text x='67.6656' y='158.998' style='font-size:15px;font-style:normal;font-weight:normal;fill-opacity:1;stroke:none;font-family:sans-serif;text-anchor:start;fill:#00CC00' ><tspan>Cl</tspan></text> 5096<text x='132.777' y='56.228' style='font-size:15px;font-style:normal;font-weight:normal;fill-opacity:1;stroke:none;font-family:sans-serif;text-anchor:start;fill:#FF0000' ><tspan>O</tspan></text> 5097<text x='149.782' y='131.743' style='font-size:15px;font-style:normal;font-weight:normal;fill-opacity:1;stroke:none;font-family:sans-serif;text-anchor:start;fill:#FF0000' ><tspan>OH</tspan></text> 5098<text x='89.9952' y='194' style='font-size:12px;font-style:normal;font-weight:normal;fill-opacity:1;stroke:none;font-family:sans-serif;text-anchor:start;fill:#000000' ><tspan>m1</tspan></text> 5099</svg>""" 5100 mol = Chem.MolFromRDKitSVG(svg2) 5101 self.assertTrue(mol is None) 5102 5103 with self.assertRaises(RuntimeError): 5104 mol = Chem.MolFromRDKitSVG("bad svg") 5105 5106 def testAssignChiralTypesFromBondDirs(self): 5107 """ 5108 Just check to see that AssignChiralTypesFromBondDirs is wrapped. 5109 Critical tests of the underlying C++ function already exist 5110 in SD file reader tests. 5111 """ 5112 mol = Chem.MolFromSmiles('C(F)(Cl)Br') 5113 rdkit.Chem.rdDepictor.Compute2DCoords(mol) 5114 atom0 = mol.GetAtomWithIdx(0) 5115 self.assertEqual(atom0.GetChiralTag(), Chem.rdchem.ChiralType.CHI_UNSPECIFIED) 5116 bond = mol.GetBondBetweenAtoms(0, 1) 5117 bond.SetBondDir(Chem.rdchem.BondDir.BEGINWEDGE) 5118 Chem.AssignChiralTypesFromBondDirs(mol) 5119 self.assertEqual(atom0.GetChiralTag(), Chem.rdchem.ChiralType.CHI_TETRAHEDRAL_CCW) 5120 5121 def testAssignStereochemistryFrom3D(self): 5122 5123 def _stereoTester(mol, expectedCIP, expectedStereo): 5124 mol.UpdatePropertyCache() 5125 self.assertEqual(mol.GetNumAtoms(), 9) 5126 self.assertFalse(mol.GetAtomWithIdx(1).HasProp("_CIPCode")) 5127 self.assertEqual(mol.GetBondWithIdx(3).GetStereo(), Chem.BondStereo.STEREONONE) 5128 for bond in mol.GetBonds(): 5129 bond.SetBondDir(Chem.BondDir.NONE) 5130 Chem.AssignStereochemistryFrom3D(mol) 5131 self.assertTrue(mol.GetAtomWithIdx(1).HasProp("_CIPCode")) 5132 self.assertEqual(mol.GetAtomWithIdx(1).GetProp("_CIPCode"), expectedCIP) 5133 self.assertEqual(mol.GetBondWithIdx(3).GetStereo(), expectedStereo) 5134 5135 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'test_data', 'stereochem.sdf') 5136 suppl = Chem.SDMolSupplier(fileN, sanitize=False) 5137 expected = ( 5138 ("R", Chem.BondStereo.STEREOZ), 5139 ("R", Chem.BondStereo.STEREOE), 5140 ("S", Chem.BondStereo.STEREOZ), 5141 ("S", Chem.BondStereo.STEREOE), 5142 ) 5143 for i, mol in enumerate(suppl): 5144 cip, stereo = expected[i] 5145 _stereoTester(mol, cip, stereo) 5146 5147 def testGitHub2082(self): 5148 ctab = """ 5149 MJ150720 5150 5151 9 9 0 0 0 0 0 0 0 0999 V2000 5152 2.5687 -0.7144 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5153 2.1562 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5154 2.5687 0.7144 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 5155 1.3312 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5156 0.9187 -0.7144 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5157 0.0937 -0.7144 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5158 -0.3187 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5159 0.0937 0.7144 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5160 0.9187 0.7144 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5161 2 1 1 6 5162 2 3 1 0 5163 2 4 1 0 5164 4 5 2 0 5165 5 6 1 0 5166 6 7 2 0 5167 7 8 1 0 5168 8 9 2 0 5169 9 4 1 0 5170M END 5171""" 5172 mol = Chem.MolFromMolBlock(ctab) 5173 self.assertFalse(mol.GetConformer().Is3D()) 5174 self.assertTrue("@" in Chem.MolToSmiles(mol, True)) 5175 5176 def testGitHub2082_2(self): 5177 # test a mol block that lies is 3D but labelled 2D 5178 ofile = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'Wrap', 'test_data', 5179 'issue2082.mol') 5180 with open(ofile) as inf: 5181 ctab = inf.read() 5182 m = Chem.MolFromMolBlock(ctab) 5183 self.assertTrue(m.GetConformer().Is3D()) 5184 5185 def testSetQuery(self): 5186 from rdkit.Chem import rdqueries 5187 pat = Chem.MolFromSmarts("[C]") 5188 self.assertFalse(Chem.MolFromSmiles("c1ccccc1").HasSubstructMatch(pat)) 5189 5190 q = rdqueries.AtomNumEqualsQueryAtom(6) 5191 for atom in pat.GetAtoms(): 5192 atom.SetQuery(q) 5193 5194 self.assertTrue(Chem.MolFromSmiles("c1ccccc1").HasSubstructMatch(pat)) 5195 5196 def testBondSetQuery(self): 5197 pat = Chem.MolFromSmarts('[#6]=[#6]') 5198 mol = Chem.MolFromSmiles("c1ccccc1") 5199 self.assertFalse(mol.HasSubstructMatch(pat)) 5200 pat2 = Chem.MolFromSmarts('C:C') 5201 for bond in pat.GetBonds(): 5202 bond.SetQuery(pat2.GetBondWithIdx(0)) 5203 self.assertTrue(mol.HasSubstructMatch(pat)) 5204 5205 def testBondExpandQuery(self): 5206 pat = Chem.MolFromSmarts('C-C') 5207 mol = Chem.MolFromSmiles("C=C-C") 5208 self.assertEqual(len(mol.GetSubstructMatches(pat)), 1) 5209 pat2 = Chem.MolFromSmarts('C=C') 5210 for bond in pat.GetBonds(): 5211 bond.ExpandQuery(pat2.GetBondWithIdx(0), Chem.CompositeQueryType.COMPOSITE_OR) 5212 self.assertEqual(len(mol.GetSubstructMatches(pat)), 2) 5213 5214 def testGitHub1985(self): 5215 # simple check, this used to throw an exception 5216 try: 5217 Chem.MolToSmarts(Chem.MolFromSmarts("[C@]")) 5218 except: 5219 self.fail("[C@] caused an exception when roundtripping smarts") 5220 5221 def testGetEnhancedStereo(self): 5222 5223 rdbase = os.environ['RDBASE'] 5224 filename = os.path.join(rdbase, 'Code/GraphMol/FileParsers/test_data/two_centers_or.mol') 5225 m = Chem.MolFromMolFile(filename) 5226 5227 sg = m.GetStereoGroups() 5228 self.assertEqual(len(sg), 2) 5229 group1 = sg[1] 5230 self.assertEqual(group1.GetGroupType(), Chem.StereoGroupType.STEREO_OR) 5231 stereo_atoms = group1.GetAtoms() 5232 self.assertEqual(len(stereo_atoms), 2) 5233 # file is 1 indexed and says 5 5234 self.assertEqual(stereo_atoms[1].GetIdx(), 4) 5235 5236 # make sure the atoms are connected to the parent molecule 5237 stereo_atoms[1].SetProp("foo", "bar") 5238 self.assertTrue(m.GetAtomWithIdx(4).HasProp("foo")) 5239 5240 # make sure that we can iterate over the atoms: 5241 for at in stereo_atoms: 5242 at.SetProp("foo2", "bar2") 5243 self.assertTrue(m.GetAtomWithIdx(at.GetIdx()).HasProp("foo2")) 5244 5245 def testEnhancedStereoPreservesMol(self): 5246 """ 5247 Check that the stereo group (and the atoms therein) preserve the lifetime 5248 of the associated mol. 5249 """ 5250 rdbase = os.environ['RDBASE'] 5251 filename = os.path.join(rdbase, 'Code/GraphMol/FileParsers/test_data/two_centers_or.mol') 5252 m = Chem.MolFromMolFile(filename) 5253 5254 sg = m.GetStereoGroups() 5255 m = None 5256 gc.collect() 5257 self.assertEqual(len(sg), 2) 5258 group1 = sg[1] 5259 stereo_atoms = group1.GetAtoms() 5260 sg = None 5261 gc.collect() 5262 self.assertEqual(stereo_atoms[1].GetIdx(), 4) 5263 self.assertEqual(stereo_atoms[1].GetOwningMol().GetNumAtoms(), 8) 5264 5265 def testSetEnhancedStereoGroup(self): 5266 m = Chem.MolFromSmiles('F[C@@H](Br)[C@H](F)Cl |o1:1|') 5267 m2 = Chem.RWMol(m) 5268 5269 groups = m2.GetStereoGroups() 5270 self.assertEqual(len(groups), 1) 5271 # Can clear the StereoGroups by setting to an empty list 5272 m2.SetStereoGroups([]) 5273 self.assertEqual(len(m2.GetStereoGroups()), 0) 5274 5275 # Can add new StereoGroups 5276 group1 = Chem.rdchem.CreateStereoGroup(Chem.rdchem.StereoGroupType.STEREO_OR, m2, [1]) 5277 m2.SetStereoGroups([group1]) 5278 self.assertEqual(len(m2.GetStereoGroups()), 1) 5279 5280 def testSetEnhancedStereoGroupOwnershipCheck(self): 5281 # make sure that the object returned by CreateStereoGroup() 5282 # preserves the owning molecule: 5283 m = Chem.RWMol(Chem.MolFromSmiles('F[C@@H](Br)[C@H](F)Cl')) 5284 group1 = Chem.rdchem.CreateStereoGroup(Chem.rdchem.StereoGroupType.STEREO_OR, m, [1]) 5285 m.SetStereoGroups([group1]) 5286 self.assertEqual(len(m.GetStereoGroups()), 1) 5287 5288 m = None 5289 gc.collect() 5290 stereo_atoms = group1.GetAtoms() 5291 self.assertEqual(stereo_atoms[0].GetIdx(), 1) 5292 return 5293 self.assertEqual(stereo_atoms[0].GetOwningMol().GetNumAtoms(), 6) 5294 5295 # make sure we can't add StereoGroups constructed from one molecule 5296 # to a different one: 5297 m2 = Chem.RWMol(Chem.MolFromSmiles('F[C@@H](Br)[C@H](F)Cl')) 5298 with self.assertRaises(ValueError): 5299 m2.SetStereoGroups([group1]) 5300 5301 def testSetEnhancedStereoTypeChecking(self): 5302 m = Chem.RWMol(Chem.MolFromSmiles('F[C@@H](Br)[C@H](F)Cl')) 5303 5304 # List or tuple should be allowed: 5305 group = Chem.rdchem.CreateStereoGroup(Chem.rdchem.StereoGroupType.STEREO_OR, m, [1, 3]) 5306 group = Chem.rdchem.CreateStereoGroup(Chem.rdchem.StereoGroupType.STEREO_OR, m, (1, 3)) 5307 5308 # Python ValueError (range error) with index past the end 5309 with self.assertRaises(ValueError): 5310 group = Chem.rdchem.CreateStereoGroup(Chem.rdchem.StereoGroupType.STEREO_OR, m, [100]) 5311 5312 # Mol is None 5313 with self.assertRaises(TypeError): 5314 group = Chem.rdchem.CreateStereoGroup(Chem.rdchem.StereoGroupType.STEREO_OR, None, [1]) 5315 5316 # Atom indices must be numbers 5317 with self.assertRaises(TypeError): 5318 group = Chem.rdchem.CreateStereoGroup(Chem.rdchem.StereoGroupType.STEREO_OR, m, [1, 'text']) 5319 5320 def testSubstructParameters(self): 5321 m = Chem.MolFromSmiles('C[C@](F)(Cl)OCC') 5322 p1 = Chem.MolFromSmiles('C[C@](F)(Cl)O') 5323 p2 = Chem.MolFromSmiles('C[C@@](F)(Cl)O') 5324 p3 = Chem.MolFromSmiles('CC(F)(Cl)O') 5325 5326 ps = Chem.SubstructMatchParameters() 5327 self.assertTrue(m.HasSubstructMatch(p1, ps)) 5328 self.assertTrue(m.HasSubstructMatch(p2, ps)) 5329 self.assertTrue(m.HasSubstructMatch(p3, ps)) 5330 self.assertEqual(m.GetSubstructMatch(p1, ps), (0, 1, 2, 3, 4)) 5331 self.assertEqual(m.GetSubstructMatch(p2, ps), (0, 1, 2, 3, 4)) 5332 self.assertEqual(m.GetSubstructMatch(p3, ps), (0, 1, 2, 3, 4)) 5333 self.assertEqual(m.GetSubstructMatches(p1, ps), ((0, 1, 2, 3, 4), )) 5334 self.assertEqual(m.GetSubstructMatches(p2, ps), ((0, 1, 2, 3, 4), )) 5335 self.assertEqual(m.GetSubstructMatches(p3, ps), ((0, 1, 2, 3, 4), )) 5336 ps.useChirality = True 5337 self.assertTrue(m.HasSubstructMatch(p1, ps)) 5338 self.assertFalse(m.HasSubstructMatch(p2, ps)) 5339 self.assertTrue(m.HasSubstructMatch(p3, ps)) 5340 self.assertEqual(m.GetSubstructMatch(p1, ps), (0, 1, 2, 3, 4)) 5341 self.assertEqual(m.GetSubstructMatch(p2, ps), ()) 5342 self.assertEqual(m.GetSubstructMatch(p3, ps), (0, 1, 2, 3, 4)) 5343 self.assertEqual(m.GetSubstructMatches(p1, ps), ((0, 1, 2, 3, 4), )) 5344 self.assertEqual(m.GetSubstructMatches(p2, ps), ()) 5345 self.assertEqual(m.GetSubstructMatches(p3, ps), ((0, 1, 2, 3, 4), )) 5346 5347 def testSubstructParametersBundles(self): 5348 b = Chem.MolBundle() 5349 smis = ('C[C@](F)(Cl)O', 'C[C@](Br)(Cl)O', 'C[C@](I)(Cl)O') 5350 for smi in smis: 5351 b.AddMol(Chem.MolFromSmiles(smi)) 5352 self.assertEqual(len(b), 3) 5353 self.assertEqual(b.Size(), 3) 5354 ps = Chem.SubstructMatchParameters() 5355 ps.useChirality = True 5356 self.assertTrue(Chem.MolFromSmiles('C[C@](F)(Cl)OCC').HasSubstructMatch(b, ps)) 5357 self.assertFalse(Chem.MolFromSmiles('C[C@@](F)(Cl)OCC').HasSubstructMatch(b, ps)) 5358 self.assertTrue(Chem.MolFromSmiles('C[C@](I)(Cl)OCC').HasSubstructMatch(b, ps)) 5359 self.assertFalse(Chem.MolFromSmiles('C[C@@](I)(Cl)OCC').HasSubstructMatch(b, ps)) 5360 5361 self.assertEqual( 5362 Chem.MolFromSmiles('C[C@](F)(Cl)OCC').GetSubstructMatch(b, ps), (0, 1, 2, 3, 4)) 5363 self.assertEqual(Chem.MolFromSmiles('C[C@@](F)(Cl)OCC').GetSubstructMatch(b, ps), ()) 5364 self.assertEqual( 5365 Chem.MolFromSmiles('C[C@](I)(Cl)OCC').GetSubstructMatch(b, ps), (0, 1, 2, 3, 4)) 5366 self.assertEqual(Chem.MolFromSmiles('C[C@@](I)(Cl)OCC').GetSubstructMatch(b, ps), ()) 5367 5368 self.assertEqual( 5369 Chem.MolFromSmiles('C[C@](F)(Cl)OCC').GetSubstructMatches(b, ps), ((0, 1, 2, 3, 4), )) 5370 self.assertEqual(Chem.MolFromSmiles('C[C@@](F)(Cl)OCC').GetSubstructMatches(b, ps), ()) 5371 self.assertEqual( 5372 Chem.MolFromSmiles('C[C@](I)(Cl)OCC').GetSubstructMatches(b, ps), ((0, 1, 2, 3, 4), )) 5373 self.assertEqual(Chem.MolFromSmiles('C[C@@](I)(Cl)OCC').GetSubstructMatches(b, ps), ()) 5374 5375 def testSubstructParametersBundles2(self): 5376 b = Chem.MolBundle() 5377 smis = ('C[C@](F)(Cl)O', 'C[C@](Br)(Cl)O', 'C[C@](I)(Cl)O') 5378 for smi in smis: 5379 b.AddMol(Chem.MolFromSmiles(smi)) 5380 self.assertEqual(len(b), 3) 5381 b2 = Chem.MolBundle() 5382 smis = ('C[C@@](F)(Cl)O', 'C[C@@](Br)(Cl)O', 'C[C@@](I)(Cl)O') 5383 for smi in smis: 5384 b2.AddMol(Chem.MolFromSmiles(smi)) 5385 self.assertEqual(len(b2), 3) 5386 ps = Chem.SubstructMatchParameters() 5387 ps.useChirality = True 5388 self.assertTrue(b.HasSubstructMatch(b, ps)) 5389 self.assertFalse(b.HasSubstructMatch(b2, ps)) 5390 self.assertFalse(b2.HasSubstructMatch(b, ps)) 5391 5392 self.assertEqual(b.GetSubstructMatch(b, ps), (0, 1, 2, 3, 4)) 5393 self.assertEqual(b.GetSubstructMatch(b2, ps), ()) 5394 self.assertEqual(b2.GetSubstructMatch(b, ps), ()) 5395 5396 self.assertEqual(b.GetSubstructMatches(b, ps), ((0, 1, 2, 3, 4), )) 5397 self.assertEqual(b.GetSubstructMatches(b2, ps), ()) 5398 self.assertEqual(b2.GetSubstructMatches(b, ps), ()) 5399 5400 def testGithub2285(self): 5401 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 5402 'github2285.sdf') 5403 5404 supp = Chem.ForwardSDMolSupplier(fileN, removeHs=False) 5405 if hasattr(supp, "__next__"): 5406 self.assertTrue(supp.__next__() is not None) 5407 else: 5408 self.assertTrue(supp.next() is not None) 5409 5410 def testBitVectProp(self): 5411 bv = DataStructs.ExplicitBitVect(100) 5412 m = Chem.MolFromSmiles("CC") 5413 for atom in m.GetAtoms(): 5414 bv.SetBit(atom.GetIdx()) 5415 atom.SetExplicitBitVectProp("prop", bv) 5416 5417 for atom in m.GetAtoms(): 5418 bv = atom.GetExplicitBitVectProp("prop") 5419 self.assertTrue(bv.GetBit(atom.GetIdx())) 5420 5421 def testBitVectQuery(self): 5422 bv = DataStructs.ExplicitBitVect(4) 5423 bv.SetBit(0) 5424 bv.SetBit(2) 5425 5426 # wow, what a mouthfull.. 5427 qa = rdqueries.HasBitVectPropWithValueQueryAtom("prop", bv, tolerance=0.0) 5428 5429 m = Chem.MolFromSmiles("CC") 5430 for atom in m.GetAtoms(): 5431 if atom.GetIdx() == 0: 5432 atom.SetExplicitBitVectProp("prop", bv) 5433 5434 l = tuple([x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)]) 5435 self.assertEqual(l, (0, )) 5436 5437 m = Chem.MolFromSmiles("CC") 5438 for atom in m.GetAtoms(): 5439 bv = DataStructs.ExplicitBitVect(4) 5440 bv.SetBit(atom.GetIdx()) 5441 atom.SetExplicitBitVectProp("prop", bv) 5442 5443 sma = Chem.MolFromSmarts("C") 5444 for atom in sma.GetAtoms(): 5445 bv = DataStructs.ExplicitBitVect(4) 5446 bv.SetBit(1) 5447 qa = rdqueries.HasBitVectPropWithValueQueryAtom("prop", bv, tolerance=0.0) 5448 atom.ExpandQuery(qa) 5449 5450 res = m.GetSubstructMatches(sma) 5451 self.assertEqual(res, ((1, ), )) 5452 5453 sma = Chem.MolFromSmarts("C") 5454 for atom in sma.GetAtoms(): 5455 bv = DataStructs.ExplicitBitVect(4) 5456 bv.SetBit(0) 5457 qa = rdqueries.HasBitVectPropWithValueQueryAtom("prop", bv, tolerance=0.0) 5458 atom.ExpandQuery(qa) 5459 5460 res = m.GetSubstructMatches(sma) 5461 self.assertEqual(res, ((0, ), )) 5462 5463 sma = Chem.MolFromSmarts("C") 5464 for atom in sma.GetAtoms(): 5465 bv = DataStructs.ExplicitBitVect(4) 5466 bv.SetBit(0) 5467 qa = rdqueries.HasBitVectPropWithValueQueryAtom("prop", bv, tolerance=1.0) 5468 atom.ExpandQuery(qa) 5469 5470 res = m.GetSubstructMatches(sma) 5471 self.assertEqual(res, ((0, ), (1, ))) 5472 5473 def testGithub2441(self): 5474 m = Chem.MolFromSmiles("CC") 5475 conf = Chem.Conformer(2) 5476 m.AddConformer(conf, assignId=False) 5477 m.GetConformer().SetIntProp("foo", 1) 5478 m.GetConformer().SetProp("bar", "foo") 5479 self.assertTrue(m.GetConformer().HasProp("foo")) 5480 self.assertFalse(m.GetConformer().HasProp("food")) 5481 d = m.GetConformer().GetPropsAsDict() 5482 self.assertTrue('foo' in d) 5483 self.assertTrue('bar' in d) 5484 self.assertEqual(d['bar'], 'foo') 5485 self.assertEqual(m.GetConformer().GetProp("bar"), "foo") 5486 self.assertEqual(m.GetConformer().GetIntProp("foo"), 1) 5487 5488 def testGithub2479(self): 5489 # Chemistry failure in last entry 5490 smi2 = '''c1ccccc duff 5491c1ccccc1 ok 5492c1ccncc1 pyridine 5493C(C garbage 5494C1CC1 ok2 5495C1C(Cl)C1 ok3 5496CC(C)(C)(C)C duff2 5497''' 5498 suppl2 = Chem.SmilesMolSupplier() 5499 suppl2.SetData(smi2, titleLine=False, nameColumn=1) 5500 l = [x for x in suppl2] 5501 self.assertEqual(len(l), 7) 5502 self.assertTrue(l[6] is None) 5503 5504 # SMILES failure in last entry 5505 smi2 = '''c1ccccc duff 5506c1ccccc1 ok 5507c1ccncc1 pyridine 5508C(C garbage 5509C1CC1 ok2 5510C1C(Cl)C1 ok3 5511C1C(Cl)CCCC duff2 5512''' 5513 suppl2 = Chem.SmilesMolSupplier() 5514 suppl2.SetData(smi2, titleLine=False, nameColumn=1) 5515 l = [x for x in suppl2] 5516 self.assertEqual(len(l), 7) 5517 self.assertTrue(l[6] is None) 5518 5519 sdf = b""" 5520 Mrv1810 06051911332D 5521 5522 3 2 0 0 0 0 999 V2000 5523 -13.3985 4.9850 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5524 -12.7066 5.4343 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 5525 -12.0654 4.9151 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5526 1 2 1 0 0 0 0 5527 2 3 1 0 0 0 0 5528M END 5529$$$$ 5530 5531 Mrv1810 06051911332D 5532 5533 3 2 0 0 0 0 999 V2000 5534 -10.3083 4.8496 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5535 -9.6408 5.3345 0.0000 F 0 0 0 0 0 0 0 0 0 0 0 0 5536 -9.0277 4.7825 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5537 1 2 1 0 0 0 0 5538 2 3 1 0 0 0 0 5539M END 5540$$$$ 5541 5542 Mrv1810 06051911332D 5543 5544 3 2 0 0 0 0 999 V2000 5545 -10.3083 4.8496 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5546 -9.6""" 5547 suppl3 = Chem.SDMolSupplier() 5548 suppl3.SetData(sdf) 5549 l = [x for x in suppl3] 5550 self.assertEqual(len(l), 3) 5551 self.assertTrue(l[1] is None) 5552 self.assertTrue(l[2] is None) 5553 5554 from io import BytesIO 5555 sio = BytesIO(sdf) 5556 suppl3 = Chem.ForwardSDMolSupplier(sio) 5557 l = [x for x in suppl3] 5558 self.assertEqual(len(l), 3) 5559 self.assertTrue(l[1] is None) 5560 self.assertTrue(l[2] is None) 5561 5562 sdf = b""" 5563 Mrv1810 06051911332D 5564 5565 3 2 0 0 0 0 999 V2000 5566 -13.3985 4.9850 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5567 -12.7066 5.4343 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 5568 -12.0654 4.9151 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5569 1 2 1 0 0 0 0 5570 2 3 1 0 0 0 0 5571M END 5572> <pval> (1) 5573[1,2,] 5574 5575$$$$ 5576 5577 Mrv1810 06051911332D 5578 5579 3 2 0 0 0 0 999 V2000 5580 -10.3083 4.8496 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5581 -9.6408 5.3345 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0 5582 -9.0277 4.7825 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5583 1 2 1 0 0 0 0 5584 2 3 1 0 0 0 0 5585M END 5586> <pval> (1) 5587[1,2,] 5588""" 5589 suppl3 = Chem.SDMolSupplier() 5590 suppl3.SetData(sdf) 5591 l = [x for x in suppl3] 5592 self.assertEqual(len(l), 2) 5593 self.assertTrue(l[0] is not None) 5594 self.assertTrue(l[1] is not None) 5595 5596 from io import BytesIO 5597 sio = BytesIO(sdf) 5598 suppl3 = Chem.ForwardSDMolSupplier(sio) 5599 l = [x for x in suppl3] 5600 self.assertEqual(len(l), 2) 5601 self.assertTrue(l[0] is not None) 5602 self.assertTrue(l[1] is not None) 5603 5604 def testXYZ(self): 5605 conf = Chem.Conformer(5) 5606 conf.SetAtomPosition(0, [0.000, 0.000, 0.000]) 5607 conf.SetAtomPosition(1, [-0.635, -0.635, 0.635]) 5608 conf.SetAtomPosition(2, [-0.635, 0.635, -0.635]) 5609 conf.SetAtomPosition(3, [0.635, -0.635, -0.635]) 5610 conf.SetAtomPosition(4, [0.635, 0.635, 0.635]) 5611 5612 emol = Chem.EditableMol(Chem.Mol()) 5613 for z in [6, 1, 1, 1, 1]: 5614 emol.AddAtom(Chem.Atom(z)) 5615 mol = emol.GetMol() 5616 mol.SetProp('_Name', 'methane\nthis part should not be output') 5617 mol.AddConformer(conf) 5618 5619 xyzblock_expected = """5 5620methane 5621C 0.000000 0.000000 0.000000 5622H -0.635000 -0.635000 0.635000 5623H -0.635000 0.635000 -0.635000 5624H 0.635000 -0.635000 -0.635000 5625H 0.635000 0.635000 0.635000 5626""" 5627 5628 self.assertEqual(Chem.MolToXYZBlock(mol), xyzblock_expected) 5629 5630 def testSanitizationExceptionBasics(self): 5631 try: 5632 Chem.SanitizeMol(Chem.MolFromSmiles('CFC', sanitize=False)) 5633 except Chem.AtomValenceException as exc: 5634 self.assertEqual(exc.cause.GetAtomIdx(), 1) 5635 else: 5636 self.assertFalse(True) 5637 5638 try: 5639 Chem.SanitizeMol(Chem.MolFromSmiles('c1cc1', sanitize=False)) 5640 except Chem.KekulizeException as exc: 5641 self.assertEqual(exc.cause.GetAtomIndices(), (0, 1, 2)) 5642 else: 5643 self.assertFalse(True) 5644 5645 def testSanitizationExceptionHierarchy(self): 5646 with self.assertRaises(Chem.AtomValenceException): 5647 Chem.SanitizeMol(Chem.MolFromSmiles('CFC', sanitize=False)) 5648 with self.assertRaises(Chem.AtomSanitizeException): 5649 Chem.SanitizeMol(Chem.MolFromSmiles('CFC', sanitize=False)) 5650 with self.assertRaises(Chem.MolSanitizeException): 5651 Chem.SanitizeMol(Chem.MolFromSmiles('CFC', sanitize=False)) 5652 with self.assertRaises(ValueError): 5653 Chem.SanitizeMol(Chem.MolFromSmiles('CFC', sanitize=False)) 5654 5655 with self.assertRaises(Chem.KekulizeException): 5656 Chem.SanitizeMol(Chem.MolFromSmiles('c1cc1', sanitize=False)) 5657 with self.assertRaises(Chem.MolSanitizeException): 5658 Chem.SanitizeMol(Chem.MolFromSmiles('c1cc1', sanitize=False)) 5659 with self.assertRaises(ValueError): 5660 Chem.SanitizeMol(Chem.MolFromSmiles('c1cc1', sanitize=False)) 5661 5662 def testNoExceptionSmilesParserParams(self): 5663 """ 5664 MolFromSmiles should catch exceptions even when SmilesParserParams 5665 is provided. 5666 """ 5667 smiles_params = Chem.SmilesParserParams() 5668 mol = Chem.MolFromSmiles("C1CC", smiles_params) 5669 self.assertIsNone(mol) 5670 5671 def testDetectChemistryProblems(self): 5672 m = Chem.MolFromSmiles('CFCc1cc1FC', sanitize=False) 5673 ps = Chem.DetectChemistryProblems(m) 5674 self.assertEqual(len(ps), 3) 5675 self.assertEqual([x.GetType() for x in ps], 5676 ['AtomValenceException', 'AtomValenceException', 'KekulizeException']) 5677 self.assertEqual(ps[0].GetAtomIdx(), 1) 5678 self.assertEqual(ps[1].GetAtomIdx(), 6) 5679 self.assertEqual(ps[2].GetAtomIndices(), (3, 4, 5)) 5680 5681 def testGithub2611(self): 5682 mol = Chem.MolFromSmiles('ONCS.ONCS') 5683 for atom in mol.GetAtoms(): 5684 atom.SetIsotope(atom.GetIdx()) 5685 5686 order1 = list( 5687 Chem.CanonicalRankAtomsInFragment(mol, atomsToUse=range(0, 4), breakTies=False, 5688 includeIsotopes=True)) 5689 order2 = list( 5690 Chem.CanonicalRankAtomsInFragment(mol, atomsToUse=range(0, 8), breakTies=False, 5691 includeIsotopes=False)) 5692 self.assertNotEqual(order1[:4], order2[4:]) 5693 # ensure that the orders are ignored in the second batch 5694 self.assertEqual(order2[:4], order2[4:]) 5695 5696 for smi in ['ONCS.ONCS', 'F[C@@H](Br)[C@H](F)Cl']: 5697 mol = Chem.MolFromSmiles(smi) 5698 for atom in mol.GetAtoms(): 5699 atom.SetIsotope(atom.GetIdx()) 5700 5701 for iso, chiral in [(True, True), (True, False), (False, True), (False, False)]: 5702 order1 = list( 5703 Chem.CanonicalRankAtomsInFragment(mol, atomsToUse=range(0, mol.GetNumAtoms()), 5704 bondsToUse=range(0, 5705 mol.GetNumBonds()), breakTies=False, 5706 includeIsotopes=iso, includeChirality=chiral)) 5707 order2 = list( 5708 Chem.CanonicalRankAtomsInFragment(mol, atomsToUse=range(0, mol.GetNumAtoms()), 5709 bondsToUse=range(0, 5710 mol.GetNumBonds()), breakTies=True, 5711 includeIsotopes=iso, includeChirality=chiral)) 5712 order3 = list( 5713 Chem.CanonicalRankAtoms(mol, breakTies=False, includeIsotopes=iso, 5714 includeChirality=chiral)) 5715 order4 = list( 5716 Chem.CanonicalRankAtoms(mol, breakTies=True, includeIsotopes=iso, 5717 includeChirality=chiral)) 5718 self.assertEqual(order1, order3) 5719 self.assertEqual(order2, order4) 5720 5721 def testSetBondStereoFromDirections(self): 5722 m1 = Chem.MolFromMolBlock( 5723 ''' 5724 Mrv1810 10141909482D 5725 5726 4 3 0 0 0 0 999 V2000 5727 3.3412 -2.9968 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5728 2.5162 -2.9968 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5729 2.1037 -3.7112 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5730 3.7537 -2.2823 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5731 1 2 2 0 0 0 0 5732 2 3 1 0 0 0 0 5733 1 4 1 0 0 0 0 5734M END 5735''', sanitize=False) 5736 self.assertEqual(m1.GetBondBetweenAtoms(0, 1).GetBondType(), Chem.BondType.DOUBLE) 5737 self.assertEqual(m1.GetBondBetweenAtoms(0, 1).GetStereo(), Chem.BondStereo.STEREONONE) 5738 Chem.SetBondStereoFromDirections(m1) 5739 self.assertEqual(m1.GetBondBetweenAtoms(0, 1).GetStereo(), Chem.BondStereo.STEREOTRANS) 5740 5741 m2 = Chem.MolFromMolBlock( 5742 ''' 5743 Mrv1810 10141909542D 5744 5745 4 3 0 0 0 0 999 V2000 5746 3.4745 -5.2424 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5747 2.6495 -5.2424 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5748 2.2370 -5.9569 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5749 3.8870 -5.9569 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 5750 1 2 2 0 0 0 0 5751 2 3 1 0 0 0 0 5752 1 4 1 0 0 0 0 5753M END 5754''', sanitize=False) 5755 self.assertEqual(m2.GetBondBetweenAtoms(0, 1).GetBondType(), Chem.BondType.DOUBLE) 5756 self.assertEqual(m2.GetBondBetweenAtoms(0, 1).GetStereo(), Chem.BondStereo.STEREONONE) 5757 Chem.SetBondStereoFromDirections(m2) 5758 self.assertEqual(m2.GetBondBetweenAtoms(0, 1).GetStereo(), Chem.BondStereo.STEREOCIS) 5759 5760 def testSetBondDirFromStereo(self): 5761 m1 = Chem.MolFromSmiles('CC=CC') 5762 m1.GetBondWithIdx(1).SetStereoAtoms(0, 3) 5763 m1.GetBondWithIdx(1).SetStereo(Chem.BondStereo.STEREOCIS) 5764 Chem.SetDoubleBondNeighborDirections(m1) 5765 self.assertEqual(Chem.MolToSmiles(m1), r"C/C=C\C") 5766 self.assertEqual(m1.GetBondWithIdx(0).GetBondDir(), Chem.BondDir.ENDUPRIGHT) 5767 self.assertEqual(m1.GetBondWithIdx(2).GetBondDir(), Chem.BondDir.ENDDOWNRIGHT) 5768 5769 def testAssignChiralTypesFromMolParity(self): 5770 5771 class TestAssignChiralTypesFromMolParity: 5772 5773 class BondDef: 5774 5775 def __init__(self, bi, ei, t): 5776 self.beginIdx = bi 5777 self.endIdx = ei 5778 self.type = t 5779 5780 def __init__(self, mol, parent): 5781 self.parent = parent 5782 self.parityMap = { 5783 Chem.ChiralType.CHI_TETRAHEDRAL_CW: 1, 5784 Chem.ChiralType.CHI_TETRAHEDRAL_CCW: 2, 5785 Chem.ChiralType.CHI_UNSPECIFIED: 0, 5786 Chem.ChiralType.CHI_OTHER: 0 5787 } 5788 self.d_rwMol = Chem.RWMol(mol) 5789 self.assignMolParity() 5790 self.fillBondDefVect() 5791 Chem.AssignAtomChiralTagsFromMolParity(self.d_rwMol) 5792 self.d_refSmiles = Chem.MolToSmiles(self.d_rwMol) 5793 self.heapPermutation() 5794 5795 def assignMolParity(self): 5796 Chem.AssignAtomChiralTagsFromStructure(self.d_rwMol) 5797 for a in self.d_rwMol.GetAtoms(): 5798 parity = self.parityMap[a.GetChiralTag()] 5799 a.SetIntProp("molParity", parity) 5800 a.SetChiralTag(Chem.ChiralType.CHI_UNSPECIFIED) 5801 5802 def fillBondDefVect(self): 5803 self.d_bondDefVect = [ 5804 self.BondDef(b.GetBeginAtomIdx(), b.GetEndAtomIdx(), b.GetBondType()) 5805 for b in self.d_rwMol.GetBonds() 5806 ] 5807 5808 def stripBonds(self): 5809 for i in reversed(range(self.d_rwMol.GetNumBonds())): 5810 b = self.d_rwMol.GetBondWithIdx(i) 5811 self.d_rwMol.RemoveBond(b.GetBeginAtomIdx(), b.GetEndAtomIdx()) 5812 5813 def addBonds(self): 5814 [ 5815 self.d_rwMol.AddBond(bondDef.beginIdx, bondDef.endIdx, bondDef.type) 5816 for bondDef in self.d_bondDefVect 5817 ] 5818 5819 def checkBondPermutation(self): 5820 self.stripBonds() 5821 self.addBonds() 5822 Chem.SanitizeMol(self.d_rwMol) 5823 Chem.AssignAtomChiralTagsFromMolParity(self.d_rwMol) 5824 self.parent.assertEqual(Chem.MolToSmiles(self.d_rwMol), self.d_refSmiles) 5825 5826 def heapPermutation(self, s=0): 5827 # if size becomes 1 the permutation is ready to use 5828 if (s == 0): 5829 s = len(self.d_bondDefVect) 5830 if (s == 1): 5831 self.checkBondPermutation() 5832 return 5833 for i in range(s): 5834 self.heapPermutation(s - 1) 5835 # if size is odd, swap first and last element 5836 j = 0 if (s % 2 == 1) else i 5837 self.d_bondDefVect[j], self.d_bondDefVect[s - 1] = \ 5838 self.d_bondDefVect[s - 1], self.d_bondDefVect[j] 5839 5840 molb = """ 5841 RDKit 3D 5842 5843 6 5 0 0 1 0 0 0 0 0999 V2000 5844 -2.9747 1.7234 0.0753 C 0 0 0 0 0 0 0 0 0 0 0 0 5845 -1.4586 1.4435 0.1253 C 0 0 0 0 0 0 0 0 0 0 0 0 5846 -3.5885 2.6215 1.4893 Cl 0 0 0 0 0 0 0 0 0 0 0 0 5847 -3.7306 0.3885 -0.0148 C 0 0 0 0 0 0 0 0 0 0 0 0 5848 -0.3395 3.0471 0.1580 Br 0 0 0 0 0 0 0 0 0 0 0 0 5849 -1.1574 0.7125 1.2684 F 0 0 0 0 0 0 0 0 0 0 0 0 5850 1 2 1 0 5851 1 3 1 0 5852 1 4 1 0 5853 2 5 1 0 5854 2 6 1 0 5855M END 5856""" 5857 m = Chem.RWMol(Chem.MolFromMolBlock(molb, sanitize=True, removeHs=False)) 5858 self.assertIsNotNone(m) 5859 TestAssignChiralTypesFromMolParity(m, self) 5860 5861 def testCXSMILESErrors(self): 5862 smi = "CCC |FAILURE|" 5863 ps = Chem.SmilesParserParams() 5864 ps.strictCXSMILES = False 5865 m = Chem.MolFromSmiles(smi, ps) 5866 self.assertTrue(m is not None) 5867 self.assertEqual(m.GetNumAtoms(), 3) 5868 5869 def testRemoveHsParams(self): 5870 smips = Chem.SmilesParserParams() 5871 smips.removeHs = False 5872 5873 m = Chem.MolFromSmiles('F.[H]', smips) 5874 ps = Chem.RemoveHsParameters() 5875 m = Chem.RemoveHs(m, ps) 5876 self.assertEqual(m.GetNumAtoms(), 2) 5877 ps.removeDegreeZero = True 5878 m = Chem.RemoveHs(m, ps) 5879 self.assertEqual(m.GetNumAtoms(), 1) 5880 5881 m = Chem.MolFromSmiles('F[H-]F', smips) 5882 ps = Chem.RemoveHsParameters() 5883 m = Chem.RemoveHs(m, ps) 5884 self.assertEqual(m.GetNumAtoms(), 3) 5885 m = Chem.MolFromSmiles('F[H-]F', smips) 5886 ps.removeHigherDegrees = True 5887 m = Chem.RemoveHs(m, ps) 5888 self.assertEqual(m.GetNumAtoms(), 2) 5889 5890 m = Chem.MolFromSmiles('[H][H]', smips) 5891 ps = Chem.RemoveHsParameters() 5892 m = Chem.RemoveHs(m, ps) 5893 self.assertEqual(m.GetNumAtoms(), 2) 5894 m = Chem.MolFromSmiles('[H][H]', smips) 5895 ps.removeOnlyHNeighbors = True 5896 m = Chem.RemoveHs(m, ps) 5897 self.assertEqual(m.GetNumAtoms(), 0) 5898 5899 m = Chem.MolFromSmiles('F[2H]', smips) 5900 ps = Chem.RemoveHsParameters() 5901 m = Chem.RemoveHs(m, ps) 5902 self.assertEqual(m.GetNumAtoms(), 2) 5903 m = Chem.MolFromSmiles('F[2H]', smips) 5904 ps.removeIsotopes = True 5905 m = Chem.RemoveHs(m, ps) 5906 self.assertEqual(m.GetNumAtoms(), 1) 5907 5908 m = Chem.MolFromSmiles('c1c(C([2H])([2H])F)cccc1', smips) 5909 ps = Chem.RemoveHsParameters() 5910 m_noh = Chem.RemoveHs(m, ps) 5911 self.assertEqual(m_noh.GetNumAtoms(), m.GetNumAtoms()) 5912 ps.removeAndTrackIsotopes = True 5913 m_noh = Chem.RemoveHs(m, ps) 5914 self.assertEqual(m_noh.GetNumAtoms(), m.GetNumAtoms() - 2) 5915 self.assertTrue(m_noh.GetAtomWithIdx(2).HasProp("_isotopicHs")) 5916 self.assertEqual(tuple(m_noh.GetAtomWithIdx(2).GetPropsAsDict().get("_isotopicHs")), (2, 2)) 5917 m_h = Chem.AddHs(m_noh) 5918 self.assertFalse(m_h.GetAtomWithIdx(2).HasProp("_isotopicHs")) 5919 self.assertEqual( 5920 sum([ 5921 1 for nbr in m_h.GetAtomWithIdx(2).GetNeighbors() 5922 if (nbr.GetAtomicNum() == 1 and nbr.GetIsotope()) 5923 ]), 2) 5924 5925 m = Chem.MolFromSmiles('*[H]', smips) 5926 ps = Chem.RemoveHsParameters() 5927 m = Chem.RemoveHs(m, ps) 5928 self.assertEqual(m.GetNumAtoms(), 2) 5929 m = Chem.MolFromSmiles('*[H]', smips) 5930 ps.removeDummyNeighbors = True 5931 m = Chem.RemoveHs(m, ps) 5932 self.assertEqual(m.GetNumAtoms(), 1) 5933 5934 m = Chem.MolFromSmiles('F/C=N/[H]', smips) 5935 ps = Chem.RemoveHsParameters() 5936 m = Chem.RemoveHs(m, ps) 5937 self.assertEqual(m.GetNumAtoms(), 4) 5938 m = Chem.MolFromSmiles('F/C=N/[H]', smips) 5939 ps.removeDefiningBondStereo = True 5940 m = Chem.RemoveHs(m, ps) 5941 self.assertEqual(m.GetNumAtoms(), 3) 5942 5943 m = Chem.MolFromSmiles('FC([H])(O)Cl', smips) 5944 m.GetBondBetweenAtoms(1, 2).SetBondDir(Chem.BondDir.BEGINWEDGE) 5945 ps = Chem.RemoveHsParameters() 5946 m = Chem.RemoveHs(m, ps) 5947 self.assertEqual(m.GetNumAtoms(), 4) 5948 m = Chem.MolFromSmiles('FC([H])(O)Cl', smips) 5949 m.GetBondBetweenAtoms(1, 2).SetBondDir(Chem.BondDir.BEGINWEDGE) 5950 ps.removeWithWedgedBond = False 5951 m = Chem.RemoveHs(m, ps) 5952 self.assertEqual(m.GetNumAtoms(), 5) 5953 5954 m = Chem.MolFromSmarts('F[#1]') 5955 ps = Chem.RemoveHsParameters() 5956 m = Chem.RemoveHs(m, ps) 5957 self.assertEqual(m.GetNumAtoms(), 2) 5958 m = Chem.MolFromSmarts('F[#1]') 5959 ps.removeWithQuery = True 5960 m = Chem.RemoveHs(m, ps) 5961 self.assertEqual(m.GetNumAtoms(), 1) 5962 5963 m = Chem.MolFromSmiles('[C@]12([H])CCC1CO2.[H+].F[H-]F.[H][H].[H]*.F/C=C/[H]') 5964 m = Chem.RemoveAllHs(m) 5965 for at in m.GetAtoms(): 5966 self.assertNotEqual(at.GetAtomicNum(), 1) 5967 5968 def testPickleCoordsAsDouble(self): 5969 import pickle 5970 m = Chem.MolFromSmiles('C') 5971 test_num = 1e50 5972 conf = Chem.Conformer(1) 5973 conf.SetAtomPosition(0, (test_num, 0.0, 0.0)) 5974 m.AddConformer(conf) 5975 5976 opts = Chem.GetDefaultPickleProperties() 5977 Chem.SetDefaultPickleProperties(Chem.PropertyPickleOptions.NoProps) 5978 self.assertNotEqual(pickle.loads(pickle.dumps(m)).GetConformer().GetAtomPosition(0).x, test_num) 5979 5980 try: 5981 Chem.SetDefaultPickleProperties(Chem.PropertyPickleOptions.CoordsAsDouble) 5982 self.assertEqual(pickle.loads(pickle.dumps(m)).GetConformer().GetAtomPosition(0).x, test_num) 5983 finally: 5984 Chem.SetDefaultPickleProperties(opts) 5985 5986 def testCustomSubstructMatchCheck(self): 5987 5988 def accept_none(mol, vect): 5989 return False 5990 5991 def accept_all(mol, vect): 5992 return True 5993 5994 def accept_large(mol, vect): 5995 return sum(vect) > 5 5996 5997 m = Chem.MolFromSmiles('CCOCC') 5998 p = Chem.MolFromSmiles('CCO') 5999 ps = Chem.SubstructMatchParameters() 6000 self.assertEqual(len(m.GetSubstructMatches(p, ps)), 2) 6001 6002 ps.setExtraFinalCheck(accept_none) 6003 self.assertEqual(len(m.GetSubstructMatches(p, ps)), 0) 6004 ps.setExtraFinalCheck(accept_all) 6005 self.assertEqual(len(m.GetSubstructMatches(p, ps)), 2) 6006 ps.setExtraFinalCheck(accept_large) 6007 self.assertEqual(len(m.GetSubstructMatches(p, ps)), 1) 6008 6009 def testMostSubstitutedCoreMatch(self): 6010 core = Chem.MolFromSmarts("[*:1]c1cc([*:2])ccc1[*:3]") 6011 orthoMeta = Chem.MolFromSmiles("c1ccc(-c2ccc(-c3ccccc3)c(-c3ccccc3)c2)cc1") 6012 ortho = Chem.MolFromSmiles("c1ccc(-c2ccccc2-c2ccccc2)cc1") 6013 meta = Chem.MolFromSmiles("c1ccc(-c2cccc(-c3ccccc3)c2)cc1") 6014 biphenyl = Chem.MolFromSmiles("c1ccccc1-c1ccccc1") 6015 phenyl = Chem.MolFromSmiles("c1ccccc1") 6016 6017 def numHsMatchingDummies(mol, core, match): 6018 return sum([ 6019 1 for qi, ai in enumerate(match) if core.GetAtomWithIdx(qi).GetAtomicNum() == 0 6020 and mol.GetAtomWithIdx(ai).GetAtomicNum() == 1 6021 ]) 6022 6023 for mol, res in ((orthoMeta, 0), (ortho, 1), (meta, 1), (biphenyl, 2), (phenyl, 3)): 6024 mol = Chem.AddHs(mol) 6025 matches = mol.GetSubstructMatches(core) 6026 bestMatch = Chem.GetMostSubstitutedCoreMatch(mol, core, matches) 6027 self.assertEqual(numHsMatchingDummies(mol, core, bestMatch), res) 6028 ctrlCounts = sorted([numHsMatchingDummies(mol, core, match) for match in matches]) 6029 sortedCounts = [ 6030 numHsMatchingDummies(mol, core, match) 6031 for match in Chem.SortMatchesByDegreeOfCoreSubstitution(mol, core, matches) 6032 ] 6033 self.assertEqual(len(ctrlCounts), len(sortedCounts)) 6034 self.assertTrue(all(ctrl == sortedCounts[i] for i, ctrl in enumerate(ctrlCounts))) 6035 with self.assertRaises(ValueError): 6036 Chem.GetMostSubstitutedCoreMatch(orthoMeta, core, []) 6037 with self.assertRaises(ValueError): 6038 Chem.SortMatchesByDegreeOfCoreSubstitution(orthoMeta, core, []) 6039 6040 def testSetCoordsTerminalAtom(self): 6041 mol = Chem.MolFromMolBlock(""" 6042 RDKit 2D 6043 6044 6 6 0 0 0 0 0 0 0 0999 V2000 6045 1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6046 0.7500 -1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6047 -0.7500 -1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6048 -1.5000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6049 -0.7500 1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6050 0.7500 1.2990 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0 6051 1 2 2 0 6052 2 3 1 0 6053 3 4 2 0 6054 4 5 1 0 6055 5 6 2 0 6056 6 1 1 0 6057M END 6058""") 6059 mol = Chem.RWMol(mol) 6060 atom = Chem.Atom(0) 6061 idx = mol.AddAtom(atom) 6062 mol.AddBond(idx, 0) 6063 Chem.SetTerminalAtomCoords(mol, idx, 0) 6064 coord = mol.GetConformer().GetAtomPosition(idx) 6065 self.assertAlmostEqual(coord.x, 2.5, 2) 6066 self.assertAlmostEqual(coord.y, 0, 2) 6067 self.assertAlmostEqual(coord.z, 0, 2) 6068 6069 def testSuppliersReadingDirectories(self): 6070 # this is an odd one, basically we need to check that we don't hang 6071 # which is pretty much a bad test in my opinion, but YMMV 6072 d = tempfile.mkdtemp() 6073 self.assertTrue(os.path.exists(d)) 6074 6075 for supplier in [ 6076 Chem.SmilesMolSupplier, 6077 Chem.SDMolSupplier, 6078 Chem.TDTMolSupplier, 6079 #Chem.CompressedSDMolSupplier, 6080 ]: 6081 print("supplier:", supplier) 6082 with self.assertRaises(OSError): 6083 suppl = supplier(d) 6084 if hasattr(Chem, 'MaeMolSupplier'): 6085 with self.assertRaises(OSError): 6086 suppl = Chem.MaeMolSupplier(d) 6087 os.rmdir(d) 6088 6089 def testRandomSmilesVect(self): 6090 m = Chem.MolFromSmiles("C1OCC1N(CO)(Cc1ccccc1NCCl)") 6091 v = Chem.MolToRandomSmilesVect(m, 5, randomSeed=0xf00d) 6092 self.assertEqual(v, [ 6093 "c1cc(CN(C2COC2)CO)c(cc1)NCCl", "N(CCl)c1c(CN(C2COC2)CO)cccc1", "N(CCl)c1ccccc1CN(C1COC1)CO", 6094 "OCN(Cc1ccccc1NCCl)C1COC1", "C(N(C1COC1)Cc1c(cccc1)NCCl)O" 6095 ]) 6096 6097 v = Chem.MolToRandomSmilesVect(m, 5, randomSeed=0xf00d, allHsExplicit=True) 6098 self.assertEqual(v, [ 6099 "[cH]1[cH][c]([CH2][N]([CH]2[CH2][O][CH2]2)[CH2][OH])[c]([cH][cH]1)[NH][CH2][Cl]", 6100 "[NH]([CH2][Cl])[c]1[c]([CH2][N]([CH]2[CH2][O][CH2]2)[CH2][OH])[cH][cH][cH][cH]1", 6101 "[NH]([CH2][Cl])[c]1[cH][cH][cH][cH][c]1[CH2][N]([CH]1[CH2][O][CH2]1)[CH2][OH]", 6102 "[OH][CH2][N]([CH2][c]1[cH][cH][cH][cH][c]1[NH][CH2][Cl])[CH]1[CH2][O][CH2]1", 6103 "[CH2]([N]([CH]1[CH2][O][CH2]1)[CH2][c]1[c]([cH][cH][cH][cH]1)[NH][CH2][Cl])[OH]" 6104 ]) 6105 6106 def testGithub3198(self): 6107 6108 ps = Chem.SmilesParserParams() 6109 ps.removeHs = False 6110 m = Chem.MolFromSmiles('[H]OC(F).[Na]', ps) 6111 6112 qa = rdqueries.AAtomQueryAtom() 6113 self.assertEqual(tuple(x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)), (1, 2, 3, 4)) 6114 6115 qa = rdqueries.AHAtomQueryAtom() 6116 self.assertEqual(tuple(x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)), (0, 1, 2, 3, 4)) 6117 6118 qa = rdqueries.QAtomQueryAtom() 6119 self.assertEqual(tuple(x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)), (1, 3, 4)) 6120 6121 qa = rdqueries.QHAtomQueryAtom() 6122 self.assertEqual(tuple(x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)), (0, 1, 3, 4)) 6123 6124 qa = rdqueries.XAtomQueryAtom() 6125 self.assertEqual(tuple(x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)), (3, )) 6126 6127 qa = rdqueries.XHAtomQueryAtom() 6128 self.assertEqual(tuple(x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)), (0, 3)) 6129 6130 qa = rdqueries.MAtomQueryAtom() 6131 self.assertEqual(tuple(x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)), (4, )) 6132 6133 qa = rdqueries.MHAtomQueryAtom() 6134 self.assertEqual(tuple(x.GetIdx() for x in m.GetAtomsMatchingQuery(qa)), (0, 4)) 6135 6136 def testAdjustQueryPropertiesFiveRings(self): 6137 mol = Chem.MolFromSmiles('c1cc[nH]c1') 6138 nops = Chem.AdjustQueryParameters.NoAdjustments() 6139 nmol = Chem.AdjustQueryProperties(mol, nops) 6140 self.assertEqual(Chem.MolToSmarts(nmol), "[#6]1:[#6]:[#6]:[#7H]:[#6]:1") 6141 6142 nops.adjustConjugatedFiveRings = True 6143 nmol = Chem.AdjustQueryProperties(mol, nops) 6144 self.assertEqual(Chem.MolToSmarts(nmol), "[#6]1-,=,:[#6]-,=,:[#6]-,=,:[#7H]-,=,:[#6]-,=,:1") 6145 6146 def testFindPotentialStereo(self): 6147 mol = Chem.MolFromSmiles('C[C@H](F)C=CC') 6148 si = Chem.FindPotentialStereo(mol) 6149 self.assertEqual(len(si), 2) 6150 self.assertEqual(si[0].type, Chem.StereoType.Atom_Tetrahedral) 6151 self.assertEqual(si[0].specified, Chem.StereoSpecified.Specified) 6152 self.assertEqual(si[0].centeredOn, 1) 6153 self.assertEqual(si[0].descriptor, Chem.StereoDescriptor.Tet_CCW) 6154 self.assertEqual(list(si[0].controllingAtoms), [0, 2, 3]) 6155 self.assertEqual(si[1].type, Chem.StereoType.Bond_Double) 6156 self.assertEqual(si[1].specified, Chem.StereoSpecified.Unspecified) 6157 self.assertEqual(si[1].centeredOn, 3) 6158 self.assertEqual(si[1].descriptor, Chem.StereoDescriptor.NoValue) 6159 self.assertEqual(list(si[1].controllingAtoms), 6160 [1, Chem.StereoInfo.NOATOM, 5, Chem.StereoInfo.NOATOM]) 6161 6162 def testNewFindMolChiralCenters(self): 6163 mol = Chem.MolFromSmiles('C[C@H](F)C=CC(F)Cl') 6164 ctrs = Chem.FindMolChiralCenters(mol, useLegacyImplementation=False) 6165 self.assertEqual(len(ctrs), 1) 6166 self.assertEqual(ctrs, [(1, 'S')]) 6167 ctrs = Chem.FindMolChiralCenters(mol, useLegacyImplementation=False, includeCIP=False) 6168 self.assertEqual(len(ctrs), 1) 6169 self.assertEqual(ctrs, [(1, 'Tet_CCW')]) 6170 ctrs = Chem.FindMolChiralCenters(mol, useLegacyImplementation=False, includeUnassigned=True, 6171 includeCIP=False) 6172 self.assertEqual(len(ctrs), 2) 6173 self.assertEqual(ctrs, [(1, 'Tet_CCW'), (5, '?')]) 6174 ctrs = Chem.FindMolChiralCenters(mol, useLegacyImplementation=False, includeUnassigned=True, 6175 includeCIP=True) 6176 self.assertEqual(len(ctrs), 2) 6177 self.assertEqual(ctrs, [(1, 'S'), (5, '?')]) 6178 6179 def testMolFromPNG(self): 6180 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 6181 'colchicine.png') 6182 mol = Chem.MolFromPNGFile(fileN) 6183 self.assertIsNotNone(mol) 6184 self.assertEqual(mol.GetNumAtoms(), 29) 6185 6186 with open(fileN, 'rb') as inf: 6187 d = inf.read() 6188 mol = Chem.MolFromPNGString(d) 6189 self.assertIsNotNone(mol) 6190 self.assertEqual(mol.GetNumAtoms(), 29) 6191 6192 def testMolToPNG(self): 6193 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 6194 'colchicine.no_metadata.png') 6195 6196 with open(fileN, 'rb') as inf: 6197 d = inf.read() 6198 mol = Chem.MolFromSmiles("COc1cc2c(c(OC)c1OC)-c1ccc(OC)c(=O)cc1[C@@H](NC(C)=O)CC2") 6199 self.assertIsNotNone(mol) 6200 self.assertEqual(mol.GetNumAtoms(), 29) 6201 6202 nd = Chem.MolMetadataToPNGString(mol, d) 6203 mol = Chem.MolFromPNGString(nd) 6204 self.assertIsNotNone(mol) 6205 self.assertEqual(mol.GetNumAtoms(), 29) 6206 6207 nd = Chem.MolMetadataToPNGFile(mol, fileN) 6208 mol = Chem.MolFromPNGString(nd) 6209 self.assertIsNotNone(mol) 6210 self.assertEqual(mol.GetNumAtoms(), 29) 6211 6212 def testMolsFromPNG(self): 6213 refMols = [Chem.MolFromSmiles(x) for x in ('c1ccccc1', 'CCO', 'CC(=O)O', 'c1ccccn1')] 6214 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 6215 'multiple_mols.png') 6216 mols = Chem.MolsFromPNGFile(fileN) 6217 self.assertEqual(len(mols), len(refMols)) 6218 for mol, refMol in zip(mols, refMols): 6219 self.assertEqual(Chem.MolToSmiles(mol), Chem.MolToSmiles(refMol)) 6220 6221 def testMetadataToPNG(self): 6222 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 6223 'colchicine.png') 6224 6225 with open(fileN, 'rb') as inf: 6226 d = inf.read() 6227 mol = Chem.MolFromPNGString(d) 6228 nd = Chem.MolMetadataToPNGString(mol, d) 6229 vals = {'foo': '1', 'bar': '2'} 6230 nd = Chem.AddMetadataToPNGString(vals, nd) 6231 nvals = Chem.MetadataFromPNGString(nd) 6232 self.assertTrue('foo' in nvals) 6233 self.assertEqual(nvals['foo'], b'1') 6234 self.assertTrue('bar' in nvals) 6235 self.assertEqual(nvals['bar'], b'2') 6236 6237 nd = Chem.AddMetadataToPNGFile(vals, fileN) 6238 nvals = Chem.MetadataFromPNGString(nd) 6239 self.assertTrue('foo' in nvals) 6240 self.assertEqual(nvals['foo'], b'1') 6241 self.assertTrue('bar' in nvals) 6242 self.assertEqual(nvals['bar'], b'2') 6243 6244 vals = {'foo': 1, 'bar': '2'} 6245 with self.assertRaises(TypeError): 6246 nd = Chem.AddMetadataToPNGString(vals, d) 6247 6248 def test_github3403(self): 6249 core1 = "[$(C-!@[a])](=O)(Cl)" 6250 sma = Chem.MolFromSmarts(core1) 6251 6252 m = Chem.MolFromSmiles("c1ccccc1C(=O)Cl") 6253 self.assertFalse(m.HasSubstructMatch(sma, recursionPossible=False)) 6254 6255 m = Chem.MolFromSmiles("c1ccccc1C(=O)Cl") 6256 self.assertTrue(m.HasSubstructMatch(sma)) 6257 6258 m = Chem.MolFromSmiles("c1ccccc1C(=O)Cl") 6259 self.assertFalse(m.HasSubstructMatch(sma, recursionPossible=False)) 6260 6261 def test_github3517(self): 6262 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 6263 'NCI_aids_few.sdf') 6264 sdSup = Chem.SDMolSupplier(fileN) 6265 mols_list = list(sdSup) 6266 mols_list_compr = [m for m in sdSup] 6267 self.assertEqual(len(mols_list), len(mols_list_compr)) 6268 6269 def test_github3492(self): 6270 6271 def read_smile(s): 6272 m = Chem.MolFromSmiles(s) 6273 rdkit.Chem.rdDepictor.Compute2DCoords(m) 6274 return m 6275 6276 def sq_dist(a, b): 6277 ab = [a[i] - b[i] for i, _ in enumerate(a)] 6278 return sum([d * d for d in ab]) 6279 6280 self.assertIsNotNone(Chem.MolFromSmiles("OCCN").GetAtoms()[0].GetOwningMol()) 6281 self.assertEqual([Chem.MolFromSmiles("OCCN").GetAtoms()[i].GetAtomicNum() for i in range(4)], 6282 [8, 6, 6, 7]) 6283 self.assertIsNotNone(Chem.MolFromSmiles("O=CCC=N").GetBonds()[0].GetOwningMol()) 6284 self.assertEqual( 6285 [Chem.MolFromSmiles("O=CCC=N").GetBonds()[i].GetBondType() for i in range(4)], 6286 [Chem.BondType.DOUBLE, Chem.BondType.SINGLE, Chem.BondType.SINGLE, Chem.BondType.DOUBLE]) 6287 self.assertIsNotNone(read_smile("CCC").GetConformers()[0].GetOwningMol()) 6288 pos = read_smile("CCC").GetConformers()[0].GetPositions() 6289 self.assertAlmostEqual(sq_dist(pos[0], pos[1]), sq_dist(pos[1], pos[2])) 6290 6291 def test_github3553(self): 6292 from io import StringIO 6293 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'Wrap', 'test_data', 6294 'github3553.sdf') 6295 sdSup = Chem.SDMolSupplier(fileN) 6296 for mol in sdSup: 6297 pval = mol.GetProp('boiling.point.predicted') 6298 sio = StringIO() 6299 w = Chem.SDWriter(sio) 6300 w.SetKekulize(True) 6301 w.SetForceV3000(True) 6302 w.write(mol) 6303 w.flush() 6304 txt = sio.getvalue() 6305 self.assertTrue(pval in txt) 6306 6307 def test_github1631(self): 6308 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 6309 '1CRN.pdb') 6310 6311 m = Chem.MolFromPDBFile(fileN) 6312 info = m.GetAtomWithIdx(0).GetPDBResidueInfo() 6313 self.assertEqual(info.GetName(), " N ") 6314 self.assertEqual(info.GetResidueName(), "THR") 6315 self.assertAlmostEqual(info.GetTempFactor(), 13.79, 2) 6316 6317 m2 = Chem.MolFromSmiles('CC(C(C(=O)O)N)O') 6318 self.assertTrue(m2.GetAtomWithIdx(6).GetPDBResidueInfo() is None) 6319 m2.GetAtomWithIdx(6).SetPDBResidueInfo(info) 6320 info2 = m2.GetAtomWithIdx(6).GetPDBResidueInfo() 6321 self.assertEqual(info2.GetName(), " N ") 6322 self.assertEqual(info2.GetResidueName(), "THR") 6323 self.assertAlmostEqual(info2.GetTempFactor(), 13.79, 2) 6324 6325 def testMolzip(self): 6326 tests = [["C[*:1]", "N[*:1]", "CN", Chem.MolzipParams()]] 6327 for a, b, res, params in tests: 6328 self.assertEqual( 6329 Chem.CanonSmiles(res), 6330 Chem.MolToSmiles(Chem.molzip(Chem.MolFromSmiles(a), Chem.MolFromSmiles(b), params))) 6331 6332 # multiple arg test 6333 a = Chem.MolFromSmiles('C=C[1*]') 6334 b = Chem.MolFromSmiles('O/C=N/[1*]') 6335 p = Chem.MolzipParams() 6336 p.label = Chem.MolzipLabel.Isotope 6337 c = Chem.molzip(a, b, p) 6338 self.assertEqual(Chem.MolToSmiles(c), 'C=C/N=C/O') 6339 6340 # single argument test 6341 a = Chem.MolFromSmiles('C=C[1*].O/C=N/[1*]') 6342 p = Chem.MolzipParams() 6343 p.label = Chem.MolzipLabel.Isotope 6344 c = Chem.molzip(a, p) 6345 self.assertEqual(Chem.MolToSmiles(c), 'C=C/N=C/O') 6346 6347 def testContextManagers(self): 6348 from rdkit import RDLogger 6349 RDLogger.DisableLog('rdApp.*') 6350 from io import StringIO 6351 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'Wrap', 'test_data', 6352 'github3553.sdf') 6353 with Chem.SDMolSupplier(fileN) as suppl: 6354 mols = [x for x in suppl if x is not None] 6355 sio = StringIO() 6356 with Chem.SDWriter(sio) as w: 6357 for m in mols: 6358 w.write(m) 6359 txt = sio.getvalue() 6360 self.assertEqual(txt.count('$$$$'), len(mols)) 6361 with self.assertRaises(RuntimeError): 6362 w.write(mols[0]) 6363 6364 with Chem.ForwardSDMolSupplier(fileN) as suppl: 6365 mols = [x for x in suppl if x is not None] 6366 6367 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 6368 'first_200.tpsa.csv') 6369 with Chem.SmilesMolSupplier(fileN, ",", 0, -1) as suppl: 6370 ms = [x for x in suppl if x is not None] 6371 6372 sio = StringIO() 6373 with Chem.SmilesWriter(sio) as w: 6374 for m in mols: 6375 w.write(m) 6376 txt = sio.getvalue() 6377 self.assertEqual(txt.count('\n'), len(mols) + 1) 6378 with self.assertRaises(RuntimeError): 6379 w.write(mols[0]) 6380 6381 data = """$SMI<Cc1nnc(N)nc1C> 6382CAS<17584-12-2> 6383| 6384$SMI<Cc1n[nH]c(=O)nc1N> 6385CAS<~> 6386| 6387$SMI<Cc1n[nH]c(=O)[nH]c1=O> 6388CAS<932-53-6> 6389| 6390$SMI<Cc1nnc(NN)nc1O> 6391CAS<~> 6392|""" 6393 with Chem.TDTMolSupplier() as suppl: 6394 suppl.SetData(data, "CAS") 6395 ms = [x for x in suppl if x is not None] 6396 sio = StringIO() 6397 with Chem.TDTWriter(sio) as w: 6398 for m in mols: 6399 w.write(m) 6400 txt = sio.getvalue() 6401 self.assertEqual(txt.count('$SMI'), len(mols)) 6402 with self.assertRaises(RuntimeError): 6403 w.write(mols[0]) 6404 6405 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 6406 '1CRN.pdb') 6407 m = Chem.MolFromPDBFile(fileN) 6408 mols = [m, m] 6409 sio = StringIO() 6410 with Chem.PDBWriter(sio) as w: 6411 for m in mols: 6412 w.write(m) 6413 txt = sio.getvalue() 6414 self.assertEqual(txt.count('COMPND CRAMBIN'), len(mols)) 6415 with self.assertRaises(RuntimeError): 6416 w.write(mols[0]) 6417 6418 if hasattr(Chem, 'MaeMolSupplier'): 6419 fileN = os.path.join(RDConfig.RDBaseDir, 'Code', 'GraphMol', 'FileParsers', 'test_data', 6420 'NCI_aids_few.mae') 6421 with Chem.MaeMolSupplier(fileN) as suppl: 6422 ms = [x for x in suppl if x is not None] 6423 6424 RDLogger.EnableLog('rdApp.*') 6425 6426 def testInsertMol(self): 6427 m = Chem.MolFromSmiles("CNO") 6428 m2 = Chem.MolFromSmiles("c1ccccc1") 6429 m3 = Chem.MolFromSmiles("C1CC1") 6430 6431 rwmol = Chem.RWMol(m) 6432 rwmol.InsertMol(m2) 6433 rwmol.InsertMol(m3) 6434 self.assertEqual(Chem.MolToSmiles(rwmol), 6435 Chem.CanonSmiles("CNO.c1ccccc1.C1CC1")) 6436 6437 def testBatchEdits(self): 6438 mol = Chem.MolFromSmiles("C1CCCO1") 6439 6440 for rwmol in [Chem.EditableMol(mol), Chem.RWMol(mol)]: 6441 rwmol.BeginBatchEdit() 6442 rwmol.RemoveAtom(2) 6443 rwmol.RemoveAtom(3) 6444 rwmol.CommitBatchEdit() 6445 nmol = rwmol.GetMol() 6446 self.assertEqual(Chem.MolToSmiles(nmol), "CCO") 6447 6448 for rwmol in [Chem.EditableMol(mol), Chem.RWMol(mol)]: 6449 rwmol = Chem.EditableMol(mol) 6450 rwmol.BeginBatchEdit() 6451 rwmol.RemoveAtom(3) 6452 rwmol.RemoveBond(4, 0) 6453 rwmol.CommitBatchEdit() 6454 nmol = rwmol.GetMol() 6455 self.assertEqual(Chem.MolToSmiles(nmol), "CCC.O") 6456 6457 for rwmol in [Chem.EditableMol(mol), Chem.RWMol(mol)]: 6458 rwmol.BeginBatchEdit() 6459 rwmol.RemoveAtom(2) 6460 rwmol.RemoveAtom(3) 6461 rwmol.RollbackBatchEdit() 6462 nmol = rwmol.GetMol() 6463 self.assertEqual(Chem.MolToSmiles(nmol), "C1CCOC1") 6464 6465 def testBatchEditContextManager(self): 6466 mol = Chem.MolFromSmiles("C1CCCO1") 6467 with Chem.RWMol(mol) as rwmol: 6468 rwmol.RemoveAtom(2) 6469 rwmol.RemoveAtom(3) 6470 # make sure we haven't actually changed anything yet: 6471 self.assertEqual(rwmol.GetNumAtoms(), mol.GetNumAtoms()) 6472 self.assertEqual(rwmol.GetNumAtoms(), mol.GetNumAtoms() - 2) 6473 6474 # make sure no changes get made if we throw an exception 6475 try: 6476 with Chem.RWMol(mol) as rwmol: 6477 rwmol.RemoveAtom(2) 6478 rwmol.RemoveAtom(6) 6479 except: 6480 pass 6481 self.assertEqual(rwmol.GetNumAtoms(), mol.GetNumAtoms()) 6482 6483 def testGithub4138(self): 6484 m = Chem.MolFromSmiles('C1CCCO1') 6485 q = Chem.MolFromSmarts('') 6486 self.assertFalse(m.HasSubstructMatch(q)) 6487 self.assertEqual(m.GetSubstructMatch(q), ()) 6488 self.assertEqual(m.GetSubstructMatches(q), ()) 6489 6490 m = Chem.MolFromSmiles('') 6491 q = Chem.MolFromSmarts('C') 6492 self.assertFalse(m.HasSubstructMatch(q)) 6493 self.assertEqual(m.GetSubstructMatch(q), ()) 6494 self.assertEqual(m.GetSubstructMatches(q), ()) 6495 6496 def testGithub4144(self): 6497 ''' the underlying problem with #4144 was that the 6498 includeRings argument could not be passed to ClearComputedProps() 6499 from Python. Make sure that's fixed 6500 ''' 6501 m = Chem.MolFromSmiles('c1ccccc1') 6502 self.assertEqual(m.GetRingInfo().NumRings(), 1) 6503 m.ClearComputedProps(includeRings=False) 6504 self.assertEqual(m.GetRingInfo().NumRings(), 1) 6505 m.ClearComputedProps() 6506 with self.assertRaises(RuntimeError): 6507 m.GetRingInfo().NumRings() 6508 6509 6510if __name__ == '__main__': 6511 if "RDTESTCASE" in os.environ: 6512 suite = unittest.TestSuite() 6513 testcases = os.environ["RDTESTCASE"] 6514 for name in testcases.split(':'): 6515 suite.addTest(TestCase(name)) 6516 6517 runner = unittest.TextTestRunner() 6518 runner.run(suite) 6519 else: 6520 unittest.main() 6521