docs: def get_construction_table(self, fragment_list=None,
                                 use_lookup=None,
                                 perform_checks=True):
          """Create a construction table for a Zmatrix.
  
          A construction table is basically a Zmatrix without the values
          for the bond lengths, angles and dihedrals.
          It contains the whole information about which reference atoms
          are used by each atom in the Zmatrix.
  
          The absolute references in cartesian space are one of the following
          magic strings::
  
              ['origin', 'e_x', 'e_y', 'e_z']
  
          This method creates a so called "chemical" construction table,
          which makes use of the connectivity table in this molecule.
  
          Args:
              fragment_list (sequence): There are four possibilities to specify
                  the sequence of fragments:
  
                  1. A list of tuples is given. Each tuple contains the fragment
                  with its corresponding construction table in the form of::
  
                      [(frag1, c_table1), (frag2, c_table2)...]
  
                  If the construction table of a fragment is not complete,
                  the rest of each fragment's
                  construction table is calculated automatically.
  
                  2. It is possible to omit the construction tables for some
                  or all fragments as in the following example::
  
                      [(frag1, c_table1), frag2, (frag3, c_table3)...]
  
                  3. If ``self`` contains more atoms than the union over all
                  fragments, the rest of the molecule without the fragments
                  is automatically prepended using
                  :meth:`~Cartesian.get_without`::
  
                      self.get_without(fragments) + fragment_list
  
                  4. If fragment_list is ``None`` then fragmentation, etc.
                  is done automatically. The fragments are then sorted by
                  their number of atoms, in order to use the largest fragment
                  as reference for the other ones.
  
              use_lookup (bool): Use a lookup variable for
                  :meth:`~chemcoord.Cartesian.get_bonds`. The default is
                  specified in ``settings['defaults']['use_lookup']``
              perform_checks (bool): The checks for invalid references are
                  performed using :meth:`~chemcoord.Cartesian.correct_dihedral`
                  and :meth:`~chemcoord.Cartesian.correct_absolute_refs`.
  
          Returns:
              :class:`pandas.DataFrame`: Construction table
          """
          if use_lookup is None:
              use_lookup = settings['defaults']['use_lookup']
  
          if fragment_list is None:
              self.get_bonds(use_lookup=use_lookup)
              self._give_val_sorted_bond_dict(use_lookup=use_lookup)
              fragments = sorted(self.fragmentate(use_lookup=use_lookup),
                                 key=len, reverse=True)
              # During function execution the bonding situation does not change,
              # so the lookup may be used now.
              use_lookup = True
          else:
              fragments = fragment_list
  
          def prepend_missing_parts_of_molecule(fragment_list):
              for fragment in fragment_list:
                  if pd.api.types.is_list_like(fragment):
                      try:
                          full_index |= fragment[0].index
                      except NameError:
                          full_index = fragment[0].index
                  else:
                      try:
                          full_index |= fragment.index
                      except NameError:
                          full_index = fragment.index
  
              if not self.index.difference(full_index).empty:
                  missing_part = self.get_without(self.loc[full_index],
                                                  use_lookup=use_lookup)
                  fragment_list = missing_part + fragment_list
              return fragment_list
  
          fragments = prepend_missing_parts_of_molecule(fragments)
  
          if isinstance(fragments[0], tuple):
              fragment, references = fragments[0]
              full_table = fragment._get_frag_constr_table(
                  use_lookup=use_lookup, predefined_table=references)
          else:
              fragment = fragments[0]
              full_table = fragment._get_frag_constr_table(use_lookup=use_lookup)
  
          for fragment in fragments[1:]:
              finished_part = self.loc[full_table.index]
              if pd.api.types.is_list_like(fragment):
                  fragment, references = fragment
                  if len(references) < min(3, len(fragment)):
                      raise ValueError('If you specify references for a '
                                       'fragment, it has to consist of at least'
                                       'min(3, len(fragment)) rows.')
                  constr_table = fragment._get_frag_constr_table(
                      predefined_table=references, use_lookup=use_lookup)
              else:
                  i, b = fragment.get_shortest_distance(finished_part)[:2]
                  constr_table = fragment._get_frag_constr_table(
                      start_atom=i, use_lookup=use_lookup)
                  if len(full_table) == 1:
                      a, d = 'e_z', 'e_x'
                  elif len(full_table) == 2:
                      if b == full_table.index[0]:
                          a = full_table.index[1]
                      else:
                          a = full_table.index[0]
                      d = 'e_x'
                  else:
                      if b in full_table.index[:2]:
                          if b == full_table.index[0]:
                              a = full_table.index[2]
                              d = full_table.index[1]
                          else:
                              a = full_table.loc[b, 'b']
                              d = full_table.index[2]
                      else:
                          a, d = full_table.loc[b, ['b', 'a']]
  
                  if len(constr_table) >= 1:
                      constr_table.iloc[0, :] = b, a, d
                  if len(constr_table) >= 2:
                      constr_table.iloc[1, [1, 2]] = b, a
                  if len(constr_table) >= 3:
                      constr_table.iloc[2, 2] = b
  
              full_table = pd.concat([full_table, constr_table])
  
          c_table = full_table
          if perform_checks:
              c_table = self.correct_dihedral(c_table)
              c_table = self.correct_dihedral(c_table, use_lookup=use_lookup)
              c_table = self.correct_absolute_refs(c_table)
          return c_table