docs: def get_tiltplanes(self, sequence):
          '''
          Extract tilting planes basing on distance map
          '''
          tilting_planes = []
          distance_map = []
  
          for i in range(1, len(sequence)):
              distance_map.append([ sequence[i], self.virtual_atoms.get_distance( sequence[0], sequence[i] ) ])
  
          distance_map = sorted(distance_map, key=lambda x: x[1])
  
          if len(distance_map) == 4:
              # surface edge case
              # semi-octahedron at surface edge has only one tilting plane to consider
              sorted_dist = [i[0] for i in distance_map]
              if distance_map[-1][1] - distance_map[-2][1] < 0.5:
                  # 1st case: max diff < 0.5 Angstrom,
                  # meaning all distances to reference atom are similar,
                  # therefore the reference atom is above the searched plane
                  # and the searched plane consists of other atoms
                  tilting_planes.append( [ i[0] for i in distance_map ] )
              else:
                  # 2nd case: reference atom belongs to the searched plane,
                  # procedure needs to be repeated with the next atom as reference atom
                  candidates = [sequence[0], sorted_dist[-1]]
                  next_distance_map = []
                  next_distance_map.append([ sorted_dist[1], self.virtual_atoms.get_distance( sorted_dist[0], sorted_dist[1] ) ])
                  next_distance_map.append([ sorted_dist[2], self.virtual_atoms.get_distance( sorted_dist[0], sorted_dist[2] ) ])
                  next_distance_map = sorted(next_distance_map, key=lambda x: x[1])
                  next_sorted_dist = [i[0] for i in next_distance_map]
  
                  # the next reference atom is taken above the plane (distances are similar)
                  if next_distance_map[1][1] - next_distance_map[0][1] < 0.5: candidates.extend([ next_sorted_dist[0], next_sorted_dist[1] ])
  
                  # the next reference atom is taken in the plane (distances are different)
                  else: candidates.extend([ sorted_dist[0], next_sorted_dist[1] ])
                  tilting_planes.append(candidates)
  
          elif len(distance_map) == 5:
              # full octahedron case
              # full octahedron has 3 different tilting planes (perpendicular in ideal case)
              sorted_dist = [i[0] for i in distance_map]
  
              # 1st plane is found as:
              first_plane = sorted_dist[0:4]
              tilting_planes.append(first_plane)
              distance_map_first_plane = []
              for i in range(1, 4):
                  distance_map_first_plane.append([ first_plane[i], self.virtual_atoms.get_distance( first_plane[0], first_plane[i] ) ])
              distance_map_first_plane = sorted(distance_map_first_plane, key=lambda x: x[1])
              sorted_first_plane = [i[0] for i in distance_map_first_plane]
  
              # 2nd and 3rd planes are found as:
              tilting_planes.append([ sequence[0], sorted_dist[4], first_plane[0], sorted_first_plane[2] ])
              tilting_planes.append([ sequence[0], sorted_dist[4], sorted_first_plane[0], sorted_first_plane[1] ])
  
          # filter planes by Z according to octahedral spatial compound
          filtered = list(filter(lambda x:
              abs(self.virtual_atoms[ x[0] ].z - self.virtual_atoms[ x[1] ].z) < self.OCTAHEDRON_ATOMS_Z_DIFFERENCE and \
              abs(self.virtual_atoms[ x[1] ].z - self.virtual_atoms[ x[2] ].z) < self.OCTAHEDRON_ATOMS_Z_DIFFERENCE and \
              abs(self.virtual_atoms[ x[2] ].z - self.virtual_atoms[ x[3] ].z) < self.OCTAHEDRON_ATOMS_Z_DIFFERENCE,
              tilting_planes
          )) # Py3
          if len(filtered): tilting_planes = filtered
  
          return tilting_planes