<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def crick_angles(p, reference_axis, tag=True, reference_axis_name='ref_axis'):
 """Returns the Crick angle for each CA atom in the `Polymer`. Notes ----- The final value is in the returned list is `None`, since the angle calculation requires pairs of points on both the primitive and reference_axis. 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 `Polymer` with the reference axis coordinates and each Residue with its Crick angle. Crick 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 ------- cr_angles : list(float) The crick angles in degrees for each CA atom of the Polymer. 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
    p_cas = p.get_reference_coords()
    ref_points = reference_axis.coordinates
    cr_angles = [
        dihedral(ref_points[i], prim_cas[i], prim_cas[i + 1], p_cas[i])
        for i in range(len(prim_cas) - 1)]
    cr_angles.append(None)

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