docs: def _compute_coarse_sets(self, user_sets):
          r"""Computes the sets to coarse-grain the tpt flux to.
  
          Parameters
          ----------
              (tpt_sets, A, B) with
                  tpt_sets : list of int-iterables
                  sets of states that shall be distinguished in the coarse-grained flux.
              A : int-iterable
                  set indexes in A
              B : int-iterable
                  set indexes in B
  
          Returns
          -------
          sets : list of int-iterables
              sets to compute tpt on. These sets still respect the boundary between
              A, B and the intermediate tpt states.
  
          Notes
          -----
          Given the sets that the user wants to distinguish, the
          algorithm will create additional sets if necessary
  
             * If states are missing in user_sets, they will be put into a
              separate set
             * If sets in user_sets are crossing the boundary between A, B and the
               intermediates, they will be split at these boundaries. Thus each
               set in user_sets can remain intact or be split into two or three
               subsets
  
          """
          # set-ify everything
          setA = set(self.A)
          setB = set(self.B)
          setI = set(self.I)
          raw_sets = [set(user_set) for user_set in user_sets]
  
          # anything missing? Compute all listed states
          set_all = set(range(self.nstates))
          set_all_user = []
          for user_set in raw_sets:
              set_all_user += user_set
          set_all_user = set(set_all_user)
          # ... and add all the unlisted states in a separate set
          set_rest = set_all - set_all_user
          if len(set_rest) > 0:
              raw_sets.append(set_rest)
  
          # split sets
          Asets = []
          Isets = []
          Bsets = []
          for raw_set in raw_sets:
              s = raw_set.intersection(setA)
              if len(s) > 0:
                  Asets.append(s)
              s = raw_set.intersection(setI)
              if len(s) > 0:
                  Isets.append(s)
              s = raw_set.intersection(setB)
              if len(s) > 0:
                  Bsets.append(s)
          tpt_sets = Asets + Isets + Bsets
          Aindexes = list(range(0, len(Asets)))
          Bindexes = list(range(len(Asets) + len(Isets), len(tpt_sets)))
  
          return (tpt_sets, Aindexes, Bindexes)