<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 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