def nonpher(rdmol, max_steps=30): """ Generator of random morphs """ mol = MolpherMol(rdmol) step = 0 operators = [ AddAtom(), AddBond(), ContractBond(), InterlayAtom(), MutateAtom(), RemoveBond(), RerouteBond(), RemoveAtom(), ] molpher = Molpher(mol, operators, attempts=1) while step < max_steps: molpher() new_morphs = molpher.getMorphs() if len(new_morphs) > 0: molpher.reset(new_morphs[0]) step += 1 yield new_morphs[0].asRDMol()
def testMorphingWithLocks(self): tree = ExplorationTree.create(source=MolpherMol(self.captopril)) # generate two generations of morphs and save them all to a list morphs = [] def some_collector(morph, operator): self.assertTrue(operator.name) self.assertTrue(morph.smiles) morphs.append((morph, operator)) gen_morphs = GenerateMorphsOper(collectors=[some_collector]) tree.runOperation(gen_morphs) tree.sortMorphs() tree.filterMorphs() tree.extend() tree.runOperation(gen_morphs) tree.extend() # check if all generated morphs satisfy some conditions locked_pattern = Chem.MolFromSmarts('C(=O)N1CCCC1C(=O)O') for x in morphs: self.assertTrue(x[0].smiles) self.assertTrue(x[1].name) self.assertTrue(x[0].asRDMol().HasSubstructMatch(locked_pattern))
def testRemoveBondOperator(self): test_mol = MolpherMol(self.remove_bond_test_mol) remove_bond = RemoveBond() self.assertOperatorValid(remove_bond, test_mol) remove_bond.setOriginal(test_mol) open_bonds = remove_bond.getOpenBonds() self.assertIsInstance(open_bonds, tuple)
def testAddBondOperator(self): propanol = MolpherMol(self.propanol) add_bond = AddBond() self.assertOperatorValid(add_bond, propanol) add_bond.setOriginal(propanol) open_bonds = add_bond.getOpenBonds() self.assertIsInstance(open_bonds, tuple)
def assertOperatorValid(self, operator, test_mol, gens=10): print("Testing operator:", operator) if not operator.getOriginal(): self.assertRaises(RuntimeError, operator.setOriginal, None) self.assertRaises(RuntimeError, operator.morph) mol = MolpherMol(self.propanol) operator.setOriginal(mol) orig = operator.getOriginal() self.assertIsNotNone(orig) self.assertIsInstance(orig, MolpherMol) self.assertEqual(orig.getSMILES(), mol.getSMILES()) operator.setOriginal(test_mol) for x in range(gens): mol = operator.morph() if mol: self.assertIsInstance(mol, MolpherMol) print(mol.smiles) operator.setOriginal(mol)
def assertOperatorValid(self, operator, test_mol, gens = 10): print("Testing operator:", operator) if not operator.getOriginal(): self.assertRaises(RuntimeError, operator.setOriginal, None) self.assertRaises(RuntimeError, operator.morph) mol = MolpherMol(self.propanol) operator.setOriginal(mol) orig = operator.getOriginal() self.assertIsNotNone(orig) self.assertIsInstance(orig, MolpherMol) self.assertEqual(orig.getSMILES(), mol.getSMILES()) operator.setOriginal(test_mol) for x in range(gens): mol = operator.morph() if mol: self.assertIsInstance(mol, MolpherMol) print(mol.smiles) operator.setOriginal(mol)
def testMolpherMol(self): mol = MolpherMol(self.test_target) self.assertTrue(mol.asRDMol()) self.assertTrue(mol.asMolBlock()) mol.smiles = 'CCC' self.assertEqual(mol.getSMILES(), 'CCC') copy = mol.copy() copy.sascore = 0.54 self.assertEqual(0.54, copy.sascore) tree = ExplorationTree.create(source=mol.smiles, target='CCCNCCC') tree = ExplorationTree.create(source=mol, target='CCCNCCC') tree = ExplorationTree.create(source=mol, target=MolpherMol('CCCNCCC')) self.assertTrue(tree.hasMol(mol)) def assign(x): tree.fetchMol(mol.smiles).smiles = x self.assertRaises(RuntimeError, assign, 'CCO') # atom locking stuff mol_locked = MolpherMol(self.cymene_locked) open_positions = (0, 2, 3, 9) for idx, atom in enumerate(mol_locked.atoms): if not atom.is_locked: self.assertIn(idx, open_positions) else: self.assertTrue(atom.lock_info['NO_ADDITION']) self.assertFalse(atom.lock_info['UNLOCKED']) self.assertFalse(atom.lock_info['FULL_LOCK']) # test RDKit conversion and locking information transfer rd_mol = mol_locked.asRDMol() output = None if sys.version_info[0] < 3: output = BytesIO() else: output = StringIO() writer = Chem.SDWriter(output) writer.write(rd_mol) writer.close() temp_path = self.test_dir + "/cymene_tmp.sdf" with open(temp_path, "w") as tempfile: tempfile.write(output.getvalue()) new_cymene = MolpherMol(temp_path) os.remove(temp_path) for atm_old, atm_new in zip(mol_locked.atoms, new_cymene.atoms): self.assertTrue(atm_old.locking_mask == atm_new.locking_mask) # test init from RDKit mol_from_rdkit = MolpherMol(other=rd_mol) for atm_old, atm_new in zip(mol_locked.atoms, mol_from_rdkit.atoms): self.assertTrue(atm_old.locking_mask == atm_new.locking_mask)
def testMolpher(self): cymene = MolpherMol(self.cymene_locked) operators = [AddAtom(), RemoveAtom()] molpher = Molpher(cymene, operators) molpher() morphs = molpher.getMorphs() self.assertTrue(morphs) self.assertFalse(molpher.getMorphs()) morphs = [] while len(morphs) < 50: morphs.append(molpher.next()) self.assertEqual(50, len(morphs))
def testMorphingOperator(self): class Identity(MorphingOperator): def morph(self): return self.original.copy() def getName(self): return "Identity" cymene = MolpherMol(self.cymene_locked) operators = [Identity()] molpher = Molpher(cymene, operators) molpher() for morph in molpher.getMorphs(): self.assertEqual(morph.smiles, cymene.smiles)
def morph(self): combo_mol = Chem.EditableMol(Chem.CombineMols( self._orig_rdkit , self._fragment )) atom_orig = self._open_atoms[get_random_number(0, len(self._open_atoms)-1)] atom_frag = len(self.original.atoms) + self._open_atoms_frag[get_random_number(0, len(self._open_atoms_frag)-1)] combo_mol.AddBond(atom_orig, atom_frag, order=Chem.rdchem.BondType.SINGLE) combo_mol = combo_mol.GetMol() Chem.SanitizeMol(combo_mol) ret = MolpherMol(other=combo_mol) for atm_ret, atm_orig in zip(ret.atoms, self.original.atoms): atm_ret.locking_mask = atm_orig.locking_mask return ret
""" rd_morph = morph.asRDMol() if not rd_morph.HasSubstructMatch(strange_patterns): sensible_morphs[morph.smiles] = morph morph.parent_operator = operator.getName() # create some AddFragment operators fragments = ['c1ccccc1', 'C(=O)O'] add_frags = [] for frag in fragments: add_frag = AddFragment(Chem.MolFromSmiles(frag), [0], "Add " + frag) add_frags.append(add_frag) # load a molecule from SDF and generate some derived molecules with given morphing operators mol = MolpherMol("captopril.sdf") molpher = Molpher( mol , [ # list of morphing operators to use AddAtom() , RemoveAtom() , MutateAtom() , AddBond() , RemoveBond() , ContractBond() , InterlayAtom() , RerouteBond() ] + add_frags # add our custom operators, too , attempts = 100 # create at most 100 molecules , collectors = [collect_sensible] )
def testInterlayAtomOperator(self): self.assertOperatorValid(InterlayAtom(), MolpherMol(self.isopropylphenol))
def testAddAtomOperator(self): cymene_no_add = MolpherMol(self.cymene_locked) add_atom = AddAtom() self.assertOperatorValid(add_atom, cymene_no_add)
def testMutateAtomOperator(self): self.assertOperatorValid(MutateAtom(), MolpherMol(self.isopropylphenol))
def testRerouteBondOperator(self): self.assertOperatorValid(ContractBond(), MolpherMol(self.contract_bond_test_mol))
def testContractBondOperator(self): self.assertOperatorValid(RerouteBond(), MolpherMol(self.reroute_test_mol))