def phi_iter(atoms): """ Iterate over all phi angles in a protein. """ res_iter1 = struct.residue_iter(atoms) res_iter2 = struct.residue_iter(atoms) next(res_iter1) yield None # No phi for first AS for res, prev_res in zip(res_iter1, res_iter2): yield prev_res[..., prev_res.atom_name == "C"] \ + res[..., struct.filter_backbone(res)]
def psi_iter(atoms): """ Iterate over all psi angles in a protein. """ res_iter1 = struct.residue_iter(atoms) res_iter2 = struct.residue_iter(atoms) next(res_iter2) for res, next_res in zip(res_iter1, res_iter2): yield res[..., struct.filter_backbone(res)] \ + next_res[..., next_res.atom_name == "N"] yield None # No psi for last AS
def analyze_chirality(array): # Filter backbone + CB array = array[struc.filter_amino_acids(array)] array = array[(array.atom_name == "CB") | (struc.filter_backbone(array))] # Iterate over each residue ids, names = struc.get_residues(array) enantiomers = np.zeros(len(ids), dtype=int) for i, id in enumerate(ids): coord = array.coord[array.res_id == id] if len(coord) != 4: # Glyine -> no chirality enantiomers[i] = 0 else: enantiomers[i] = get_enantiomer(coord[0], coord[1], coord[2], coord[3]) return enantiomers
clashed = distances < vdw_radii_mean for clash_atom1, clash_atom2 in zip(*np.where(clashed)): if clash_atom1 == clash_atom2: # Ignore distance of an atom to itself continue if (clash_atom1, clash_atom2) not in bond_list: # Nonbonded atoms clash # -> structure is not accepted accepted = False rotamer_coord[i] = coord rotamers = struc.from_template(residue, rotamer_coord) ### Superimpose backbone onto first model for better visualization ### rotamers, _ = struc.superimpose(rotamers[0], rotamers, atom_mask=struc.filter_backbone(rotamers)) ### Visualize rotamers ### colors = np.zeros((residue.array_length(), 3)) colors[residue.element == "H"] = (0.8, 0.8, 0.8) # gray colors[residue.element == "C"] = (0.0, 0.8, 0.0) # green colors[residue.element == "N"] = (0.0, 0.0, 0.8) # blue colors[residue.element == "O"] = (0.8, 0.0, 0.0) # red # For consistency, each subplot has the same box size coord = rotamers.coord size = np.array([ coord[:, :, 0].max() - coord[:, :, 0].min(), coord[:, :, 1].max() - coord[:, :, 1].min(), coord[:, :, 2].max() - coord[:, :, 2].min() ]).max() * 0.5
clashed = distances < vdw_radii_mean for clash_atom1, clash_atom2 in zip(*np.where(clashed)): if clash_atom1 == clash_atom2: # Ignore distance of an atom to itself continue if (clash_atom1, clash_atom2) not in bond_list: # Nonbonded atoms clash # -> structure is not accepted accepted = False rotamer_coord[i] = coord rotamers = struc.from_template(residue, rotamer_coord) ### Superimpose backbone onto first model for better visualization ### rotamers, _ = struc.superimpose( rotamers[0], rotamers, atom_mask=struc.filter_backbone(rotamers) ) ### Visualize rotamers ### colors = np.zeros((residue.array_length(), 3)) colors[residue.element == "H"] = (0.8, 0.8, 0.8) # gray colors[residue.element == "C"] = (0.0, 0.8, 0.0) # green colors[residue.element == "N"] = (0.0, 0.0, 0.8) # blue colors[residue.element == "O"] = (0.8, 0.0, 0.0) # red # For consistency, each subplot has the same box size coord = rotamers.coord size = np.array( [coord[:, :, 0].max() - coord[:, :, 0].min(), coord[:, :, 1].max() - coord[:, :, 1].min(),
def test_backbone_filter(sample_array): assert len(sample_array[struc.filter_backbone(sample_array)]) == 384
def assemble_peptide(sequence): res_names = [seq.ProteinSequence.convert_letter_1to3(r) for r in sequence] peptide = struc.AtomArray(length=0) for res_id, res_name, connect_angle in zip( np.arange(1, len(res_names) + 1), res_names, itertools.cycle([120, -120])): # Create backbone atom_n = struc.Atom([0.0, 0.0, 0.0], atom_name="N", element="N") atom_ca = struc.Atom([0.0, N_CA_LENGTH, 0.0], atom_name="CA", element="C") coord_c = calculate_atom_coord_by_z_rotation(atom_ca.coord, atom_n.coord, 120, CA_C_LENGTH) atom_c = struc.Atom(coord_c, atom_name="C", element="C") coord_o = calculate_atom_coord_by_z_rotation(atom_c.coord, atom_ca.coord, 120, C_O_DOUBLE_LENGTH) atom_o = struc.Atom(coord_o, atom_name="O", element="O") coord_h = calculate_atom_coord_by_z_rotation(atom_n.coord, atom_ca.coord, -120, N_H_LENGTH) atom_h = struc.Atom(coord_h, atom_name="H", element="H") backbone = struc.array([atom_n, atom_ca, atom_c, atom_o, atom_h]) backbone.res_id[:] = res_id backbone.res_name[:] = res_name # Add bonds between backbone atoms bonds = struc.BondList(backbone.array_length()) bonds.add_bond(0, 1, struc.BondType.SINGLE) # N-CA bonds.add_bond(1, 2, struc.BondType.SINGLE) # CA-C bonds.add_bond(2, 3, struc.BondType.DOUBLE) # C-O bonds.add_bond(0, 4, struc.BondType.SINGLE) # N-H backbone.bonds = bonds # Get residue from dataset residue = info.residue(res_name) # Superimpose backbone of residue # with backbone created previously _, transformation = struc.superimpose( backbone[struc.filter_backbone(backbone)], residue[struc.filter_backbone(residue)]) residue = struc.superimpose_apply(residue, transformation) # Remove backbone atoms from residue because they are already # existing in the backbone created prevoisly side_chain = residue[~np.isin( residue. atom_name, ["N", "CA", "C", "O", "OXT", "H", "H2", "H3", "HXT"])] # Assemble backbone with side chain (including HA) # and set annotation arrays residue = backbone + side_chain residue.bonds.add_bond( np.where(residue.atom_name == "CA")[0][0], np.where(residue.atom_name == "CB")[0][0], struc.BondType.SINGLE) residue.bonds.add_bond( np.where(residue.atom_name == "CA")[0][0], np.where(residue.atom_name == "HA")[0][0], struc.BondType.SINGLE) residue.chain_id[:] = "A" residue.res_id[:] = res_id residue.res_name[:] = res_name peptide += residue # Connect current residue to existing residues in the chain if res_id > 1: index_prev_ca = np.where((peptide.res_id == res_id - 1) & (peptide.atom_name == "CA"))[0][0] index_prev_c = np.where((peptide.res_id == res_id - 1) & (peptide.atom_name == "C"))[0][0] index_curr_n = np.where((peptide.res_id == res_id) & (peptide.atom_name == "N"))[0][0] index_curr_c = np.where((peptide.res_id == res_id) & (peptide.atom_name == "C"))[0][0] curr_residue_mask = peptide.res_id == res_id # Adjust geometry curr_coord_n = calculate_atom_coord_by_z_rotation( peptide.coord[index_prev_c], peptide.coord[index_prev_ca], connect_angle, C_N_LENGTH) peptide.coord[curr_residue_mask] -= peptide.coord[index_curr_n] peptide.coord[curr_residue_mask] += curr_coord_n # Adjacent residues should show in opposing directions # -> rotate residues with even residue ID by 180 degrees if res_id % 2 == 0: coord_n = peptide.coord[index_curr_n] coord_c = peptide.coord[index_curr_c] peptide.coord[curr_residue_mask] = struc.rotate_about_axis( atoms=peptide.coord[curr_residue_mask], axis=coord_c - coord_n, angle=np.deg2rad(180), support=coord_n) # Add bond between previous C and current N peptide.bonds.add_bond(index_prev_c, index_curr_n, struc.BondType.SINGLE) # Add N-terminal hydrogen atom_n = peptide[(peptide.res_id == 1) & (peptide.atom_name == "N")][0] atom_h = peptide[(peptide.res_id == 1) & (peptide.atom_name == "H")][0] coord_h2 = calculate_atom_coord_by_z_rotation(atom_n.coord, atom_h.coord, -120, N_H_LENGTH) atom_h2 = struc.Atom(coord_h2, chain_id="A", res_id=1, res_name=atom_h.res_name, atom_name="H2", element="H") peptide = struc.array([atom_h2]) + peptide peptide.bonds.add_bond(0, 1, struc.BondType.SINGLE) # H2-N # Add C-terminal hydroxyl group last_id = len(sequence) index_c = np.where((peptide.res_id == last_id) & (peptide.atom_name == "C"))[0][0] index_o = np.where((peptide.res_id == last_id) & (peptide.atom_name == "O"))[0][0] coord_oxt = calculate_atom_coord_by_z_rotation(peptide.coord[index_c], peptide.coord[index_o], connect_angle, C_O_LENGTH) coord_hxt = calculate_atom_coord_by_z_rotation(coord_oxt, peptide.coord[index_c], connect_angle, O_H_LENGTH) atom_oxt = struc.Atom(coord_oxt, chain_id="A", res_id=last_id, res_name=peptide[index_c].res_name, atom_name="OXT", element="O") atom_hxt = struc.Atom(coord_hxt, chain_id="A", res_id=last_id, res_name=peptide[index_c].res_name, atom_name="HXT", element="H") peptide = peptide + struc.array([atom_oxt, atom_hxt]) peptide.bonds.add_bond(index_c, -2, struc.BondType.SINGLE) # C-OXT peptide.bonds.add_bond(-2, -1, struc.BondType.SINGLE) # OXT-HXT return peptide
# Get the first 100 atoms from the third model subarray = stack[2, :100] # Get the first 100 atoms from the models 3, 4 and 5 substack = stack[2:5, :100] # Get the first atom in the second model atom = stack[1, 0] # Get a stack containing arrays containing only the first atom substack = stack[:, 0] ######################################################################## # Furthermore, :mod:`biotite.structure` contains advanced filters, # that create boolean masks from an array using specific criteria. # Here is a small example. backbone = array[struc.filter_backbone(array)] print(backbone.atom_name) ######################################################################## # If you would like to know which atoms are in proximity to specific # coordinates, have a look at the :class:`CellList` class. # # .. warning:: Creating a subarray or substack by indexing does not # necessarily copy the coordinates and annotation arrays. # If possible, only *array views* are created. # Look into the `NumPy` documentation for furher details. # If you want to ensure, that you are working with a copy, # use the :func:`copy()` method after indexing. # # Representing bonds # ------------------