docs: def estimate_parameters(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, 2000):
              # 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 = 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 my_bin, val in zip(local_bins, local_storage):
                  # print "bin = ", bin
                  self.dict_collect[my_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 = np.array(self.mean_contacts_upd)
  
          # self.mean_contacts_upd =
          # ndi.filters.gaussian_filter1d(self.mean_contacts_upd,
          # sigma=len(self.bins_upd) / 5.)
  
          p, self.y_estim = nuis.estimate_param_hic(
              self.mean_contacts_upd, self.bins_upd
          )
          ##########################################
          fit_param = p.x
          ##########################################
          logger.info("mean value trans = {}".format(self.mean_value_trans))
          ##########################################
          estim_max_dist = nuis.estimate_max_dist_intra(
              fit_param, self.mean_value_trans
          )
          logger.info("max distance cis/trans = {}".format(estim_max_dist))
          ##########################################
          self.param_simu = self.setup_model_parameters(
              fit_param, estim_max_dist
          )
          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)
  
          if display_graph:
              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.legend(["obs", "fit"])
              plt.show()