def test_find_connected(bond_list): """ Find all connected atoms to an atom in a known example. """ for index in (0, 1, 2, 3, 4, 6): assert struc.find_connected(bond_list, index).tolist() == [0, 1, 2, 3, 4, 6] assert struc.find_connected(bond_list, 5).tolist() == [5]
def rotate_residue(mol, bond_number, angle): # --- Identify rotatable bonds --- rotatable_bonds = struc.find_rotatable_bonds(mol.bonds) # --- do not rotate about backbone bonds --- for atom_name in BACKBONE: index = np.where(mol.atom_name == atom_name)[0][0] rotatable_bonds.remove_bonds_to(index) # --- init coordinates for new model --- coord = mol.coord.copy() # --- get bond axis --- atom_i, atom_j, _ = rotatable_bonds.as_array()[bond_number] axis = coord[atom_j] - coord[atom_i] # --- get support atom --- support = coord[atom_i] # --- need to get atoms only on one side of the bond --- bond_list_without_axis = mol.bonds.copy() bond_list_without_axis.remove_bond(atom_i, atom_j) rotated_atom_indices = struc.find_connected(bond_list_without_axis, root=atom_j) # --- rotate atoms --- coord[rotated_atom_indices] = struc.rotate_about_axis( coord[rotated_atom_indices], axis, angle, support) atom_list = [] for i, atom_i in enumerate(mol): atom_new = struc.Atom(coord[i], atom_name=atom_i.atom_name, element=atom_i.element) atom_list.append(atom_new) new_mol = struc.array(atom_list) new_mol.res_id[:] = mol.res_id new_mol.res_name[:] = mol.res_name new_mol.bonds = mol.bonds.copy() return new_mol
# Coordinates for the current rotamer model coord = residue.coord.copy() for atom_i, atom_j, _ in rotatable_bonds.as_array(): # The bond axis axis = coord[atom_j] - coord[atom_i] # Position of one of the involved atoms support = coord[atom_i] # Only atoms at one side of the rotatable bond should be moved # So the original Bondist is taken... bond_list_without_axis = residue.bonds.copy() # ...the rotatable bond is removed... bond_list_without_axis.remove_bond(atom_i, atom_j) # ...and these atoms are found by identifying the atoms that # are still connected to one of the two atoms involved rotated_atom_indices = struc.find_connected(bond_list_without_axis, root=atom_i) accepted = False while not accepted: # A random angle between 0 and 360 degrees angle = np.random.rand() * 2 * np.pi # Rotate coord[rotated_atom_indices] = struc.rotate_about_axis( coord[rotated_atom_indices], axis, angle, support) # Check if the atoms clash with each other: # The distance between each pair of atoms must be larger # than the sum of their VdW radii, if they are not bonded to # each other accepted = True distances = struc.distance(coord[:, np.newaxis],
def test_find_connected(bond_list): for index in (0,1,2,3,4,6): assert struc.find_connected(bond_list, index).tolist() == [0,1,2,3,4,6] assert struc.find_connected(bond_list, 5).tolist() == [5]
# Get the structure (including bonds) from the standard RCSB compound residue = info.residue("TYR") bond_list = residue.bonds ### Identify rotatable bonds ### rotatable_bonds = [] for atom1, atom2, bond_type in bond_list.as_array(): # Can only rotate about single bonds if bond_type != struc.BondType.SINGLE: continue segmented = bond_list.copy() segmented.remove_bond(atom1, atom2) conn_atoms1 = struc.find_connected(segmented, atom1) conn_atoms2 = struc.find_connected(segmented, atom2) # Rotation makes no sense if one of the atoms is a terminal atom, # e.g. a hydrogen if len(conn_atoms1) == 1 or len(conn_atoms2) == 1: continue # A bond cannot be rotated in a trivial way, # if it is inside a cyclic structure is_circular = atom2 in struc.find_connected(segmented, atom1) if is_circular: continue # Do not rotate about backbone bonds, # as these are irrelevant for a amino rotamer library