# Path: scvelo/preprocessing/neighbors.py
# def get_connectivities(
#     adata, mode="connectivities", n_neighbors=None, recurse_neighbors=False
# ):
#     if "neighbors" in adata.uns.keys():
#         C = get_neighs(adata, mode)
#         if n_neighbors is not None and n_neighbors < get_n_neighs(adata):
#             if mode == "connectivities":
#                 C = select_connectivities(C, n_neighbors)
#             else:
#                 C = select_distances(C, n_neighbors)
#         connectivities = C > 0
#         with warnings.catch_warnings():
#             warnings.simplefilter("ignore")
#             connectivities.setdiag(1)
#             if recurse_neighbors:
#                 connectivities += connectivities.dot(connectivities * 0.5)
#                 connectivities.data = np.clip(connectivities.data, 0, 1)
#             connectivities = connectivities.multiply(1.0 / connectivities.sum(1))
#         return connectivities.tocsr().astype(np.float32)
#     else:
#         return None
# 
# def get_neighs(adata, mode="distances"):
#     if hasattr(adata, "obsp") and mode in adata.obsp.keys():
#         return adata.obsp[mode]
#     elif "neighbors" in adata.uns.keys() and mode in adata.uns["neighbors"]:
#         return adata.uns["neighbors"][mode]
#     else:
#         raise ValueError("The selected mode is not valid.")
# 
# Path: scvelo/tools/utils.py
# def normalize(X):
#     with warnings.catch_warnings():
#         warnings.simplefilter("ignore")
#         if issparse(X):
#             return X.multiply(csr_matrix(1.0 / np.abs(X).sum(1)))
#         else:
#             return X / X.sum(1)


import warnings
import numpy as np
import pandas as pd
from scipy.sparse import csr_matrix, SparseEfficiencyWarning
from scipy.spatial.distance import pdist, squareform
from scvelo.preprocessing.neighbors import get_connectivities, get_neighs
from .utils import normalize
        from sklearn.neighbors import NearestNeighbors
                adata, mode="distances", n_neighbors=n_neighbors, recurse_neighbors=True
            )
        )

    if perc is not None or threshold is not None:
        if threshold is None:
            threshold = np.percentile(T.data, perc)
        T.data[T.data < threshold] = 0
        T.eliminate_zeros()

    if backward:
        T = T.T
    T = normalize(T)

    if f"X_{basis}" in adata.obsm.keys():
        dists_emb = (T > 0).multiply(squareform(pdist(adata.obsm[f"X_{basis}"])))
        scale_diffusion *= dists_emb.data.mean()

        diffusion_kernel = dists_emb.copy()
        diffusion_kernel.data = np.exp(
            -0.5 * dists_emb.data ** 2 / scale_diffusion ** 2
        )
        T = T.multiply(diffusion_kernel)  # combine velocity kernel & diffusion kernel

        if 0 < weight_diffusion < 1:  # add diffusion kernel (Brownian motion - like)
            diffusion_kernel.data = np.exp(
                -0.5 * dists_emb.data ** 2 / (scale_diffusion / 2) ** 2
            )
            T = (1 - weight_diffusion) * T + weight_diffusion * diffusion_kernel


# Path: scvelo/preprocessing/neighbors.py
# def get_connectivities(
#     adata, mode="connectivities", n_neighbors=None, recurse_neighbors=False
# ):
#     if "neighbors" in adata.uns.keys():
#         C = get_neighs(adata, mode)
#         if n_neighbors is not None and n_neighbors < get_n_neighs(adata):
#             if mode == "connectivities":
#                 C = select_connectivities(C, n_neighbors)
#             else:
#                 C = select_distances(C, n_neighbors)
#         connectivities = C > 0
#         with warnings.catch_warnings():
#             warnings.simplefilter("ignore")
#             connectivities.setdiag(1)
#             if recurse_neighbors:
#                 connectivities += connectivities.dot(connectivities * 0.5)
#                 connectivities.data = np.clip(connectivities.data, 0, 1)
#             connectivities = connectivities.multiply(1.0 / connectivities.sum(1))
#         return connectivities.tocsr().astype(np.float32)
#     else:
#         return None
# 
# def get_neighs(adata, mode="distances"):
#     if hasattr(adata, "obsp") and mode in adata.obsp.keys():
#         return adata.obsp[mode]
#     elif "neighbors" in adata.uns.keys() and mode in adata.uns["neighbors"]:
#         return adata.uns["neighbors"][mode]
#     else:
#         raise ValueError("The selected mode is not valid.")
# 
# Path: scvelo/tools/utils.py
# def normalize(X):
#     with warnings.catch_warnings():
#         warnings.simplefilter("ignore")
#         if issparse(X):
#             return X.multiply(csr_matrix(1.0 / np.abs(X).sum(1)))
#         else:
#             return X / X.sum(1)


# Path: scvelo/tools/transition_matrix.py
import warnings
import numpy as np
import pandas as pd
from scipy.sparse import csr_matrix, SparseEfficiencyWarning
from scipy.spatial.distance import pdist, squareform
from scvelo.preprocessing.neighbors import get_connectivities, get_neighs
from .utils import normalize
        from sklearn.neighbors import NearestNeighbors

                adata, mode="distances", n_neighbors=n_neighbors, recurse_neighbors=True
            )
        )

    if perc is not None or threshold is not None:
        if threshold is None:
            threshold = np.percentile(T.data, perc)
        T.data[T.data < threshold] = 0
        T.eliminate_zeros()

    if backward:
        T = T.T
    T = normalize(T)

    if f"X_{basis}" in adata.obsm.keys():
        dists_emb = (T > 0).multiply(squareform(pdist(adata.obsm[f"X_{basis}"])))
        scale_diffusion *= dists_emb.data.mean()

        diffusion_kernel = dists_emb.copy()
        diffusion_kernel.data = np.exp(
            -0.5 * dists_emb.data ** 2 / scale_diffusion ** 2
        )
        T = T.multiply(diffusion_kernel)  # combine velocity kernel & diffusion kernel

        if 0 < weight_diffusion < 1:  # add diffusion kernel (Brownian motion - like)
            diffusion_kernel.data = np.exp(
                -0.5 * dists_emb.data ** 2 / (scale_diffusion / 2) ** 2
            )
            T = (1 - weight_diffusion) * T + weight_diffusion * diffusion_kernel


        T = normalize(T)