Skip to content

Commit

Permalink
Merge pull request #22 from YosefLab/sparse_distances
Browse files Browse the repository at this point in the history
Sparse distances
  • Loading branch information
adamgayoso committed May 8, 2022
2 parents ae261ae + b3da536 commit 6000265
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 17 deletions.
3 changes: 0 additions & 3 deletions docs/source/hotspot.rst
@@ -1,8 +1,5 @@
Function Reference
******************


Where does this stuff get included?

.. autoclass:: hotspot.Hotspot
:members:
8 changes: 1 addition & 7 deletions hotspot/hotspot.py
Expand Up @@ -90,12 +90,6 @@ def __init__(
"Both `distances_obsp_key` and `tree` provided - only one of these should be provided."
)

if distances is not None:
assert not issparse(distances)
distances = pd.DataFrame(
distances, index=adata.obs_names, columns=adata.obs_names
)

if latent is not None:
latent = pd.DataFrame(latent, index=adata.obs_names)

Expand Down Expand Up @@ -260,7 +254,7 @@ def legacy_init(
input_adata.obs[tc_key] = umi_counts.values
dkey = "distances"
if distances is not None:
input_adata.obsp[dkey] = np.asarray(distances)
input_adata.obsp[dkey] = distances
dist_input = True
else:
dist_input = False
Expand Down
21 changes: 16 additions & 5 deletions hotspot/knn.py
Expand Up @@ -5,6 +5,7 @@
from numba import jit
from tqdm import tqdm
from pynndescent import NNDescent
import warnings


def neighbors_and_weights(data, n_neighbors=30, neighborhood_factor=3, approx_neighbors=True):
Expand All @@ -26,8 +27,10 @@ def neighbors_and_weights(data, n_neighbors=30, neighborhood_factor=3, approx_ne
coords = data.values

if approx_neighbors:
index = NNDescent(coords, n_neighbors=n_neighbors)
# pynndescent first neighbor is self, unlike sklearn
index = NNDescent(coords, n_neighbors=n_neighbors + 1)
ind, dist = index.neighbor_graph
ind, dist = ind[:, 1:], dist[:, 1:]
else:
nbrs = NearestNeighbors(n_neighbors=n_neighbors,
algorithm="ball_tree").fit(coords)
Expand All @@ -45,7 +48,7 @@ def neighbors_and_weights(data, n_neighbors=30, neighborhood_factor=3, approx_ne


def neighbors_and_weights_from_distances(
distances, n_neighbors=30, neighborhood_factor=3
distances, cell_index, n_neighbors=30, neighborhood_factor=3
):
"""
Computes nearest neighbors and associated weights using
Expand All @@ -61,15 +64,23 @@ def neighbors_and_weights_from_distances(
weights: pandas.Dataframe num_cells x n_neighbors
"""
if isinstance(distances, pd.DataFrame):
distances = distances.values

nbrs = NearestNeighbors(
n_neighbors=n_neighbors, algorithm="brute", metric="precomputed"
).fit(distances.values)
dist, ind = nbrs.kneighbors()
).fit(distances)
try:
dist, ind = nbrs.kneighbors()
# already is a neighbors graph
except ValueError:
nn = np.asarray((distances[0] > 0).sum())
warnings.warn(f"Provided cell-cell distance graph is likely a {nn}-neighbors graph. Using {nn} precomputed neighbors.")
dist, ind = nbrs.kneighbors(n_neighbors=nn-1)

weights = compute_weights(dist, neighborhood_factor=neighborhood_factor)

ind = pd.DataFrame(ind, index=distances.index)
ind = pd.DataFrame(ind, index=cell_index)
neighbors = ind
weights = pd.DataFrame(
weights, index=neighbors.index, columns=neighbors.columns
Expand Down
5 changes: 3 additions & 2 deletions pyproject.toml
Expand Up @@ -29,7 +29,7 @@ packages = [
{include = "hotspot"},
]
readme = "README.md"
version = "1.1"
version = "1.1.1"

[tool.poetry.dependencies]
pytest = {version = ">=5.0", optional = true}
Expand All @@ -50,10 +50,11 @@ sphinx-book-theme = {version= ">=0.2.0", optional = true}
nbsphinx = {version = "*", optional = true}
sphinx = {version = ">=4.1", optional = true}
ipython = {version = "*", optional = true}
scanpy = {version = "*", optional = true}


[tool.poetry.extras]
test = ["pytest"]
test = ["pytest", "scanpy"]
docs=["sphinx-book-theme", "nbsphinx", "sphinx>", "ipython"]

[tool.poetry.dev-dependencies]
Expand Down
13 changes: 13 additions & 0 deletions tests/test_validations.py
Expand Up @@ -4,6 +4,7 @@
from hotspot import Hotspot
import anndata
import pytest
import scanpy as sc

from scipy.sparse import csc_matrix

Expand Down Expand Up @@ -73,6 +74,18 @@ def test_models():
assert isinstance(hs.module_scores, pd.DataFrame)
assert (hs.module_scores.index == gene_exp.columns).all()

# test precomputed distance matrix
sc.pp.neighbors(adata, use_rep="latent", n_neighbors=30)
hs = Hotspot(
adata,
model="normal",
umi_counts_obs_key="umi_counts",
layer_key="sparse",
distances_obsp_key="distances"
)
hs.create_knn_graph(False, n_neighbors=30)
hs.compute_autocorrelations()


def test_filter_genes():
"""
Expand Down

0 comments on commit 6000265

Please sign in to comment.