code: def get_all_functional_groups(self, elements=None, func_groups=None,
                                    catch_basic=True):
          
  
          heteroatoms = self.get_heteroatoms(elements=elements)
          special_cs = self.get_special_carbon(elements=elements)
          groups = self.link_marked_atoms(heteroatoms.union(special_cs))
  
          if catch_basic:
              groups += self.get_basic_functional_groups(func_groups=func_groups)
  
          return groups
docs: Identify all functional groups (or all within a certain subset) in the
          molecule, combining the methods described above.
  
          :param elements: List of elements that will qualify a carbon as special
              (if only certain functional groups are of interest).
              Default None.
          :param func_groups: List of strs representing the functional groups of
              interest. Default to None, meaning that all of the functional groups
              defined in this function will be sought.
          :param catch_basic: bool. If True, use get_basic_functional_groups and
              other methods
          :return: list of sets of ints, representing groups of connected atoms