docs: def nmf_init(data, clusters, k, init='enhanced'):
      """
      Generates initial M and W given a data set and an array of cluster labels.
  
      There are 3 options for init:
          enhanced - uses EIn-NMF from Gong 2013
          basic - uses means for M, assigns W such that the chosen cluster for a given cell has value 0.75 and all others have 0.25/(k-1).
          nmf - uses means for M, and assigns W using the NMF objective while holding M constant.
      """
      init_m = np.zeros((data.shape[0], k))
      if sparse.issparse(data):
          for i in range(k):
              if data[:,clusters==i].shape[1]==0:
                  point = np.random.randint(0, data.shape[1])
                  init_m[:,i] = data[:,point].toarray().flatten()
              else:
                  init_m[:,i] = np.array(data[:,clusters==i].mean(1)).flatten()
      else:
          for i in range(k):
              if data[:,clusters==i].shape[1]==0:
                  point = np.random.randint(0, data.shape[1])
                  init_m[:,i] = data[:,point].flatten()
              else:
                  init_m[:,i] = data[:,clusters==i].mean(1)
      init_w = np.zeros((k, data.shape[1]))
      if init == 'enhanced':
          distances = np.zeros((k, data.shape[1]))
          for i in range(k):
              for j in range(data.shape[1]):
                  distances[i,j] = np.sqrt(((data[:,j] - init_m[:,i])**2).sum())
          for i in range(k):
              for j in range(data.shape[1]):
                  init_w[i,j] = 1/((distances[:,j]/distances[i,j])**(-2)).sum()
      elif init == 'basic':
          init_w = initialize_from_assignments(clusters, k)
      elif init == 'nmf':
          init_w_, _, n_iter = non_negative_factorization(data.T, n_components=k, init='custom', update_W=False, W=init_m.T)
          init_w = init_w_.T
      return init_m, init_w