docs: def estimate_parameters_rippe(
          self, max_dist_kb, size_bin_kb, display_graph
      ):
          """
          estimation by least square optimization of Rippe parameters on the
          experimental data
          :param max_dist_kb:
          :param size_bin_kb:
          """
          logger.info("estimation of the parameters of the model")
          self.bins = np.arange(
              size_bin_kb, max_dist_kb + size_bin_kb, size_bin_kb
          )
  
          self.mean_contacts = np.zeros_like(self.bins, dtype=np.float32)
          self.dict_collect = dict()
          self.gpu_vect_frags.copy_from_gpu()
          epsi = self.mean_value_trans
          for k in self.bins:
              self.dict_collect[k] = []
          for i in range(0, self.n_frags // 10):
              # print "frag i = ", i
              start = self.sparse_matrix.indptr[i]
              end = self.sparse_matrix.indptr[i + 1]
              id_j = self.sparse_matrix.indices[start:end]
              data = self.sparse_matrix.data[start:end]
  
              info_i = self.np_sub_frags_2_frags[i]
              init_id_fi = int(info_i[0])
              # pos_i = self.S_o_A_frags["pos"][init_id_fi]
              id_c_i = self.S_o_A_frags["id_c"][init_id_fi]
              s_i = (
                  self.S_o_A_frags["start_bp"][init_id_fi] / 1000.0
                  + self.np_sub_frags_2_frags[i][1]
              )
              len_kb_c_i = self.S_o_A_frags["l_cont_bp"][init_id_fi] / 1000
              # local_bins = np.arange(size_bin_kb, min(len_kb_c_i, max_dist_kb)
              # + size_bin_kb, size_bin_kb) local_storage =
              # np.zeros_like(local_bins, dtype=np.int32)
              #
              # for fj, dj in zip(id_j, data):
              #     info_j = self.np_sub_frags_2_frags[fj]
              #     init_id_fj = info_j[0]
              #     id_c_j = self.S_o_A_frags['id_c'][init_id_fj]
              #     if id_c_i == id_c_j:
              #         pos_j = self.S_o_A_frags['pos'][init_id_fj]
              #         s_j = self.S_o_A_frags['start_bp'][init_id_fj]/1000.0 +
              #         self.np_sub_frags_2_frags[fj][1]
              #         d = np.abs(s_i - s_j)
              #         if d < max_dist_kb:
              #             id_bin = d / size_bin_kb
              #             local_storage[id_bin] += dj
              #             # self.dict_collect[self.bins[id_bin]].append(dj)
              # # we have to add also the zeros
              # for bin, val in zip(local_bins, local_storage):
              #     # print "bin = ", bin
              #     self.dict_collect[bin].append(val)
  
              if size_bin_kb < len_kb_c_i:
                  # local_bins = np.arange(size_bin_kb, min(len_kb_c_i,
                  # max_dist_kb) + size_bin_kb, size_bin_kb)
                  local_bins = np.arange(
                      size_bin_kb, max_dist_kb + size_bin_kb, size_bin_kb
                  )
                  local_storage = np.zeros_like(local_bins, dtype=np.int32)
  
                  for fj, dj in zip(id_j, data):
                      info_j = self.np_sub_frags_2_frags[fj]
                      init_id_fj = int(info_j[0])
                      id_c_j = self.S_o_A_frags["id_c"][init_id_fj]
                      if id_c_i == id_c_j:
                          # pos_j = self.S_o_A_frags["pos"][init_id_fj]
                          s_j = (
                              self.S_o_A_frags["start_bp"][init_id_fj] / 1000.0
                              + self.np_sub_frags_2_frags[fj][1]
                          )
                          d = np.abs(s_i - s_j)
                          if d < max_dist_kb:
                              id_bin = int(d / size_bin_kb)
                              local_storage[id_bin] += dj
                              # self.dict_collect[self.bins[id_bin]].append(dj)
                  # we have to add also the zeros
                  for bin, val in zip(local_bins, local_storage):
                      # print "bin = ", bin
                      self.dict_collect[bin].append(val)
  
          for id_bin in range(0, len(self.bins)):
              k = self.bins[id_bin]
              self.mean_contacts[id_bin] = np.mean(self.dict_collect[k])
  
          for id_bin in range(0, len(self.bins)):
              k = self.bins[id_bin]
              tmp = np.mean(self.dict_collect[k])
              if np.isnan(tmp) or tmp == 0:
                  # if np.isnan(tmp):
                  # if np.isnan(tmp):
                  #     print "removing nan"
                  self.mean_contacts[id_bin] = np.nan
              else:
                  self.mean_contacts[id_bin] = tmp + epsi
  
          self.mean_contacts_upd = []
          self.bins_upd = []
  
          for count, ele in zip(self.mean_contacts, self.bins):
              if not np.isnan(count):
                  self.bins_upd.append(ele)
                  self.mean_contacts_upd.append(count)
  
          self.bins_upd = np.array(self.bins_upd)
          # self.mean_contacts_upd.sort()
          # self.mean_contacts_upd.reverse()
          self.mean_contacts_upd = np.array(self.mean_contacts_upd)
  
          # self.mean_contacts_upd =
          # ndi.filters.gaussian_filter1d(self.mean_contacts_upd,
          # sigma=len(self.bins_upd) / 5.)
  
          # print "size mean contacts vector = ", self.mean_contacts_upd.shape
          # print "mean contacts vector = ", self.mean_contacts_upd
  
          p, self.y_estim = opti.estimate_param_rippe(
              self.mean_contacts_upd, self.bins_upd
          )
          ##########################################
          logger.info("p from estimate parameters  = {}".format(p))
          # p = list(p[0])
          # p[3] = 2
          # p = tuple(p)
          ##########################################
          fit_param = p
          logger.info("mean value trans = {}".format(self.mean_value_trans))
          ##########################################
          logger.info("BEWARE!!! : I will lower mean value trans  !!!")
          self.mean_value_trans = self.mean_value_trans / 10.0
          ##########################################
  
          estim_max_dist = opti.estimate_max_dist_intra(
              fit_param, self.mean_value_trans
          )
          logger.info("estimate max dist cis trans = {}".format(estim_max_dist))
          self.param_simu = self.setup_rippe_parameters(
              fit_param, estim_max_dist
          )
          self.param_simu_test = self.param_simu
          self.gpu_param_simu = cuda.mem_alloc(self.param_simu.nbytes)
          self.gpu_param_simu_test = cuda.mem_alloc(self.param_simu.nbytes)
  
          cuda.memcpy_htod(self.gpu_param_simu, self.param_simu)
          cuda.memcpy_htod(self.gpu_param_simu_test, self.param_simu_test)
          display_graph = False
          if display_graph:
              plt.figure()
              plt.loglog(self.bins_upd, self.mean_contacts_upd, "-*b")
              plt.loglog(self.bins_upd, self.y_estim, "-*r")
              plt.xlabel("genomic distance (kb)")
              plt.ylabel("frequency of contact")
              plt.title(
                  r"$\mathrm{Frequency\ of\ contact\ versus\ genomic\ distance"
                  " \(data\ tricho test):}\ slope=%.3f,\ max\ cis\ distance(kb)"
                  "=%.3f\ d=%.3f\ scale\ factor=%.3f\ $"
                  % (
                      self.param_simu["slope"],
                      estim_max_dist,
                      self.param_simu["d"],
                      self.param_simu["fact"],
                  )
              )
              plt.legend(["obs", "fit"])
              plt.savefig()
              plt.close()
  
          self.eval_likelihood_init()