docs: def build_kernel(self):
          """Build the KNN kernel.
  
          Build a k nearest neighbors kernel, optionally with alpha decay.
          If `precomputed` is not `None`, the appropriate steps in the kernel
          building process are skipped.
          Must return a symmetric matrix
  
          Returns
          -------
          K : kernel matrix, shape=[n_samples, n_samples]
              symmetric matrix with ones down the diagonal
              with no non-negative entries.
  
          Raises
          ------
          ValueError: if `precomputed` is not an acceptable value
          """
          if self.precomputed == "affinity":
              # already done
              # TODO: should we check that precomputed matrices look okay?
              # e.g. check the diagonal
              K = self.data_nu
          elif self.precomputed == "adjacency":
              # need to set diagonal to one to make it an affinity matrix
              K = self.data_nu
              if sparse.issparse(K) and \
                  not (isinstance(K, sparse.dok_matrix) or
                       isinstance(K, sparse.lil_matrix)):
                  K = K.tolil()
              K = set_diagonal(K, 1)
          else:
              tasklogger.log_start("affinities")
              if sparse.issparse(self.data_nu):
                  self.data_nu = self.data_nu.toarray()
              if self.precomputed == "distance":
                  pdx = self.data_nu
              elif self.precomputed is None:
                  pdx = pdist(self.data_nu, metric=self.distance)
                  if np.any(pdx == 0):
                      pdx = squareform(pdx)
                      duplicate_ids = np.array(
                          [i for i in np.argwhere(pdx == 0)
                           if i[1] > i[0]])
                      duplicate_names = ", ".join(["{} and {}".format(i[0], i[1])
                                                   for i in duplicate_ids])
                      warnings.warn(
                          "Detected zero distance between samples {}. "
                          "Consider removing duplicates to avoid errors in "
                          "downstream processing.".format(duplicate_names),
                          RuntimeWarning)
                  else:
                      pdx = squareform(pdx)
              else:
                  raise ValueError(
                      "precomputed='{}' not recognized. "
                      "Choose from ['affinity', 'adjacency', 'distance', "
                      "None]".format(self.precomputed))
              if self.bandwidth is None:
                  knn_dist = np.partition(
                      pdx, self.knn + 1, axis=1)[:, :self.knn + 1]
                  bandwidth = np.max(knn_dist, axis=1)
              elif callable(self.bandwidth):
                  bandwidth = self.bandwidth(pdx)
              else:
                  bandwidth = self.bandwidth
              bandwidth = bandwidth * self.bandwidth_scale
              pdx = (pdx.T / bandwidth).T
              K = np.exp(-1 * np.power(pdx, self.decay))
              # handle nan
              K = np.where(np.isnan(K), 1, K)
              tasklogger.log_complete("affinities")
          # truncate
          if sparse.issparse(K):
              if not (isinstance(K, sparse.csr_matrix) or
                      isinstance(K, sparse.csc_matrix) or
                      isinstance(K, sparse.bsr_matrix)):
                  K = K.tocsr()
              K.data[K.data < self.thresh] = 0
              K = K.tocoo()
              K.eliminate_zeros()
              K = K.tocsr()
          else:
              K[K < self.thresh] = 0
          return K