code: def fill_sampling(slice_list, N):
      
      A = [len(s.inliers) for s in slice_list]
      N_max = np.sum(A)
      if N > N_max:
          raise ValueError("Tried to draw {:d} samples from a pool of only {:d} items".format(N, N_max))
      
      samples_from = np.zeros((len(A),), dtype='int') # Number of samples to draw from each group
  
      remaining = N
      while remaining > 0:
          remaining_groups = np.flatnonzero(samples_from - np.array(A))
          
          if remaining < len(remaining_groups):
              np.random.shuffle(remaining_groups)
              for g in remaining_groups[:remaining]:
                  samples_from[g] += 1
          else:
              # Give each group the allowed number of samples. Constrain to their max size.
              to_each = max(1, int(remaining / len(remaining_groups)))
              samples_from = np.min(np.vstack((samples_from + to_each, A)), axis=0)
          
          # Update remaining count
          remaining = int(N - np.sum(samples_from))
      if not remaining == 0:
          raise ValueError("Still {:d} samples left! This is an error in the selection.")
  
      # Construct index list of selected samples
      samples = []
      for s, a, n in zip(slice_list, A, samples_from):
          if a == n:
              samples.append(np.array(s.inliers)) # all
          elif a == 0:
              samples.append(np.arange([]))
          else:
              chosen = np.random.choice(s.inliers, n, replace=False)
              samples.append(np.array(chosen))
      return samples
docs: Given a list of slices, draw N samples such that each slice contributes as much as possible
  
      Parameters
      --------------------------
      slice_list : list of Slice
          List of slices
      N : int
          Number of samples to draw