Alpha angle calculated using points on the primitive of helix and axis.

    Notes
    -----
    The final value is None, since the angle calculation requires pairs
    of points along the primitive and axis. This is a generalisation
    of the calculation used to measure the tilt of a helix in a
    coiled-coil with respect to the central axis of the coiled coil.

    Parameters
    ----------
    p : ampal.Polymer
        Reference `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 alpha angle. Alpha angles are stored
        at the Residue level, but are calculated using the CA atom.
    reference_axis_name : str, optional
        Used to name the keys in tags at Chain and Residue level.

    Returns
    -------
    alphas : list of float
        The alpha angle for the Polymer at each point of its primitive,
        in degrees.

    Raises
    ------
    ValueError
        If the Polymer and the reference_axis have unequal length.

def alpha_angles(p, reference_axis, tag=True, reference_axis_name='ref_axis'):
    """Alpha angle calculated using points on the primitive of helix and axis.

    Notes
    -----
    The final value is None, since the angle calculation requires pairs
    of points along the primitive and axis. This is a generalisation
    of the calculation used to measure the tilt of a helix in a
    coiled-coil with respect to the central axis of the coiled coil.

    Parameters
    ----------
    p : ampal.Polymer
        Reference `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 alpha angle. Alpha angles are stored
        at the Residue level, but are calculated using the CA atom.
    reference_axis_name : str, optional
        Used to name the keys in tags at Chain and Residue level.

    Returns
    -------
    alphas : list of float
        The alpha angle for the Polymer at each point of its primitive,
        in degrees.

    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
    alphas = [abs(dihedral(ref_points[i + 1], ref_points[i], prim_cas[i], prim_cas[i + 1]))
              for i in range(len(prim_cas) - 1)]
    alphas.append(None)

    if tag:
        p.tags[reference_axis_name] = reference_axis
        monomer_tag_name = 'alpha_angle_{0}'.format(reference_axis_name)
        for m, a in zip(p._monomers, alphas):
            m.tags[monomer_tag_name] = a
    return alphas