docs: 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