def kmeans_pp(data, k, centers=None):
<EOL>genes, cells = data.shape<EOL>if sparse.issparse(data) and not sparse.isspmatrix_csc(data):<EOL><INDENT>data = sparse.csc_matrix(data)<EOL><DEDENT>num_known_centers = <NUM_LIT:0><EOL>if centers is None:<EOL><INDENT>centers = np.zeros((genes, k))<EOL><DEDENT>else:<EOL><INDENT>num_known_centers = centers.shape[<NUM_LIT:1>]<EOL>centers = np.concatenate((centers, np.zeros((genes, k-num_known_centers))), <NUM_LIT:1>)<EOL><DEDENT>distances = np.zeros((cells, k))<EOL>distances[:] = np.inf<EOL>if num_known_centers == <NUM_LIT:0>:<EOL><INDENT>init = np.random.randint(<NUM_LIT:0>, cells)<EOL>if sparse.issparse(data):<EOL><INDENT>centers[:,<NUM_LIT:0>] = data[:, init].toarray().flatten()<EOL><DEDENT>else:<EOL><INDENT>centers[:,<NUM_LIT:0>] = data[:, init]<EOL><DEDENT>num_known_centers+=<NUM_LIT:1><EOL><DEDENT>available_cells = list(range(cells))<EOL>for c in range(num_known_centers, k):<EOL><INDENT>c2 = c-<NUM_LIT:1><EOL>if sparse.issparse(data):<EOL><INDENT>lls = poisson_ll(data, centers[:,c2:c2+<NUM_LIT:1>]).flatten()<EOL>distances[:,c2] = <NUM_LIT:1> + lls.max() - lls<EOL>distances[:,c2] /= distances[:,c2].max()<EOL><DEDENT>else:<EOL><INDENT>for cell in range(cells):<EOL><INDENT>distances[cell, c2] = poisson_dist(data[:,cell], centers[:,c2])<EOL><DEDENT><DEDENT>min_distances = np.min(distances, <NUM_LIT:1>)<EOL>min_distances = min_distances**<NUM_LIT:2><EOL>min_distances = min_distances[available_cells]<EOL>min_dist = np.random.choice(available_cells,<EOL>p=min_distances/min_distances.sum())<EOL>available_cells.pop(available_cells.index(min_dist))<EOL>if sparse.issparse(data):<EOL><INDENT>centers[:,c] = data[:, min_dist].toarray().flatten()<EOL><DEDENT>else:<EOL><INDENT>centers[:,c] = data[:, min_dist]<EOL><DEDENT><DEDENT>lls = poisson_ll(data, centers)<EOL>new_assignments = np.argmax(lls, <NUM_LIT:1>)<EOL>centers[centers==<NUM_LIT:0.0>] = eps<EOL>return centers, new_assignments<EOL>
Generates kmeans++ initial centers.

Args:
    data (array): A 2d array- genes x cells
    k (int): Number of clusters
    centers (array, optional): if provided, these are one or more known cluster centers. 2d array of genes x number of centers (<=k).

Returns:
    centers - a genes x k array of cluster means.
    assignments - a cells x 1 array of cluster assignments