code: def angle_single(self, g_num, at_1, at_2, at_3):
          import numpy as np
          from .utils import safe_cast as scast
          from .utils.vector import vec_angle
          if not(-self.num_atoms <= at_1 < self.num_atoms):
              raise IndexError("Invalid index for 'at_1' ({0})".format(at_1))
          if not(-self.num_atoms <= at_2 < self.num_atoms):
              raise IndexError("Invalid index for 'at_2' ({0})".format(at_2))
          if not(-self.num_atoms <= at_3 < self.num_atoms):
              raise IndexError("Invalid index for 'at_3' ({0})".format(at_3))
          at_1 = scast(np.floor(at_1), np.int_)
          at_2 = scast(np.floor(at_2), np.int_)
          at_3 = scast(np.floor(at_3), np.int_)
          if (at_2 % self.num_atoms) == (at_1 % self.num_atoms):
              raise ValueError("'at_1' and 'at_2' must be different")
          if (at_2 % self.num_atoms) == (at_3 % self.num_atoms):
              raise ValueError("'at_2' and 'at_3' must be different")
          if (at_1 % self.num_atoms) == (at_3 % self.num_atoms):
              return 0.0
          vec_2_1 = self.displ_single(g_num, at_2, at_1)
          vec_2_3 = self.displ_single(g_num, at_2, at_3)
          angle = vec_angle(vec_2_1, vec_2_3)
          return angle