def from_rdkit(cls, rd_atom: Chem.Atom) -> "Atom": """ Build a QUBEKit atom from an rdkit atom instance. """ atomic_number = rd_atom.GetAtomicNum() index = rd_atom.GetIdx() formal_charge = rd_atom.GetFormalCharge() aromatic = rd_atom.GetIsAromatic() bonds = [a.GetIdx() for a in rd_atom.GetNeighbors()] # check for names in the normal places pdb, mol2 and mol if rd_atom.HasProp("_Name"): name = rd_atom.GetProp("_Name") elif rd_atom.HasProp("_TriposAtomName"): name = rd_atom.GetProp("_TriposAtomName") else: try: name = rd_atom.GetMonomerInfo().GetName().strip() except AttributeError: name = None # stereochem if rd_atom.HasProp("_CIPCode"): stereo_code = rd_atom.GetProp("_CIPCode") else: stereo_code = None return cls( atomic_number=atomic_number, atom_index=index, atom_name=name, formal_charge=formal_charge, aromatic=aromatic, stereochemistry=stereo_code, bonds=bonds, )
def _parse_atom(self, atom: Chem.Atom) -> None: if atom.GetSymbol() == '*': neighbor = atom.GetNeighbors()[0] n_name = self._get_pdb_atomname(neighbor) self.CONNECT.append([n_name, len(self.CONNECT) + 1, 'CONNECT']) else: d = self._get_atom_descriptors(atom) self.ATOM.append(d)
def _get_square(self, first: Chem.Atom, second: Chem.Atom) -> Union[Tuple[int, int], None]: for third in [neigh for neigh in second.GetNeighbors() if neigh.GetIdx() != first.GetIdx()]: fourths = self._get_triangles(first, third) if fourths and len(fourths) > 1: fourth = [f for f in fourths if f != second.GetIdx()][0] return third.GetIdx(), fourth else: return None
def assess_atom(atom: Chem.Atom, bt: Chem.BondType) -> Tuple[bool, Chem.BondType]: if atom.GetAtomicNum() > 8: return True, bt elif len(atom.GetNeighbors()) <= 2 and atom.GetIsAromatic(): return True, Chem.BondType.SINGLE elif len(atom_i.GetNeighbors()) <= 3 and not atom.GetIsAromatic(): return True, bt else: return False, bt # too bonded already!
def _is_square(self, first: Chem.Atom, second: Chem.Atom) -> bool: """ Get bool of whether two atoms share a common over-neighbor. Ie. joining them would make a square. Direct bond does not count. :param first: :param second: :return: """ for third in [neigh for neigh in second.GetNeighbors() if neigh.GetIdx() != first.GetIdx()]: if self._is_triangle(first, third) is True: return True else: return False
def _get_unseen_neighbors(self, atom: Chem.Atom, seen: List[Chem.Atom], nondummy: bool = True): neighbors = atom.GetNeighbors() if nondummy: neighbors = [ neighbor for neighbor in neighbors if neighbor.GetSymbol() != '*' ] seenIdx = {a.GetIdx() for a in seen} return [ neighbor for neighbor in neighbors if neighbor.GetIdx() not in seenIdx ]
def get_substructures_from_atom( atom: Chem.Atom, max_size: int, substructure: Set[int] = None) -> Set[FrozenSet[int]]: """ Recursively gets all substructures up to a maximum size starting from an atom in a substructure. :param atom: The atom to start at. :param max_size: The maximum size of the substructure to fine. :param substructure: The current substructure that atom is in. :return: A set of substructures starting at atom where each substructure is a frozenset of indices. """ assert max_size >= 1 if substructure is None: substructure = {atom.GetIdx()} substructures = {frozenset(substructure)} if len(substructure) == max_size: return substructures # Get neighbors which are not already in the substructure new_neighbors = [ neighbor for neighbor in atom.GetNeighbors() if neighbor.GetIdx() not in substructure ] for neighbor in new_neighbors: # Define new substructure with neighbor new_substructure = deepcopy(substructure) new_substructure.add(neighbor.GetIdx()) # Skip if new substructure has already been considered if frozenset(new_substructure) in substructures: continue # Recursively get substructures including this substructure plus neighbor new_substructures = get_substructures_from_atom( neighbor, max_size, new_substructure) # Add those substructures to current set of substructures substructures |= new_substructures return substructures
def _parse_atom(self, atom: Chem.Atom) -> None: if atom.GetSymbol() == '*': neighbor = atom.GetNeighbors()[0] n_name = self._get_PDBInfo_atomname(neighbor) if self.is_aminoacid() and neighbor.GetSymbol() == 'N': # atom_name, index, connect_type, connect_name self.CONNECT.append([n_name, 1, 'LOWER_CONNECT', 'LOWER']) elif self.is_aminoacid() and neighbor.GetSymbol() == 'C': # atom_name, index, connect_type, connect_name self.CONNECT.append([n_name, 2, 'UPPER_CONNECT', 'UPPER']) elif self.is_aminoacid(): i = max(3, len(self.CONNECT) + 1) self.CONNECT.append([n_name, i, 'CONNECT']) else: self.CONNECT.append([n_name, len(self.CONNECT) + 1, 'CONNECT']) else: d = self._get_atom_descriptors(atom) self.ATOM.append(d)
def assess_atom(atom: Chem.Atom, bt: Chem.BondType) -> Tuple[bool, Chem.BondType]: """ True means add, False means delete :param atom: :param bt: :return: """ n_neigh = sum([self._is_count_valid(neigh) for neigh in atom.GetNeighbors()]) if atom.GetAtomicNum() > 8: return True, bt elif atom.HasProp('DELETE'): # if it is to be deleted it should be fine. return True, bt elif n_neigh <= 2 and atom.GetIsAromatic(): return True, Chem.BondType.SINGLE elif n_neigh <= 3 and not atom.GetIsAromatic(): return True, bt else: return False, bt # too bonded already!
def _assess_atom_for_possible_bonding(self, atom: Chem.Atom, bt: Chem.BondType) -> bool: """ Method for add_bond_if_possible True means add, False means delete :param atom: :param bt: :return: """ n_neigh = sum( [self._is_count_valid(neigh) for neigh in atom.GetNeighbors()]) if atom.GetAtomicNum() > 8: return True elif atom.HasProp( 'DELETE'): # if it is to be deleted it should be fine. return True elif n_neigh <= 2 and atom.GetIsAromatic(): return True, Chem.BondType.SINGLE elif n_neigh <= 3 and not atom.GetIsAromatic(): return True else: return False # too bonded already!
def _parse_atom(self, atom: Chem.Atom) -> None: self.log.debug( f'Parsing {atom.GetSymbol()} at position {atom.GetIdx()}') if atom.GetSymbol() == '*': neighbor = atom.GetNeighbors()[0] n_name = self._get_PDBInfo_atomname(neighbor) if self.is_aminoacid() and neighbor.GetSymbol() == 'N': # atom_name, index, connect_type, connect_name self.CONNECT.append([n_name, 1, 'LOWER_CONNECT', 'LOWER']) elif self.is_aminoacid() and neighbor.GetSymbol() == 'C': # atom_name, index, connect_type, connect_name self.CONNECT.append([n_name, 2, 'UPPER_CONNECT', 'UPPER']) elif self.is_aminoacid(): i = max(3, len(self.CONNECT) + 1) self.CONNECT.append([n_name, i, 'CONNECT']) else: self.CONNECT.append([n_name, len(self.CONNECT) + 1, 'CONNECT']) else: d = self._get_atom_descriptors( atom) # dict of 'name', 'rtype': 'mtype', 'partial' self.ATOM.append(d) formal = atom.GetFormalCharge() if formal != 0: self.CHARGE.append([d['name'], formal])
def is_hydrogen_bonding(self, atom: Atom): return any([ nbr.GetSymbol() in ["N", "O", "S"] for nbr in atom.GetNeighbors() ])