Calculates the dihedral angles for a list of backbone atoms.

    Parameters
    ----------
    residues : [ampal.Residue]
        List of `Residue` objects.

    Returns
    -------
    torsion_angles : (float, float, float)
        One triple for each residue, containing torsion angles in
        the range [-pi, pi].
            [0] omega
            [1] phi
            [2] psi
        For the first residue, omega and phi are not defined. For
        the final residue, psi is not defined.

    Raises
    ------
    ValueError
        If the number of input residues is less than 2.

def measure_torsion_angles(residues):
    """Calculates the dihedral angles for a list of backbone atoms.

    Parameters
    ----------
    residues : [ampal.Residue]
        List of `Residue` objects.

    Returns
    -------
    torsion_angles : (float, float, float)
        One triple for each residue, containing torsion angles in
        the range [-pi, pi].
            [0] omega
            [1] phi
            [2] psi
        For the first residue, omega and phi are not defined. For
        the final residue, psi is not defined.

    Raises
    ------
    ValueError
        If the number of input residues is less than 2.
    """
    if len(residues) < 2:
        torsion_angles = [(None, None, None)] * len(residues)
    else:
        torsion_angles = []
        for i in range(len(residues)):
            if i == 0:
                res1 = residues[i]
                res2 = residues[i + 1]
                omega = None
                phi = None
                try:
                    psi = dihedral(
                        res1['N']._vector, res1['CA']._vector,
                        res1['C']._vector, res2['N']._vector)
                except KeyError as k:
                    print("{0} atom missing - can't assign psi".format(k))
                    psi = None
                torsion_angles.append((omega, phi, psi))
            elif i == len(residues) - 1:
                res1 = residues[i - 1]
                res2 = residues[i]
                try:
                    omega = dihedral(
                        res1['CA']._vector, res1['C']._vector,
                        res2['N']._vector, res2['CA']._vector)
                except KeyError as k:
                    print("{0} atom missing - can't assign omega".format(k))
                    omega = None
                try:
                    phi = dihedral(
                        res1['C']._vector, res2['N']._vector,
                        res2['CA']._vector, res2['C']._vector)
                except KeyError as k:
                    print("{0} atom missing - can't assign phi".format(k))
                    phi = None
                psi = None
                torsion_angles.append((omega, phi, psi))
            else:
                res1 = residues[i - 1]
                res2 = residues[i]
                res3 = residues[i + 1]
                try:
                    omega = dihedral(
                        res1['CA']._vector, res1['C']._vector,
                        res2['N']._vector, res2['CA']._vector)
                except KeyError as k:
                    print("{0} atom missing - can't assign omega".format(k))
                    omega = None
                try:
                    phi = dihedral(
                        res1['C']._vector, res2['N']._vector,
                        res2['CA']._vector, res2['C']._vector)
                except KeyError as k:
                    print("{0} atom missing - can't assign phi".format(k))
                    phi = None
                try:
                    psi = dihedral(
                        res2['N']._vector, res2['CA']._vector,
                        res2['C']._vector, res3['N']._vector)
                except KeyError as k:
                    print("{0} atom missing - can't assign psi".format(k))
                    psi = None
                torsion_angles.append((omega, phi, psi))
    return torsion_angles