def find_RNA_anions(residue): """Finds all nucleic acid's residue's anions. :param residue: nucleic acid's residue object :type residue: openbabel.OBResidue :return: coords of residue's anions :rtype: list """ P = None anions_RNA = [] for atom in openbabel.OBResidueAtomIter(residue): if atom.GetAtomicNum() == config.PHOSPHORUS_NUM: P = atom break # Assuming there is only 1 Phosphate in residue if P: # 5'end has no phosphate group O = [] # List of 2 negative charged Oxygens for oxygen in pybel.ob.OBAtomAtomIter(P): # https://open-babel.readthedocs.io/en/latest/UseTheLibrary/migration.html if oxygen.GetExplicitValence() == 1 or oxygen.HasDoubleBond(): O.append(oxygen) anions_RNA.extend(O) return anions_RNA
def find_RNA_HB_HAL_acc_don(residue): """Finds all hydrogen/halogen bonds acceptors with all of their neighbours and all hydrogen bonds donors together with hydrogens in nucleic acid residue. :param residue: nucleic acid residue object :type residue: openbabel.OBResidue :return: coords of residue's halogen/hydrogen bonds acceptors & their neighbours :return: coords of residue's hydrogen bonds donors together with hydrogens :rtype: list :rtype: list """ residue_atoms_list = [] for atom in openbabel.OBResidueAtomIter(residue): residue_atoms_list.append(atom) # Create list of all residue's atoms acceptors_RNA = [ ] # List of sublists [[acceptor,acceptor',acceptor'(if the 2nd one exists)]] donors_RNA = [] for atom in filter(lambda at: at.IsHbondAcceptor(), residue_atoms_list): # Find all acceptors acceptors_RNA.append([atom]) for neighbour in pybel.ob.OBAtomAtomIter(atom): if neighbour.GetAtomicNum() != 1: # If not hydrogen acceptors_RNA[-1].append(neighbour) # Append acceptor' for atom in filter( lambda at: at.IsHbondDonor(), residue_atoms_list): # Find all donors with their hydrogens for neighbour in pybel.ob.OBAtomAtomIter(atom): if neighbour.IsHbondDonorH(): donors_RNA.append((atom, neighbour)) return acceptors_RNA, donors_RNA
def GetAtomByID(protein, residueNumber, name): """ Returns the OBAtom object given the AtomID (PDB Columns 13-16), the protein name (ace2 or spike), and the residue number """ for res in ob.OBResidueIter(protein): if res.GetNum() == residueNumber: for atom in ob.OBResidueAtomIter(res): if res.GetAtomID(atom) == name: return atom
def calculate_SIMPLE(residue, ligand_name, ligand_atoms, centroid_ligand): """Calculates SIMPLE interaction between residue - ligand pair: 1. Check RNA residue - ligand distance 2. Compare the distance to CUTOFF: - write down 1 if the distance <= CUTOFF - write down 0 if the distance > CUTOFF :param residue: residue as OpenBabel object :param ligand_name: ligand_name^pose_number :param ligand_atoms: coordinates of all ligand's atoms :type residue: openbabel.OBResidue :type ligand_name: str :type ligand_atoms: list :return: [ligand_name^pose_number, residue_number:residue_chain, binary info about interaction (0/1)] :rtype: list """ # List of sublists of all atoms' coords of the residue residue_atoms = [] for atom in openbabel.OBResidueAtomIter(residue): if atom.GetAtomicNum() != 1: residue_atoms.append( np.array([atom.GetX(), atom.GetY(), atom.GetZ()])) result = [ ligand_name, str(residue.GetNum()) + ':' + str(residue.GetChain()), 0 ] if measure_distance( centroid(residue_atoms), centroid_ligand ) > config.RES_LIGAND_MIN_DIST: # RNA residue centroid and ligand centroid are futher than declared threshold, no chance for any contact return result # Flag to iterate over residue's atoms as long as we do not find an atom within CUTOFF distance from ligand flag = True for rna_atom in residue_atoms: if flag: for ligand_atom in ligand_atoms: if check_distance(ligand_atom, rna_atom, config.CUT_OFF_SIMPLE): result[-1] = 1 # Condition met; write down 1 flag = False break else: break return result
def GetResidueMolecule(protein, residueNumber): """ Gets the OBMol object corresponding to a residue number on ACE2 protein or Spike protein protein: 'ace2' or 'spike' residueNumber: The residue Number returns: The OBMol object representing the molecule """ resMol = ob.OBMol() for res in ob.OBResidueIter(protein): if res.GetNum() == residueNumber: for atom in ob.OBResidueAtomIter(res): resMol.AddAtom(atom) break return resMol
def rna_coords_atom_index_dict(structure): """For the debug/detail mode only; creates a dictionary or nucleic acid's atoms' coords with their atom ids as values :param structure: nucleic acid structure object :type structure: pybel.Molecule :return: dictionary indexed by nucleic acid's atoms' coords, with their atom ids as values :rtype: dict """ dictionary = {} for residue in openbabel.OBResidueIter(structure.OBMol): if residue.GetNumAtoms() > 3: for atom in openbabel.OBResidueAtomIter(residue): dictionary[( atom.GetX(), atom.GetY(), atom.GetZ())] = atom.GetResidue().GetAtomID(atom).strip() return dictionary
def atoms(self): """List of Atoms in the Residue""" return [Atom(atom) for atom in ob.OBResidueAtomIter(self.OBResidue)]
def printAtomNames(mol): for res in openbabel.OBResidueIter(mol): for atom in openbabel.OBResidueAtomIter(res): name = res.GetAtomID(atom) print(name)
def __init__(self, protein, res_name, res_num, custom_settings): self.residue_number = int(res_num) - 1 self.residue = protein.GetResidue(self.residue_number) self.atoms = [atom for atom in ob.OBResidueAtomIter(self.residue)] # Making atom index consistent by separating hydrogen and heavy atom self.heavyatoms = [] self.hydrogens = [] for atom in self.atoms: if atom.GetAtomicNum() == 1: self.hydrogens.append(atom) else: self.heavyatoms.append(atom) self.output_mode = custom_settings['output_mode'] self.simplified = False self.full = False self.full_nobb = False if self.output_mode['full']: self.full = True if self.output_mode['full_nobb']: self.full_nobb = True if self.output_mode['simplified']: self.simplified = True self.full_bitstring = bitarray('0000000') self.full_nobb_bitstring = bitarray('0000000') self.simp_bitstring = self.bs_template[res_name[:3]] self.res_name = res_name self.AA_name = res_name[:3] self.res_num = res_num self.interactions = self.AAinteractionMatrix[self.AA_name] # Classifying atoms into atom groups self.atomGroup = {} for AA_int, int_atom, int_name in \ zip(self.interactions, self.interactionList, self.interactionNames): if AA_int == 1: atomIDs = int_atom[self.AA_name]['id'] atomList = [self.heavyatoms[atomID] for atomID in atomIDs] self.atomGroup[int_name] = atomList if int_name == 'h_donor': h_donorh_list = self.h_donorh[self.AA_name]['id'] h_donorh_atoms = [] for h_list in h_donorh_list: hydrogen = [self.hydrogens[atomID] for atomID in h_list] h_donorh_atoms.append(hydrogen) self.atomGroup['h_donorh'] = h_donorh_atoms if self.AA_name in self.aromatic.keys(): self.path3 = self.aromatic[self.AA_name]['id'][:3] self.path3atoms = [] for i in self.path3: self.path3atoms.append(self.heavyatoms[i]) self.cross, self.modulus = getCrossModulus(self.path3atoms) self.res_weight1 = custom_settings['res_weight1'] self.res_weight2 = custom_settings['res_weight2'] self.res_weight3 = custom_settings['res_weight3'] self.res_weight4 = custom_settings['res_weight4'] self.res_weight5 = custom_settings['res_weight5']
def calculate_PBS(residue, ligand_name, ligand_atoms, centroid_ligand): """Calculates PBS interaction between residue - ligand pair: 1. Divide RNA residue into 3 groups Phosphate/Base/Sugar (P/B/S) 2. Check each group - ligand distance 3. Compare the distance to CUTOFF: - write down 1 if the distance <= CUTOFF - write down 0 if the distance > CUTOFF :param residue: residue as OpenBabel object :param ligand_name: ligand_name^pose_number :param ligand_atoms: coordinates of all ligand's atoms :type residue: openbabel.OBResidue :type ligand_name: str :type ligand_atoms: list :return: [ligand_name^pose_number, residue_number:residue_chain, binary info about interaction in P group (0/1), binary info about interaction in B group (0/1), binary info about interaction in S group (0/1)] :rtype: list """ # List of residue's atoms as OBAtoms objects residue_atoms = [] residue_atoms_coords = [] for atom in openbabel.OBResidueAtomIter(residue): if atom.GetAtomicNum() != 1: residue_atoms.append(atom) residue_atoms_coords.append( np.array([atom.GetX(), atom.GetY(), atom.GetZ()])) result = [ ligand_name, str(residue.GetNum()) + ':' + str(residue.GetChain()), 0, 0, 0 ] if measure_distance( centroid(residue_atoms_coords), centroid_ligand ) > config.RES_LIGAND_MIN_DIST: # RNA residue centroid and ligand centroid are futher than declared threshold, no chance for any contact return result # Flag to iterate over residue's atoms as long as we do not find an atom of the defined P/B/S group within CUTOFF distance from ligand flags = [True, True, True] for rna_atom in residue_atoms: # Flag to check if we deal with atom that does not belong to any of the defined P/B/S groups atom_group_type = False rna_atom_name = residue.GetAtomID(rna_atom).strip() rna_atom_coords = np.array( [rna_atom.GetX(), rna_atom.GetY(), rna_atom.GetZ()]) for g in range(len(config.GROUPS)): # If atom present in the group if rna_atom_name in config.GROUPS[g]: atom_group_type = True # If atom belongs to one of the 3 groups if flags[g]: for ligand_atom in ligand_atoms: if check_distance(ligand_atom, rna_atom_coords, config.CUT_OFF_SIMPLE): result[g - 3] = 1 # Condition met; write down 1 flags[g] = False break if not atom_group_type: raise Exception('Unknown atom type %s' % rna_atom_name) # MAYBE NEEDS TO BE CHANGED return result
# Fill the RESULTS dictionary of keys - ligand ids and values - lists of 0 for ligand_name in ligands_hba_hbd.keys(): RESULTS[ligand_name] = [0] * RNA_LENGTH * FUNCTIONS[fingerprint] for residue in openbabel.OBResidueIter( structure.OBMol ): # Loop over all RNA residue to calculate hydrogen bondings, halogen bondings & cation-anion interactions RNA_residues.append( str(residue.GetNum()) + ':' + str(residue.GetChain())) RNA_nucleotides.append(str(residue.GetName())) acceptors_RNA, donors_RNA = find_RNA_HB_HAL_acc_don(residue) anions_RNA = find_RNA_anions(residue) residue_atoms_coords = [] for atom in openbabel.OBResidueAtomIter(residue): if atom.GetAtomicNum() != 1: residue_atoms_coords.append( np.array([atom.GetX(), atom.GetY(), atom.GetZ()])) for ligand_name_HB, ligand_values_HB in ligands_hba_hbd.items(): if measure_distance( centroid(residue_atoms_coords), centroid(ligands_all_atoms[ligand_name_HB]) ) > config.RES_LIGAND_MIN_DIST: # RNA residue centroid and ligand centroid are futher than declared threshold, no chance for any contact continue if consider_dha: result = calculate_HB(residue, acceptors_RNA, donors_RNA,