예제 #1
0
def covalent_bonds(atoms, threshold=1.1):
    """Returns all the covalent bonds in a list of `Atom` pairs.

    Notes
    -----
    Uses information `element_data`, which can be accessed directly
    through this module i.e. `isambard.ampal.interactions.element_data`.

    Parameters
    ----------
    atoms : [(`Atom`, `Atom`)]
        List of pairs of `Atoms`.
    threshold : float, optional
        Allows deviation from ideal covalent bond distance to be included.
        For example, a value of 1.1 would allow interactions up to 10% further
        from the ideal distance to be included.
    """
    bonds = []
    for a, b in atoms:
        bond_distance = (
            element_data[a.element.title()]['atomic radius'] +
            element_data[b.element.title()]['atomic radius']) / 100
        dist = distance(a._vector, b._vector)
        if dist <= bond_distance * threshold:
            bonds.append(CovalentBond(a, b, dist))
    return bonds
예제 #2
0
def polymer_to_reference_axis_distances(p,
                                        reference_axis,
                                        tag=True,
                                        reference_axis_name='ref_axis'):
    """Returns distances between the primitive of a Polymer and a reference_axis.

    Notes
    -----
    Distances are calculated between each point of the Polymer primitive
    and the corresponding point in reference_axis. In the special case
    of the helical barrel, if the Polymer is a helix and the reference_axis
    represents the centre of the barrel, then this function returns the
    radius of the barrel at each point on the helix primitive. The points
    of the primitive and the reference_axis are run through in the same
    order, so take care with the relative orientation of the reference
    axis when defining it.

    Parameters
    ----------
    p : ampal.Polymer
    reference_axis : list(numpy.array or tuple or list)
        Length of reference_axis must equal length of the Polymer.
        Each element of reference_axis represents a point in R^3.
    tag : bool, optional
        If True, tags the Chain with the reference axis coordinates
        and each Residue with its distance to the ref axis.
        Distances are stored at the Residue level, but refer to
        distances from the CA atom.
    reference_axis_name : str, optional
        Used to name the keys in tags at Chain and Residue level.

    Returns
    -------
    distances : list(float)
        Distance values between corresponding points on the
        reference axis and the `Polymer` `Primitive`.

    Raises
    ------
    ValueError
        If the Polymer and the reference_axis have unequal length.
    """
    if not len(p) == len(reference_axis):
        raise ValueError(
            "The reference axis must contain the same number of points "
            "as the Polymer primitive.")
    prim_cas = p.primitive.coordinates
    ref_points = reference_axis.coordinates
    distances = [
        distance(prim_cas[i], ref_points[i]) for i in range(len(prim_cas))
    ]
    if tag:
        p.tags[reference_axis_name] = reference_axis
        monomer_tag_name = 'distance_to_{0}'.format(reference_axis_name)
        for m, d in zip(p._monomers, distances):
            m.tags[monomer_tag_name] = d
    return distances
예제 #3
0
def make_primitive_extrapolate_ends(cas_coords, smoothing_level=2):
    """Generates smoothed helix primitives and extrapolates lost ends.

    Notes
    -----
    From an input list of CA coordinates, the running average is
    calculated to form a primitive. The smoothing_level dictates how
    many times to calculate the running average. A higher
    smoothing_level generates a 'smoother' primitive - i.e. the
    points on the primitive more closely fit a smooth curve in R^3.
    Each time the smoothing level is increased by 1, a point is lost
    from either end of the primitive. To correct for this, the primitive
    is extrapolated at the ends to approximate the lost values. There
    is a trade-off then between the smoothness of the primitive and
    its accuracy at the ends.


    Parameters
    ----------
    cas_coords : list(numpy.array or float or tuple)
        Each element of the list must have length 3.
    smoothing_level : int
        Number of times to run the averaging.

    Returns
    -------
    final_primitive : list(numpy.array)
        Each array has length 3.
    """
    try:
        smoothed_primitive = make_primitive_smoothed(
            cas_coords, smoothing_level=smoothing_level)
    except ValueError:
        smoothed_primitive = make_primitive_smoothed(
            cas_coords, smoothing_level=smoothing_level - 1)
    # if returned smoothed primitive is too short, lower the smoothing
    # level and try again.
    if len(smoothed_primitive) < 3:
        smoothed_primitive = make_primitive_smoothed(
            cas_coords, smoothing_level=smoothing_level - 1)
    final_primitive = []
    for ca in cas_coords:
        prim_dists = [distance(ca, p) for p in smoothed_primitive]
        closest_indices = sorted([
            x[0] for x in sorted(enumerate(prim_dists), key=lambda k: k[1])[:3]
        ])
        a, b, c = [smoothed_primitive[x] for x in closest_indices]
        ab_foot = find_foot(a, b, ca)
        bc_foot = find_foot(b, c, ca)
        ca_foot = (ab_foot + bc_foot) / 2
        final_primitive.append(ca_foot)
    return final_primitive
