class_docstr: StreamConvSCCS provides parallel solving for k_fold and bootstrap ConvSCCS
     using a threadpool. Everything needed is precalculated and handed of to C++
  
  Parameters
  ----------
  threads : integer, number of threads for the thread pool,
   for kfold must be < n_folds * n_cv_iter
   for bootstrap must be <= rep
code: def fit_kfold_cv(
      self,
      features,
      labels,
      censoring,
      C_tv_range: tuple = (),
      C_group_l1_range: tuple = (),
      logscale=True,
      n_cv_iter: int = 30,
      n_folds: int = 3,
      shuffle: bool = True,
      confidence_intervals: bool = False,
      n_samples_bootstrap: int = 100,
      confidence_level: float = 0.95,
  ):
      p_features, p_labels, p_censoring = self._prefit(
          features, labels, censoring
      )
      # split the data with stratified KFold
      kf = StratifiedKFold(n_folds, shuffle, self.random_state)
      labels_interval = np.nonzero(p_labels)[1]
  
      # Training loop
      model_global_parameters = {
          "n_intervals": self.n_intervals,
          "n_lags": self.n_lags,
          "n_features": self.n_features,
      }
      cv_tracker = CrossValidationTracker(model_global_parameters)
      (
          C_tv_generator,
          C_group_l1_generator,
      ) = self._construct_generator_obj(
          C_tv_range, C_group_l1_range, logscale
      )
  
      model_list, coeffs_list = ([] for i in range(2))  # 2 on the left
      for i in range(n_cv_iter * n_folds):
          model_list.append(self._construct_model_obj())
          coeffs_list.append(np.zeros(self.n_coeffs))
  
      if (n_cv_iter * n_folds) < self.threads:
          self.threads = n_cv_iter * n_folds
      self._set("_fitted", True)
      C_s, score_vals, indexes = ([] for i in range(3))  # 3 on the left
      for cv_iter in range(n_cv_iter):
          C_s.append(
              (C_tv_generator.rvs(1)[0], C_group_l1_generator.rvs(1)[0])
          )
          indexes.append(list(kf.split(p_features, labels_interval)))
          for n_job in range(n_folds):
              index = n_job + (cv_iter * n_folds)
              train_index, test_index = indexes[-1][n_job]
              train = itemgetter(*train_index.tolist())
              test = itemgetter(*test_index.tolist())
              X_train, X_test = list(train(p_features)), list(
                  test(p_features)
              )
              y_train, y_test = list(train(p_labels)), list(
                  test(p_labels)
              )
              censoring_train, censoring_test = (
                  p_censoring[train_index],
                  p_censoring[test_index],
              )
              model_list[index].fit(X_train, y_train, censoring_train)
              score_vals.append((X_test, y_test, censoring_test))
  
      minimizers = self._multi_fit(
          model_list, coeffs_list, C_s, n_folds
      )
      for cv_iter in range(n_cv_iter):
          train_scores, test_scores = (
              [] for i in range(2)
          )  # 2 on the left
          for n_job in range(n_folds):
              index = n_job + (cv_iter * n_folds)
              train_scores.append(
                  model_list[index].loss(minimizers[index])
              )
              X_test, y_test, censoring_test = score_vals[index]
              test_scores.append(
                  self._construct_model_obj()
                  .fit(X_test, y_test, censoring_test)
                  .loss(minimizers[index])
              )
          self.C_tv, self.C_group_l1 = C_s[cv_iter]
          cv_tracker.log_cv_iteration(
              self.C_tv,
              self.C_group_l1,
              np.array(train_scores),
              np.array(test_scores),
          )
  
      # refit best model on all the data
      best_parameters = cv_tracker.find_best_params()
      self.C_tv = best_parameters["C_tv"]
      self.C_group_l1 = best_parameters["C_group_l1"]
      self._set("_coeffs", np.zeros(self.n_coeffs))
      self._model_obj.fit(p_features, p_labels, p_censoring)
      coeffs, bootstrap_ci = self._postfit(
          p_features,
          p_labels,
          p_censoring,
          True,
          confidence_intervals,
          n_samples_bootstrap,
          confidence_level,
      )
      cv_tracker.log_best_model(
          self.C_tv,
          self.C_group_l1,
          self._coeffs.tolist(),
          self.score(),
          self.confidence_intervals,
      )
      return self.coeffs, cv_tracker
  
imports: from tick.survival.convolutional_sccs import *
label_desc: Use image node_id 3 for calling the StreamConvSCCS obj's underlying member method code with example usage: obj.fit_kfold_cv(features, labels, censoring, C_tv_range, C_group_l1_range, logscale, n_cv_iter, n_folds, shuffle, confidence_intervals, n_samples_bootstrap, confidence_level) and returns: self,  cv_tracker