def louvain_clustering(self, X=None, res=<NUM_LIT:1>, method='<STR_LIT>'):
if X is None:<EOL><INDENT>X = self.adata.uns['<STR_LIT>']['<STR_LIT>']<EOL>save = True<EOL><DEDENT>else:<EOL><INDENT>if not sp.isspmatrix_csr(X):<EOL><INDENT>X = sp.csr_matrix(X)<EOL><DEDENT>save = False<EOL><DEDENT>import igraph as ig<EOL>import louvain<EOL>adjacency = sparse_knn(X.dot(X.T) / self.k, self.k).tocsr()<EOL>sources, targets = adjacency.nonzero()<EOL>weights = adjacency[sources, targets]<EOL>if isinstance(weights, np.matrix):<EOL><INDENT>weights = weights.A1<EOL><DEDENT>g = ig.Graph(directed=True)<EOL>g.add_vertices(adjacency.shape[<NUM_LIT:0>])<EOL>g.add_edges(list(zip(sources, targets)))<EOL>try:<EOL><INDENT>g.es['<STR_LIT>'] = weights<EOL><DEDENT>except BaseException:<EOL><INDENT>pass<EOL><DEDENT>if method == '<STR_LIT>':<EOL><INDENT>cl = louvain.find_partition(g, louvain.SignificanceVertexPartition)<EOL><DEDENT>else:<EOL><INDENT>cl = louvain.find_partition(<EOL>g,<EOL>louvain.RBConfigurationVertexPartition,<EOL>resolution_parameter=res)<EOL><DEDENT>if save:<EOL><INDENT>self.adata.obs['<STR_LIT>'] = pd.Categorical(np.array(cl.membership))<EOL><DEDENT>else:<EOL><INDENT>return np.array(cl.membership)<EOL><DEDENT>
Runs Louvain clustering using the vtraag implementation. Assumes
        that 'louvain' optional dependency is installed.

        Parameters
        ----------
        res - float, optional, default 1
            The resolution parameter which tunes the number of clusters Louvain
            finds.

        method - str, optional, default 'modularity'
            Can be 'modularity' or 'significance', which are two different
            optimizing funcitons in the Louvain algorithm.