예제 #4
0
    def rise_per_residue(self):
        """The rise per residue at each point on the Primitive.

        Notes
        -----
        Each element of the returned list is the rise per residue,
        at a point on the Primitive. Element i is the distance
        between primitive[i] and primitive[i + 1]. The final value
        is None.
        """
        rprs = [
            distance(self[i]['CA'], self[i + 1]['CA'])
            for i in range(len(self) - 1)
        ]
        rprs.append(None)
        return rprs
예제 #5
0
def find_atoms_within_distance(atoms, cutoff_distance, point):
    """Returns atoms within the distance from the point.

    Parameters
    ----------
    atoms : [ampal.atom]
        A list of `ampal.atoms`.
    cutoff_distance : float
        Maximum distance from point.
    point : (float, float, float)
        Reference point, 3D coordinate.

    Returns
    -------
    filtered_atoms : [ampal.atoms]
        `atoms` list filtered by distance.
    """
    return [x for x in atoms if distance(x, point) <= cutoff_distance]
예제 #6
0
 def knob_end(self):
     """ Coordinates of the end of the knob residue (atom in side-chain furthest from CB atom.
     Returns CA coordinates for GLY.
     """
     side_chain_atoms = self.knob_residue.side_chain
     if not side_chain_atoms:
         return self.knob_residue['CA']
     distances = [
         distance(self.knob_residue['CB'], x) for x in side_chain_atoms
     ]
     max_d = max(distances)
     knob_end_atoms = [
         atom for atom, d in zip(side_chain_atoms, distances) if d == max_d
     ]
     if len(knob_end_atoms) == 1:
         return knob_end_atoms[0]._vector
     else:
         return numpy.mean([x._vector for x in knob_end_atoms], axis=0)
예제 #7
0
def find_contiguous_packing_segments(polypeptide, residues, max_dist=10.0):
    """ Assembly containing segments of polypeptide, divided according to separation of contiguous residues.

    Parameters
    ----------
    polypeptide : Polypeptide
    residues : iterable containing Residues
    max_dist : float
        Separation beyond which splitting of Polymer occurs.

    Returns
    -------
    segments : Assembly
        Each segment contains a subset of residues, each not separated by more than max_dist from the previous Residue.
    """
    segments = Assembly(assembly_id=polypeptide.ampal_parent.id)
    residues_in_polypeptide = list(
        sorted(residues.intersection(set(polypeptide.get_monomers())),
               key=lambda x: int(x.id)))
    if not residues_in_polypeptide:
        return segments
    # residue_pots contains separate pots of residues divided according to their separation distance.
    residue_pots = []
    pot = [residues_in_polypeptide[0]]
    for r1, r2 in zip(residues_in_polypeptide, residues_in_polypeptide[1:]):
        d = distance(r1['CA'], r2['CA'])
        if d <= max_dist:
            pot.append(r2)
            if sum([len(x) for x in residue_pots] +
                   [len(pot)]) == len(residues_in_polypeptide):
                residue_pots.append(pot)
        else:
            residue_pots.append(pot)
            pot = [r2]
    for pot in residue_pots:
        segment = polypeptide.get_slice_from_res_id(pot[0].id, pot[-1].id)
        segment.ampal_parent = polypeptide.ampal_parent
        segments.append(segment)
    return segments
예제 #8
0
def find_kihs(assembly, hole_size=4, cutoff=7.0):
    """ KnobIntoHoles between residues of different chains in assembly.

    Notes
    -----
    A KnobIntoHole is a found when the side-chain centre of a Residue a chain is close than (cutoff) Angstroms from at
    least (hole_size) side-chain centres of Residues of a different chain.

    Parameters
    ----------
    assembly : Assembly
    hole_size : int
        Number of Residues required to form each hole.
    cutoff : float
        Maximum distance between the knob and each of the hole residues.

    Returns
    -------
    kihs : [KnobIntoHole]
    """
    pseudo_group = side_chain_centres(assembly=assembly, masses=False)
    pairs = itertools.permutations(pseudo_group, 2)
    kihs = []
    for pp_1, pp_2 in pairs:
        for r in pp_1:
            close_atoms = pp_2.is_within(cutoff, r)
            # kihs occur between residue and (hole_size) closest side-chains on adjacent polypeptide.
            if len(close_atoms) < hole_size:
                continue
            elif len(close_atoms) > hole_size:
                close_atoms = sorted(close_atoms,
                                     key=lambda x: distance(x, r))[:hole_size]
            kih = OrderedDict()
            kih['k'] = r
            for i, hole_atom in enumerate(close_atoms):
                kih['h{0}'.format(i)] = hole_atom
            knob_into_hole = KnobIntoHole(pseudo_atoms=kih)
            kihs.append(knob_into_hole)
    return kihs
예제 #9
0
 def max_knob_end_distance(self):
     """ Maximum distance between knob_end and each of the hole side-chain centres. """
     return max([distance(self.knob_end, h) for h in self.hole])
예제 #10
0
 def max_kh_distance(self):
     return max([distance(self.knob, h) for h in self.hole])