def test_add_atom_map(toolkit): smiles = 'CCCC' mol = utils.load_molecule(smiles, toolkit=toolkit, strict=False) mapped_mol = utils.add_atom_map(mol, in_place=False) assert utils.has_atom_map(mapped_mol) assert not utils.has_atom_map(mol) assert not utils.is_missing_atom_map(mapped_mol) assert utils.is_missing_atom_map(mol)
def test_remove_restore_atom_map(toolkit): mapped_smiles = '[H:5][C:1]([H:6])([C:2]([H:7])([H:8])[O:4][H:10])[O:3][H:9]' mapped_mol = utils.load_molecule(mapped_smiles, toolkit=toolkit) utils.remove_atom_map(mapped_mol) assert utils.has_atom_map(mapped_mol) == False assert utils.is_missing_atom_map(mapped_mol) == True utils.restore_atom_map(mapped_mol) assert utils.has_atom_map(mapped_mol) == True assert utils.is_missing_atom_map(mapped_mol) == False smiles = 'OCCO' mol = utils.load_molecule(smiles, toolkit=toolkit) with pytest.warns(UserWarning): utils.restore_atom_map(mol)
def find_equivelant_torsions(mapped_mol, restricted=False, central_bonds=None): """ Final all torsions around a given central bond Parameters ---------- mapped_mol: oemol. Must contaion map indices restricted: bool, optional, default False If True, will also find restricted torsions central_bonds: list of tuple of ints, optional, defualt None If provides, only torsions around those central bonds will be given. If None, all torsions in molecule will be found Returns ------- eq_torsions: dict maps central bond to all equivelant torisons """ #ToDo check that mol has mapping from openeye import oechem mol = oechem.OEMol(mapped_mol) if not has_atom_map(mol): raise ValueError("OEMol must have map indices") terminal_smarts = '[*]~[*]-[X2H1,X3H2,X4H3]-[#1]' terminal_torsions = _find_torsions_from_smarts(mol, terminal_smarts) mid_torsions = [[tor.a, tor.b, tor.c, tor.d] for tor in oechem.OEGetTorsions(mapped_mol)] all_torsions = terminal_torsions + mid_torsions if restricted: restricted_smarts = '[*]~[C,c]=,@[C,c]~[*]' restricted_torsions = _find_torsions_from_smarts(mol, restricted_smarts) all_torsions = all_torsions + restricted_torsions tor_idx = [] for tor in all_torsions: tor_name = (tor[0].GetMapIdx()-1, tor[1].GetMapIdx()-1, tor[2].GetMapIdx()-1, tor[3].GetMapIdx()-1) tor_idx.append(tor_name) if central_bonds: if not isinstance(central_bonds, list): central_bonds = [central_bonds] if not central_bonds: central_bonds = set((tor[1], tor[2]) for tor in tor_idx) eq_torsions = {cb : [tor for tor in tor_idx if cb == (tor[1], tor[2]) or cb ==(tor[2], tor[1])] for cb in central_bonds} return eq_torsions
def find_torsion_around_bond(molecule, bond): """ Find the torsion around a given bond Parameters ---------- molecule : molecule with atom maps bond : tuple of map idx of bond atoms Returns ------- list of 4 atom map idx (-1) Note: This returns the map indices of the torsion -1, not the atom indices. """ from openeye import oechem if not has_atom_map(molecule): raise ValueError("Molecule must have atom maps") #torsions = [[tor.a, tor.b, tor.c, tor.d ] for tor in oechem.OEGetTorsions(molecule)] terminal_smarts = '[*]~[*]-[X2H1,X3H2,X4H3]-[#1]' terminal_torsions = _find_torsions_from_smarts(molecule, terminal_smarts) mid_torsions = [[tor.a, tor.b, tor.c, tor.d] for tor in oechem.OEGetTorsions(molecule)] all_torsions = terminal_torsions + mid_torsions tors = one_torsion_per_rotatable_bond(all_torsions) tor_idx = [tuple(i.GetMapIdx() for i in tor) for tor in tors] central_bonds = [(tor[1], tor[2]) for tor in tor_idx] try: idx = central_bonds.index(bond) except ValueError: idx = central_bonds.index(tuple(reversed(bond))) torsion = [i-1 for i in tor_idx[idx]] return torsion
def find_torsions(molecule, restricted=True, terminal=True): #ToDo: Get rid of equivalent torsions. Ex H-C-C-C and C-C-C-H. """ This function takes an OEMol (atoms must be tagged with index map) and finds the map indices for torsion that need to be driven. Parameters ---------- molecule : OEMol The atoms in the molecule need to be tagged with map indices restricted: bool, optional, default True If True, will find restricted torsions such as torsions in rings and double bonds. terminal: bool, optional, default True If True, will find terminal torsions Returns ------- needed_torsion_scans: dict a dictionary that maps internal, terminal and restricted torsions to map indices of torsion atoms """ # Check if molecule has map from openeye import oechem is_mapped = has_atom_map(molecule) if not is_mapped: utils.logger().warning('Molecule does not have atom map. A new map will be generated. You might need a new tagged SMARTS if the ordering was changed') tagged_smiles = mol_to_smiles(molecule, isomeric=True, mapped=True, explicit_hydrogen=True) # Generate new molecule with tags molecule = chemi.smiles_to_oemol(tagged_smiles) utils.logger().warning('If you already have a tagged SMARTS, compare it with the new one to ensure the ordering did not change') utils.logger().warning('The new tagged SMARTS is: {}'.format(tagged_smiles)) # ToDo: save the new tagged SMILES somewhere. Maybe return it? needed_torsion_scans = {'internal': {}, 'terminal': {}, 'restricted': {}} mol = oechem.OEMol(molecule) if restricted: smarts = '[*]~[C,c]=,@[C,c]~[*]' # This should capture double bonds (not capturing rings because OpenEye does not # generate skewed conformations. ToDo: use scan in geometric or something else to get this done. restricted_tors = _find_torsions_from_smarts(molecule=mol, smarts=smarts) if len(restricted_tors) > 0: restricted_tors_min = one_torsion_per_rotatable_bond(restricted_tors) for i, tor in enumerate(restricted_tors_min): tor_name = ((tor[0].GetMapIdx() - 1), (tor[1].GetMapIdx() - 1), (tor[2].GetMapIdx() - 1), (tor[3].GetMapIdx() - 1)) needed_torsion_scans['restricted']['torsion_{}'.format(str(i))] = tor_name if terminal: smarts = '[*]~[*]-[X2H1,X3H2,X4H3]-[#1]' # This smarts should match terminal torsions such as -CH3, -NH2, -NH3+, -OH, and -SH h_tors = _find_torsions_from_smarts(molecule=mol, smarts=smarts) if len(h_tors) > 0: h_tors_min = one_torsion_per_rotatable_bond(h_tors) for i, tor in enumerate(h_tors_min): tor_name = ((tor[0].GetMapIdx() -1 ), (tor[1].GetMapIdx() - 1), (tor[2].GetMapIdx() - 1), (tor[3].GetMapIdx() - 1)) needed_torsion_scans['terminal']['torsion_{}'.format(str(i))] = tor_name mid_tors = [[tor.a, tor.b, tor.c, tor.d ] for tor in oechem.OEGetTorsions(mol)] if mid_tors: mid_tors_min = one_torsion_per_rotatable_bond(mid_tors) for i, tor in enumerate(mid_tors_min): tor_name = ((tor[0].GetMapIdx() - 1), (tor[1].GetMapIdx() - 1), (tor[2].GetMapIdx() - 1), (tor[3].GetMapIdx() - 1)) needed_torsion_scans['internal']['torsion_{}'.format(str(i))] = tor_name # Check that there are no duplicate torsions in mid and h_torsions list_tor = list(needed_torsion_scans['internal'].values()) + list(needed_torsion_scans['terminal'].values()) set_tor = set(list_tor) if not len(set_tor) == len(list_tor): raise Warning("There is a torsion defined in both mid and terminal torsions. This should not happen. Check " "your molecule and the atom mapping") return needed_torsion_scans
def test_is_mapped(toolkit, input, output): """Test is mapped""" mapped_mol = utils.load_molecule(input, toolkit=toolkit) assert utils.has_atom_map(mapped_mol) == output utils.remove_atom_map(mapped_mol) assert utils.has_atom_map(mapped_mol) == False