def fixup(atoms, mol, struct): '''Set atom properties to match channel. Keep doing this to beat openbabel over the head with what we want to happen.''' mol.SetAromaticPerceived(True) #avoid perception for atom, t in zip(atoms, struct.c): ch = struct.channels[t] if 'Aromatic' in ch.name: atom.SetAromatic(True) for nbr in openbabel.OBAtomAtomIter(atom): if nbr.IsAromatic(): bond = atom.GetBond(nbr) bond.SetAromatic() if 'Donor' in ch.name: if atom.GetTotalDegree() - atom.GetHvyDegree() <= 0: atom.SetImplicitHCount( 1 ) # this is nice in theory, but connectthedots is going to ignore implicit valances elif 'Acceptor' in ch.name: # NOT AcceptorDonor because of else atom.SetImplicitHCount(0) if False and 'Nitrogen' in ch.name and atom.IsInRing(): #this is a little iffy, ommitting until there is more evidence it is a net positive #we don't have aromatic types for nitrogen, but if it #is in a ring with aromatic carbon mark it aromatic as well acnt = 0 for nbr in openbabel.OBAtomAtomIter(atom): if nbr.IsAromatic(): acnt += 1 if acnt > 1: atom.SetAromatic(True)
def find_C_cap(self): for atom in ob.OBAtomAtomIter(self.CTerminus): if atom.GetAtomicNum() == 7: self.CTermCap.AddAtom(atom) for n_atom in ob.OBAtomAtomIter(atom): if not OBAminoAcid.Equals(self.CTerminus, n_atom): self.CTermCap.AddAtom(n_atom) for n_atom2 in ob.OBAtomAtomIter(n_atom): if n_atom2.GetAtomicNum() == 1: self.CTermCap.AddAtom(n_atom2)
def find_termini(self): for atom1 in ob.OBMolAtomIter(self.mol): if atom1.GetAtomicNum() == 7: for atom2 in ob.OBAtomAtomIter(atom1): if atom2.GetAtomicNum() == 6: for atom3 in ob.OBAtomAtomIter(atom2): if atom3.GetAtomicNum() == 6: for atom4 in ob.OBAtomAtomIter(atom3): if atom4.GetAtomicNum( ) == 8 and atom3.GetBond( atom4).GetBondOrder() == 2: self.NTerminus = atom1 self.CTerminus = atom3 return
def IsProtein(mol, big_mol): for atom1 in ob.OBMolAtomIter(big_mol): if OBLigand.IsInMolecule(atom1, mol): if atom1.GetAtomicNum() == 7: for atom2 in ob.OBAtomAtomIter(atom1): if atom2.GetAtomicNum() == 6: for atom3 in ob.OBAtomAtomIter(atom2): if atom3.GetAtomicNum() == 6: for atom4 in ob.OBAtomAtomIter(atom3): if atom4.GetAtomicNum( ) == 8 and atom3.GetBond( atom4).GetBondOrder() == 2: return True return False
def fixup(atoms, mol, struct): '''Set atom properties to match channel. Keep doing this to beat openbabel over the head with what we want to happen.''' mol.SetAromaticPerceived(True) #avoid perception for atom, t in zip(atoms, struct.c): ch = struct.channels[t] if 'Aromatic' in ch.name: atom.SetAromatic(True) atom.SetHyb(2) if 'Donor' in ch.name: if atom.GetExplicitDegree() == atom.GetHvyDegree(): if atom.GetHvyDegree() == 1 and atom.GetAtomicNum() == 7: atom.SetImplicitHCount(2) else: atom.SetImplicitHCount(1) elif 'Acceptor' in ch.name: # NOT AcceptorDonor because of else atom.SetImplicitHCount(0) if ('Nitrogen' in ch.name or 'Oxygen' in ch.name) and atom.IsInRing(): #this is a little iffy, ommitting until there is more evidence it is a net positive #we don't have aromatic types for nitrogen, but if it #is in a ring with aromatic carbon mark it aromatic as well acnt = 0 for nbr in ob.OBAtomAtomIter(atom): if nbr.IsAromatic(): acnt += 1 if acnt > 1: atom.SetAromatic(True)
def _calc_di(self, idx, atom): """ """ # keep track of equivalent groups, and mark the first one # to be used as main self._equivalents[idx] = [] if not idx in self._equivalents: if idx in self.automorphs: if len(set(self._equivalents.keys()) & self.automorphs[idx]) == 0: self._equivalents[idx] = self.automorphs[idx] else: self._equivalents[idx] = set() if idx in self.automorphs: for u in self.automorphs[idx]: self._equivalents[idx].append(u) # count how many non-equivalent neighbors there are for atom groups = [] for neigh in ob.OBAtomAtomIter(atom): if self._is_hydrogen(neigh.GetIdx()): continue neigh_idx = neigh.GetIdx() if (neigh_idx in self.automorphs): if len(set(groups) & self.automorphs[neigh_idx]) > 0: continue groups.append(neigh_idx) self._indices[idx]['di'] = len(groups)
def obatom_to_smina_type(self, ob_atom): """Original author: Constantin schneider""" atomic_number = ob_atom.atomicnum num_to_name = {1: 'HD', 6: 'A', 7: 'NA', 8: 'OA', 16: 'SA'} # Default fn returns True, otherwise inspect atom properties condition_fns = defaultdict(lambda: lambda: True) condition_fns.update({ 6: ob_atom.OBAtom.IsAromatic, 7: ob_atom.OBAtom.IsHbondAcceptor, 16: ob_atom.OBAtom.IsHbondAcceptor }) # Get symbol ename = openbabel.GetSymbol(atomic_number) # Do we need to adjust symbol? if condition_fns[atomic_number](): ename = num_to_name.get(atomic_number, ename) atype = self.string_to_smina_type(ename) h_bonded = False hetero_bonded = False for neighbour in openbabel.OBAtomAtomIter(ob_atom.OBAtom): if neighbour.GetAtomicNum() == 1: h_bonded = True elif neighbour.GetAtomicNum() != 6: hetero_bonded = True return self.adjust_smina_type(atype, h_bonded, hetero_bonded)
def SideChainGrowerRecursive(atom, mol, cmol): for n_atom in ob.OBAtomAtomIter(atom): print(atom.GetAtomicNum(), n_atom.GetAtomicNum(), OBAminoAcid.IsInMolecule(n_atom, mol)) if not OBAminoAcid.IsInMolecule(n_atom, mol): mol.AddAtom(n_atom) cmol.AddAtom(n_atom) OBAminoAcid.SideChainGrower(n_atom, mol, cmol)
def MolGrowerHelper(atom, mol): count = 0 for n_atom in ob.OBAtomAtomIter(atom): #print(atom.GetAtomicNum(), n_atom.GetAtomicNum(), OBLigand.IsInMolecule(n_atom, mol)) if not OBLigand.IsInMolecule(n_atom, mol): mol.AddAtom(n_atom) count += 1 return count
def SetResiduesPerceived(self): self.residues = [] count = 0 for atom1 in ob.OBMolAtomIter(self.mol): if atom1.GetAtomicNum() == 7: for atom2 in ob.OBAtomAtomIter(atom1): if atom2.GetAtomicNum() == 6: for atom3 in ob.OBAtomAtomIter(atom2): if atom3.GetAtomicNum() == 6: for atom4 in ob.OBAtomAtomIter(atom3): #print(atom4.GetAtomicNum(), atom3.GetBond(atom4).GetBondOrder()) if atom4.GetAtomicNum( ) == 8 and atom3.GetBond( atom4).GetBondOrder() == 2: count += 1 self.residues.append( OBAminoAcid( self, count, atom1, atom3))
def forms_small_angle(a, b, cutoff=45): '''Return true if bond between a and b is part of a small angle with a neighbor of a only.''' for nbr in ob.OBAtomAtomIter(a): if nbr != b: degrees = b.GetAngle(a, nbr) if degrees < cutoff: return True return False
def count_nbrs_of_elem(atom, atomic_num): ''' Count the number of neighbors atoms of atom with the given atomic_num. ''' count = 0 for nbr in ob.OBAtomAtomIter(atom): if nbr.GetAtomicNum() == atomic_num: count += 1 return count
def find_N_cap(self): a1 = ob.OBAtom() for atom in ob.OBAtomAtomIter(self.NTerminus): if atom.GetAtomicNum() == 6: for n_atom in ob.OBAtomAtomIter(atom): if n_atom.GetAtomicNum() == 8 and atom.GetBond( n_atom).GetBondOrder() == 2: self.NTermCap.AddAtom(atom) self.NTermCap.AddAtom(n_atom) a1 = atom for atom in ob.OBAtomAtomIter(self.NTerminus): if OBAminoAcid.Equals(atom, a1): for atom1 in ob.OBAtomAtomIter(atom): if atom1.GetAtomicNum() == 6: self.NTermCap.AddAtom(atom1) for n_atom1 in ob.OBAtomAtomIter(atom1): if not OBAminoAcid.Equals(n_atom1, atom): self.NTermCap.AddAtom(n_atom1)
def forms_small_angle(atom_a, atom_b, cutoff=45): ''' Return whether bond between atom_a and atom_b is part of a small angle with a neighbor of a only. ''' for nbr in ob.OBAtomAtomIter(atom_a): if nbr != atom_b: degrees = atom_b.GetAngle(atom_a, nbr) if degrees < cutoff: return True return False
def IsConnectedTo(atom, mol, big_mol): if OBLigand.IsInMolecule(atom, mol): return False for mol_atom in ob.OBMolAtomIter(big_mol): if OBLigand.IsInMolecule(mol_atom, mol): for n_atom in ob.OBAtomAtomIter(mol_atom): if OBLigand.Equals(n_atom, atom): return True return False
def SideChainGrowerHelper(atom, mol, cmol): count = 0 for n_atom in ob.OBAtomAtomIter(atom): print(atom.GetAtomicNum(), n_atom.GetAtomicNum(), OBAminoAcid.IsInMolecule(n_atom, mol)) if not OBAminoAcid.IsInMolecule(n_atom, mol) and not ( atom.GetAtomicNum() == 16 and n_atom.GetAtomicNum() == 16): mol.AddAtom(n_atom) cmol.AddAtom(n_atom) count += 1 return count
def reachable_r(a, b, seenbonds): '''Recursive helper.''' for nbr in ob.OBAtomAtomIter(a): bond = a.GetBond(nbr).GetIdx() if bond not in seenbonds: seenbonds.add(bond) if nbr == b: return True elif reachable_r(nbr, b, seenbonds): return True return False
def get_connect_info(self): """Grab all the atoms which are flagged by this program to be connectivity points. Namely, Xe, Y, and Rn. Ac series elements are replacement Xe atoms for special bonding purposes. """ special, remove = [], [] connect_index = 0 for ind, atom in enumerate(ob.OBMolAtomIter(self.mol)): N = atom.GetAtomicNum() if N == 54 or (N >= 89 and N <= 102): connect_index += 1 con_line = "%4i " % (connect_index) X = "%12.4f %8.4f %8.4f" % (atom.GetX(), atom.GetY(), atom.GetZ()) if (N >= 89 and N <= 102): special.append((connect_index, N % 89 + 1)) net_vector, bond_vector = "", "" for neighbour in ob.OBAtomAtomIter(atom): x = neighbour.GetX() - atom.GetX() y = neighbour.GetY() - atom.GetY() z = neighbour.GetZ() - atom.GetZ() if neighbour.GetAtomicNum() == 39: net_atom = neighbour net_vector = "%12.4f %8.4f %8.4f" % (x, y, z) remove.append(net_atom) elif neighbour.GetAtomicNum() == 86: bond_atom = neighbour bond_vector = "%12.4f %8.4f %8.4f" % (x, y, z) remove.append(bond_atom) else: #TEMP if Rn does not exist bond_vector = "%12.4f %8.4f %8.4f" % (-x, -y, -z) neighbour.SetFormalCharge(connect_index) id = neighbour.GetIdx() con_line += "".join([X, bond_vector, net_vector, "\n"]) self.update(connectivity=con_line) remove.append(atom) self._remove_atoms(*remove) # include special considerations for (i, spec) in special: if spec == 2: bond_partner = 1 elif spec == 1: bond_partner = 2 else: bond_partner = 0 const_line = '%5i%5i%5i\n' % (i, spec, bond_partner) self.update(connect_flag=const_line)
def test_atom_iteration(self): mol = parse_smiles("[U](F)(F)(F)[Cl]") atom = mol.GetAtom(1) counts = {9: 0, 17: 0} for bond in ob.OBAtomBondIter(atom): xatom = bond.GetNbrAtom(atom) n = xatom.GetAtomicNum() counts[n] += 1 self.assertEqual(counts, {9: 3, 17: 1}) counts = {9: 0, 17: 0} for atom in ob.OBAtomAtomIter(atom): n = atom.GetAtomicNum() counts[n] += 1 self.assertEqual(counts, {9: 3, 17: 1})
def reachable_r(curr_atom, goal_atom, avoid_bond, visited_atoms): ''' Recursive helper for determining whether goal_atom is reachable from curr_atom without using avoid_bond. ''' for nbr_atom in ob.OBAtomAtomIter(curr_atom): curr_bond = curr_atom.GetBond(nbr_atom) nbr_atom_idx = nbr_atom.GetIdx() if not compare_bonds(curr_bond, avoid_bond) and nbr_atom_idx not in visited_atoms: visited_atoms.add(nbr_atom_idx) if nbr_atom == goal_atom: return True elif reachable_r(nbr_atom, goal_atom, avoid_bond, visited_atoms): return True return False
def CapC(resMol): resMol.AddAtom(NTerminus(protein, resNumber + 1)) resMol.AddAtom(AlphaCarbon(protein, resNumber + 1)) hasH = False for atom in ob.OBAtomAtomIter(NTerminus(protein, resNumber + 1)): if atom.GetAtomicNum() == 1: resMol.AddAtom(atom) hasH = True if not hasH: atom = GetAtomByID(protein, resNumber + 1, ' CD ') if atom is not None: atom.SetAtomicNum(1) origin = np.array([ NTerminus(protein, resNumber + 1).GetX(), NTerminus(protein, resNumber + 1).GetY(), NTerminus(protein, resNumber + 1).GetZ() ], dtype=float) vector = np.array( [atom.GetX(), atom.GetY(), atom.GetZ()], dtype=float) - origin vector = 1.01 * vector / np.linalg.norm(vector) vector = origin + vector atom.SetVector(vector[0], vector[1], vector[2]) resMol.AddAtom(atom) resMol = Hydrogenate(AlphaCarbon(protein, resNumber + 1), NTerminus(protein, resNumber + 1), resMol)
def _calc_bi_ei_si(self, idx, atom): """ calculate atomic Bi (bond), Ei (equivalence/symmetry) and Si (chirality/asymmetry) terms """ bi = 0 ei = [self._get_atomic_num(atom)] si = 1 if atom.IsChiral(): si += 1 for neigh in ob.OBAtomAtomIter(atom): neigh_idx = neigh.GetIdx() if self._is_hydrogen(neigh_idx): continue if idx in self._mesomery_equivalence: # use mesomeric-corrected bond order contribution = self._mesomery_equivalence[idx] else: # get bond order bond = self.mol.GetBond(atom, neigh) contribution = bond.GetBondOrder() bi += contribution # get neighbor element ei.append(self._get_atomic_num(neigh)) self._indices[idx]['bi'] = bi self._indices[idx]['ei'] = len(set(ei)) self._indices[idx]['si'] = si
def find_alpha_hydrogen(self): for atom in ob.OBAtomAtomIter(self.AlphaCarbon): if atom.GetAtomicNum() == 1: self.AlphaHydrogen = atom return
def __init__(self, protein, residueNumber, NTerminus, CTerminus): self.protein = protein self.residueNumber = residueNumber self.NTerminus = NTerminus self.CTerminus = CTerminus self.resMol = ob.OBMol() self.sideChain = ob.OBMol() self.NTermCap = ob.OBMol() self.CTermCap = ob.OBMol() self.resMol.AddAtom(NTerminus) self.resMol.AddAtom(CTerminus) for atomN in ob.OBAtomAtomIter(NTerminus): for atomC in ob.OBAtomAtomIter(CTerminus): if OBAminoAcid.Equals(atomN, atomC): self.AlphaCarbon = atomC self.resMol.AddAtom(atomC) for atom in ob.OBAtomAtomIter(NTerminus): if atom.GetAtomicNum() == 1: self.resMol.AddAtom(atom) for atom in ob.OBAtomAtomIter(CTerminus): if atom.GetAtomicNum() == 8 and atom.GetBond( CTerminus).GetBondOrder() == 2: self.resMol.AddAtom(atom) for atom in ob.OBAtomAtomIter(self.AlphaCarbon): if atom.GetAtomicNum() == 1: self.resMol.AddAtom(atom) self.AlphaHydrogen = atom break for atom in ob.OBAtomAtomIter(self.AlphaCarbon): if not (OBAminoAcid.Equals(atom, self.NTerminus) or OBAminoAcid.Equals(atom, self.CTerminus) or OBAminoAcid.Equals(atom, self.AlphaHydrogen)): self.resMol.AddAtom(atom) self.sideChain.AddAtom(atom) print(self.residueNumber) OBAminoAcid.SideChainGrowerIterative(self.protein.mol, self.resMol, self.sideChain) hasDisulfide = False for atom in ob.OBMolAtomIter(self.protein.mol): print( F'{atom.GetAtomicNum()},BOSum: {OBAminoAcid.BondOrderSum(atom)}' ) if atom.GetAtomicNum() == 16 and OBAminoAcid.IsInMolecule( atom, self.resMol): for n_atom in ob.OBAtomAtomIter(atom): if n_atom.GetAtomicNum() == 16: hasDisulfide = True if hasDisulfide: for atom in ob.OBMolAtomIter(self.protein.mol): if atom.GetAtomicNum() == 16 and OBAminoAcid.IsInMolecule( atom, self.resMol): for n_atom in ob.OBAtomAtomIter(atom): if n_atom.GetAtomicNum() == 6: self.resMol = OBAminoAcid.SulfurHydrogenator( atom, n_atom, self.resMol) self.sideChain = OBAminoAcid.SulfurHydrogenator( atom, n_atom, self.sideChain) #Set the Residue Name of the Amino Acid countH = 0 countC = 0 countN = 0 countO = 0 countS = 0 for atom in ob.OBMolAtomIter(self.sideChain): if atom.GetAtomicNum() == 1: countH += 1 elif atom.GetAtomicNum() == 6: countC += 1 elif atom.GetAtomicNum() == 7: countN += 1 elif atom.GetAtomicNum() == 8: countO += 1 elif atom.GetAtomicNum() == 16: countS += 1 countTuple = (countH, countC, countN, countO, countS) if countTuple == (1, 0, 0, 0, 0): self.name = "GLY" elif countTuple == (3, 1, 0, 0, 0): self.name = "ALA" elif countTuple == (7, 3, 0, 0, 0): self.name = "VAL" elif countTuple == (9, 4, 0, 0, 0): carbonCount = 0 for atom in ob.OBAtomAtomIter(self.AlphaCarbon): if OBAminoAcid.IsInMolecule(atom, self.sideChain): for n_atom in ob.OBAtomAtomIter(atom): if n_atom.GetAtomicNum() == 6: carbonCount += 1 if carbonCount == 2: self.name = "LEU" elif carbonCount == 3: self.name = "ILE" elif countTuple == (7, 3, 0, 0, 1): self.name = "MET" elif countTuple == (7, 7, 0, 0, 0): self.name = "PHE" elif countTuple == (8, 9, 1, 0, 0): self.name = "TRP" elif countTuple == (6, 3, 0, 0, 0): self.name = "PRO" elif countTuple == (3, 1, 0, 1, 0): self.name = "SER" elif countTuple == (5, 2, 0, 1, 0): self.name = "THR" elif countTuple == (7, 7, 0, 1, 0): self.name = "TYR" elif countTuple == (3, 1, 0, 0, 1): self.name = "CYS" elif countTuple == (2, 2, 0, 2, 0): self.name = "ASP" elif countTuple == (11, 4, 1, 0, 0): self.name = "LYS" elif countTuple == (4, 2, 1, 1, 0): self.name = "ASN" elif countTuple == (6, 3, 1, 1, 0): self.name = "GLN" elif countTuple == (4, 3, 0, 2, 0): self.name = "GLU" elif countTuple == (11, 4, 3, 0, 0): self.name = "ARG" elif countTuple == (5, 4, 2, 0, 0) or countTuple == (6, 4, 2, 0, 0): self.name = "HIS"
def BondOrderSum(atom): bosum = 0 for n_atom in ob.OBAtomAtomIter(atom): bosum += atom.GetBond(n_atom).GetBondOrder() return bosum
def count_nbrs_of_elem(atom, atomic_num): count = 0 for nbr in ob.OBAtomAtomIter(atom): if nbr.GetAtomicNum() == atomic_num: count += 1 return count
def IsConnectedTo(atom1, atom2): for atom in ob.OBAtomAtomIter(atom1): if OBAminoAcid.Equals(atom, atom2): return True return False
def HasABondTo(atom, atNum, bondOrder): for atom1 in ob.OBAtomAtomIter(atom): if atom1.GetAtomicNum() == atNum and atom.GetBond( atom1).GetBondOrder() == bondOrder: return True return False
def find_alpha_carbon(self): for atomC in ob.OBAtomAtomIter(self.CTerminus): for atomN in ob.OBAtomAtomIter(self.NTerminus): if OBAminoAcid.Equals(atomN, atomC): self.AlphaCarbon = atomN return
def get_residue_name(self): countH = 0 countC = 0 countN = 0 countO = 0 countS = 0 for atom in ob.OBMolAtomIter(self.SideChain): if atom.GetAtomicNum() == 1: countH += 1 elif atom.GetAtomicNum() == 6: countC += 1 elif atom.GetAtomicNum() == 7: countN += 1 elif atom.GetAtomicNum() == 8: countO += 1 elif atom.GetAtomicNum() == 16: countS += 1 countTuple = (countH, countC, countN, countO, countS) if countTuple == (1, 0, 0, 0, 0): self.name = "GLY" elif countTuple == (3, 1, 0, 0, 0): self.name = "ALA" elif countTuple == (7, 3, 0, 0, 0): self.name = "VAL" elif countTuple == (9, 4, 0, 0, 0): carbonCount = 0 for atom in ob.OBAtomAtomIter(self.AlphaCarbon): if OBAminoAcid.IsInMolecule(atom, self.SideChain): for n_atom in ob.OBAtomAtomIter(atom): if n_atom.GetAtomicNum() == 6: carbonCount += 1 if carbonCount == 2: self.name = "LEU" elif carbonCount == 3: self.name = "ILE" elif countTuple == (7, 3, 0, 0, 1): self.name = "MET" elif countTuple == (7, 7, 0, 0, 0): self.name = "PHE" elif countTuple == (8, 9, 1, 0, 0): self.name = "TRP" elif countTuple == (6, 3, 0, 0, 0): self.name = "PRO" elif countTuple == (3, 1, 0, 1, 0): self.name = "SER" elif countTuple == (5, 2, 0, 1, 0): self.name = "THR" elif countTuple == (7, 7, 0, 1, 0): self.name = "TYR" elif countTuple == (3, 1, 0, 0, 1): self.name = "CYS" elif countTuple == (2, 2, 0, 2, 0): self.name = "ASP" elif countTuple == (11, 4, 1, 0, 0): self.name = "LYS" elif countTuple == (4, 2, 1, 1, 0): self.name = "ASN" elif countTuple == (6, 3, 1, 1, 0): self.name = "GLN" elif countTuple == (4, 3, 0, 2, 0): self.name = "GLU" elif countTuple == (11, 4, 3, 0, 0): self.name = "ARG" elif countTuple == (5, 4, 2, 0, 0) or countTuple == (6, 4, 2, 0, 0): self.name = "HIS"